cpufreq: interactive: use idle notifier
Allen Martin [Tue, 28 Jun 2011 16:58:39 +0000 (09:58 -0700)]
Convert interactive governor to use idle notifier instead of
hooking pm_idle directly.

Change-Id: I47e007f330468ac559240a0ae8a3cb06a89ccb67
Signed-off-by: Allen Martin <amartin@nvidia.com>

drivers/cpufreq/cpufreq_interactive.c

index 26a423b..9100c3b 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <asm/cputime.h>
 
-static void (*pm_idle_old)(void);
 static atomic_t active_count = ATOMIC_INIT(0);
 
 struct cpufreq_interactive_cpuinfo {
@@ -227,14 +226,13 @@ exit:
        return;
 }
 
-static void cpufreq_interactive_idle(void)
+static void cpufreq_interactive_idle_start(void)
 {
        struct cpufreq_interactive_cpuinfo *pcpu =
                &per_cpu(cpuinfo, smp_processor_id());
        int pending;
 
        if (!pcpu->governor_enabled) {
-               pm_idle_old();
                return;
        }
 
@@ -278,7 +276,13 @@ static void cpufreq_interactive_idle(void)
                }
        }
 
-       pm_idle_old();
+}
+
+static void cpufreq_interactive_idle_end(void)
+{
+       struct cpufreq_interactive_cpuinfo *pcpu =
+               &per_cpu(cpuinfo, smp_processor_id());
+
        pcpu->idling = 0;
        smp_wmb();
 
@@ -462,8 +466,6 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
                if (rc)
                        return rc;
 
-               pm_idle_old = pm_idle;
-               pm_idle = cpufreq_interactive_idle;
                break;
 
        case CPUFREQ_GOV_STOP:
@@ -489,7 +491,6 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
                sysfs_remove_group(cpufreq_global_kobject,
                                &interactive_attr_group);
 
-               pm_idle = pm_idle_old;
                break;
 
        case CPUFREQ_GOV_LIMITS:
@@ -504,6 +505,26 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
        return 0;
 }
 
+static int cpufreq_interactive_idle_notifier(struct notifier_block *nb,
+                                            unsigned long val,
+                                            void *data)
+{
+       switch (val) {
+       case IDLE_START:
+               cpufreq_interactive_idle_start();
+               break;
+       case IDLE_END:
+               cpufreq_interactive_idle_end();
+               break;
+       }
+
+       return 0;
+}
+
+static struct notifier_block cpufreq_interactive_idle_nb = {
+       .notifier_call = cpufreq_interactive_idle_notifier,
+};
+
 static int __init cpufreq_interactive_init(void)
 {
        unsigned int i;
@@ -542,6 +563,8 @@ static int __init cpufreq_interactive_init(void)
        spin_lock_init(&up_cpumask_lock);
        spin_lock_init(&down_cpumask_lock);
 
+       idle_notifier_register(&cpufreq_interactive_idle_nb);
+
        return cpufreq_register_governor(&cpufreq_gov_interactive);
 
 err_freeuptask: