PM / OPP: RCU reclaim
synchronize_rcu() blocks the caller of opp_enable/disbale for a complete grace period. This blocking duration prevents any intensive use of the functions. Replace synchronize_rcu() by call_rcu() which will call our function for freeing the old opp element. The duration of opp_enable() and opp_disable() will be no more dependant of the grace period. Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org> Reviewed-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
77b67063bb
commit
dde8437d06
1 changed files with 14 additions and 5 deletions
|
@ -65,6 +65,7 @@ struct opp {
|
|||
unsigned long u_volt;
|
||||
|
||||
struct device_opp *dev_opp;
|
||||
struct rcu_head head;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -441,6 +442,17 @@ int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* opp_free_rcu() - helper to clear the struct opp when grace period has
|
||||
* elapsed without blocking the the caller of opp_set_availability
|
||||
*/
|
||||
static void opp_free_rcu(struct rcu_head *head)
|
||||
{
|
||||
struct opp *opp = container_of(head, struct opp, head);
|
||||
|
||||
kfree(opp);
|
||||
}
|
||||
|
||||
/**
|
||||
* opp_set_availability() - helper to set the availability of an opp
|
||||
* @dev: device for which we do this operation
|
||||
|
@ -512,7 +524,7 @@ static int opp_set_availability(struct device *dev, unsigned long freq,
|
|||
|
||||
list_replace_rcu(&opp->node, &new_opp->node);
|
||||
mutex_unlock(&dev_opp_list_lock);
|
||||
synchronize_rcu();
|
||||
call_rcu(&opp->head, opp_free_rcu);
|
||||
|
||||
/* Notify the change of the OPP availability */
|
||||
if (availability_req)
|
||||
|
@ -522,13 +534,10 @@ static int opp_set_availability(struct device *dev, unsigned long freq,
|
|||
srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_DISABLE,
|
||||
new_opp);
|
||||
|
||||
/* clean up old opp */
|
||||
new_opp = opp;
|
||||
goto out;
|
||||
return 0;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&dev_opp_list_lock);
|
||||
out:
|
||||
kfree(new_opp);
|
||||
return r;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue