[PATCH] cpufreq: make the transition_notifier chain use SRCU
This patch (as762) changes the cpufreq_transition_notifier_list from a blocking_notifier_head to an srcu_notifier_head. This will prevent errors caused attempting to call down_read() to access the notifier chain at a time when interrupts must remain disabled, during system suspend. It's not clear to me whether this is really necessary; perhaps the chain could be made into an atomic_notifier. However a couple of the callout routines do use blocking operations, so this approach seems safer. The head of the notifier chain needs to be initialized before use; this is done by an __init routine at core_initcall time. If this turns out not to be a good choice, it can easily be changed. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Cc: "Paul E. McKenney" <paulmck@us.ibm.com> Cc: Jesse Brandeburg <jesse.brandeburg@gmail.com> Cc: Dave Jones <davej@codemonkey.org.uk> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
e6a92013ba
commit
b4dfdbb3c7
@ -52,8 +52,14 @@ static void handle_update(void *data);
|
|||||||
* The mutex locks both lists.
|
* The mutex locks both lists.
|
||||||
*/
|
*/
|
||||||
static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list);
|
static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list);
|
||||||
static BLOCKING_NOTIFIER_HEAD(cpufreq_transition_notifier_list);
|
static struct srcu_notifier_head cpufreq_transition_notifier_list;
|
||||||
|
|
||||||
|
static int __init init_cpufreq_transition_notifier_list(void)
|
||||||
|
{
|
||||||
|
srcu_init_notifier_head(&cpufreq_transition_notifier_list);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
core_initcall(init_cpufreq_transition_notifier_list);
|
||||||
|
|
||||||
static LIST_HEAD(cpufreq_governor_list);
|
static LIST_HEAD(cpufreq_governor_list);
|
||||||
static DEFINE_MUTEX (cpufreq_governor_mutex);
|
static DEFINE_MUTEX (cpufreq_governor_mutex);
|
||||||
@ -262,14 +268,14 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
|
|||||||
freqs->old = policy->cur;
|
freqs->old = policy->cur;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
blocking_notifier_call_chain(&cpufreq_transition_notifier_list,
|
srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
|
||||||
CPUFREQ_PRECHANGE, freqs);
|
CPUFREQ_PRECHANGE, freqs);
|
||||||
adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
|
adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CPUFREQ_POSTCHANGE:
|
case CPUFREQ_POSTCHANGE:
|
||||||
adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
|
adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
|
||||||
blocking_notifier_call_chain(&cpufreq_transition_notifier_list,
|
srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
|
||||||
CPUFREQ_POSTCHANGE, freqs);
|
CPUFREQ_POSTCHANGE, freqs);
|
||||||
if (likely(policy) && likely(policy->cpu == freqs->cpu))
|
if (likely(policy) && likely(policy->cpu == freqs->cpu))
|
||||||
policy->cur = freqs->new;
|
policy->cur = freqs->new;
|
||||||
@ -1049,7 +1055,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)
|
|||||||
freqs.old = cpu_policy->cur;
|
freqs.old = cpu_policy->cur;
|
||||||
freqs.new = cur_freq;
|
freqs.new = cur_freq;
|
||||||
|
|
||||||
blocking_notifier_call_chain(&cpufreq_transition_notifier_list,
|
srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
|
||||||
CPUFREQ_SUSPENDCHANGE, &freqs);
|
CPUFREQ_SUSPENDCHANGE, &freqs);
|
||||||
adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs);
|
adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs);
|
||||||
|
|
||||||
@ -1130,7 +1136,7 @@ static int cpufreq_resume(struct sys_device * sysdev)
|
|||||||
freqs.old = cpu_policy->cur;
|
freqs.old = cpu_policy->cur;
|
||||||
freqs.new = cur_freq;
|
freqs.new = cur_freq;
|
||||||
|
|
||||||
blocking_notifier_call_chain(
|
srcu_notifier_call_chain(
|
||||||
&cpufreq_transition_notifier_list,
|
&cpufreq_transition_notifier_list,
|
||||||
CPUFREQ_RESUMECHANGE, &freqs);
|
CPUFREQ_RESUMECHANGE, &freqs);
|
||||||
adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs);
|
adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs);
|
||||||
@ -1176,7 +1182,7 @@ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
|
|||||||
|
|
||||||
switch (list) {
|
switch (list) {
|
||||||
case CPUFREQ_TRANSITION_NOTIFIER:
|
case CPUFREQ_TRANSITION_NOTIFIER:
|
||||||
ret = blocking_notifier_chain_register(
|
ret = srcu_notifier_chain_register(
|
||||||
&cpufreq_transition_notifier_list, nb);
|
&cpufreq_transition_notifier_list, nb);
|
||||||
break;
|
break;
|
||||||
case CPUFREQ_POLICY_NOTIFIER:
|
case CPUFREQ_POLICY_NOTIFIER:
|
||||||
@ -1208,7 +1214,7 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
|
|||||||
|
|
||||||
switch (list) {
|
switch (list) {
|
||||||
case CPUFREQ_TRANSITION_NOTIFIER:
|
case CPUFREQ_TRANSITION_NOTIFIER:
|
||||||
ret = blocking_notifier_chain_unregister(
|
ret = srcu_notifier_chain_unregister(
|
||||||
&cpufreq_transition_notifier_list, nb);
|
&cpufreq_transition_notifier_list, nb);
|
||||||
break;
|
break;
|
||||||
case CPUFREQ_POLICY_NOTIFIER:
|
case CPUFREQ_POLICY_NOTIFIER:
|
||||||
|
Loading…
Reference in New Issue
Block a user