|
@@ -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);
|
|
|
|