diff options
Diffstat (limited to 'kernel/cpu_pm.c')
| -rw-r--r-- | kernel/cpu_pm.c | 50 | 
1 files changed, 13 insertions, 37 deletions
| diff --git a/kernel/cpu_pm.c b/kernel/cpu_pm.c index 009cc9a17d95..67b02e138a47 100644 --- a/kernel/cpu_pm.c +++ b/kernel/cpu_pm.c @@ -22,15 +22,21 @@  #include <linux/spinlock.h>  #include <linux/syscore_ops.h> -static DEFINE_RWLOCK(cpu_pm_notifier_lock); -static RAW_NOTIFIER_HEAD(cpu_pm_notifier_chain); +static ATOMIC_NOTIFIER_HEAD(cpu_pm_notifier_chain);  static int cpu_pm_notify(enum cpu_pm_event event, int nr_to_call, int *nr_calls)  {  	int ret; -	ret = __raw_notifier_call_chain(&cpu_pm_notifier_chain, event, NULL, +	/* +	 * __atomic_notifier_call_chain has a RCU read critical section, which +	 * could be disfunctional in cpu idle. Copy RCU_NONIDLE code to let +	 * RCU know this. +	 */ +	rcu_irq_enter_irqson(); +	ret = __atomic_notifier_call_chain(&cpu_pm_notifier_chain, event, NULL,  		nr_to_call, nr_calls); +	rcu_irq_exit_irqson();  	return notifier_to_errno(ret);  } @@ -47,14 +53,7 @@ static int cpu_pm_notify(enum cpu_pm_event event, int nr_to_call, int *nr_calls)   */  int cpu_pm_register_notifier(struct notifier_block *nb)  { -	unsigned long flags; -	int ret; - -	write_lock_irqsave(&cpu_pm_notifier_lock, flags); -	ret = raw_notifier_chain_register(&cpu_pm_notifier_chain, nb); -	write_unlock_irqrestore(&cpu_pm_notifier_lock, flags); - -	return ret; +	return atomic_notifier_chain_register(&cpu_pm_notifier_chain, nb);  }  EXPORT_SYMBOL_GPL(cpu_pm_register_notifier); @@ -69,14 +68,7 @@ EXPORT_SYMBOL_GPL(cpu_pm_register_notifier);   */  int cpu_pm_unregister_notifier(struct notifier_block *nb)  { -	unsigned long flags; -	int ret; - -	write_lock_irqsave(&cpu_pm_notifier_lock, flags); -	ret = raw_notifier_chain_unregister(&cpu_pm_notifier_chain, nb); -	write_unlock_irqrestore(&cpu_pm_notifier_lock, flags); - -	return ret; +	return atomic_notifier_chain_unregister(&cpu_pm_notifier_chain, nb);  }  EXPORT_SYMBOL_GPL(cpu_pm_unregister_notifier); @@ -100,7 +92,6 @@ int cpu_pm_enter(void)  	int nr_calls;  	int ret = 0; -	read_lock(&cpu_pm_notifier_lock);  	ret = cpu_pm_notify(CPU_PM_ENTER, -1, &nr_calls);  	if (ret)  		/* @@ -108,7 +99,6 @@ int cpu_pm_enter(void)  		 * PM entry who are notified earlier to prepare for it.  		 */  		cpu_pm_notify(CPU_PM_ENTER_FAILED, nr_calls - 1, NULL); -	read_unlock(&cpu_pm_notifier_lock);  	return ret;  } @@ -128,13 +118,7 @@ EXPORT_SYMBOL_GPL(cpu_pm_enter);   */  int cpu_pm_exit(void)  { -	int ret; - -	read_lock(&cpu_pm_notifier_lock); -	ret = cpu_pm_notify(CPU_PM_EXIT, -1, NULL); -	read_unlock(&cpu_pm_notifier_lock); - -	return ret; +	return cpu_pm_notify(CPU_PM_EXIT, -1, NULL);  }  EXPORT_SYMBOL_GPL(cpu_pm_exit); @@ -159,7 +143,6 @@ int cpu_cluster_pm_enter(void)  	int nr_calls;  	int ret = 0; -	read_lock(&cpu_pm_notifier_lock);  	ret = cpu_pm_notify(CPU_CLUSTER_PM_ENTER, -1, &nr_calls);  	if (ret)  		/* @@ -167,7 +150,6 @@ int cpu_cluster_pm_enter(void)  		 * PM entry who are notified earlier to prepare for it.  		 */  		cpu_pm_notify(CPU_CLUSTER_PM_ENTER_FAILED, nr_calls - 1, NULL); -	read_unlock(&cpu_pm_notifier_lock);  	return ret;  } @@ -190,13 +172,7 @@ EXPORT_SYMBOL_GPL(cpu_cluster_pm_enter);   */  int cpu_cluster_pm_exit(void)  { -	int ret; - -	read_lock(&cpu_pm_notifier_lock); -	ret = cpu_pm_notify(CPU_CLUSTER_PM_EXIT, -1, NULL); -	read_unlock(&cpu_pm_notifier_lock); - -	return ret; +	return cpu_pm_notify(CPU_CLUSTER_PM_EXIT, -1, NULL);  }  EXPORT_SYMBOL_GPL(cpu_cluster_pm_exit); |