]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blobdiff - kernel/cpu_pm.c
Merge branch 'intel_pstate'
[mirror_ubuntu-kernels.git] / kernel / cpu_pm.c
index 009cc9a17d95d601e4f6bf38f13d0f810ebbdb34..67b02e138a472da5f908a6eb2156887e058d0704 100644 (file)
 #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);