cpufreq: interactive: Unify Governor Lock Strategy
Matt Wagner [Mon, 17 Sep 2012 23:06:15 +0000 (16:06 -0700)]
Change our locking strategy to be the same as the conservative
and ondemand governor for GOV_START and GOV_STOP to allow
for correct handling of multiple CPUs

Bug 1049258

Change-Id: I15ab620e2f9d47b00ec8186c224eb719b9735aa7
Signed-off-by: Matt Wagner <mwagner@nvidia.com>
Reviewed-on: http://git-master/r/133360
Reviewed-by: Satya Popuri <spopuri@nvidia.com>
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Dan Willemsen <dwillemsen@nvidia.com>

drivers/cpufreq/cpufreq_interactive.c

index 7821e41..cf6ba6c 100644 (file)
@@ -30,8 +30,6 @@
 
 #include <asm/cputime.h>
 
-static atomic_t active_count = ATOMIC_INIT(0);
-
 struct cpufreq_interactive_cpuinfo {
        struct timer_list cpu_timer;
        int timer_idlecancel;
@@ -61,7 +59,9 @@ static spinlock_t up_cpumask_lock;
 static cpumask_t down_cpumask;
 static spinlock_t down_cpumask_lock;
 static struct mutex set_speed_lock;
+static struct mutex gov_state_lock;
 static struct kobject *interactive_kobj;
+static unsigned int active_count;
 
 /* Go to max speed when CPU load at or above this value. */
 #define DEFAULT_GO_MAXSPEED_LOAD 85
@@ -652,21 +652,25 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
                                mod_timer(&pcpu->cpu_timer, jiffies + 2);
                }
 
+               mutex_lock(&gov_state_lock);
+               active_count++;
                /*
                 * Do not register the idle hook and create sysfs
                 * entries if we have already done so.
                 */
-               if (atomic_inc_return(&active_count) > 1)
-                       return 0;
-
-               rc = sysfs_create_group(cpufreq_global_kobject,
-                               &interactive_attr_group);
-               interactive_kobj = kobject_create_and_add(
-                                       "gov_interactive",
-                                       cpufreq_global_kobject);
-               kobject_uevent(interactive_kobj, KOBJ_ADD);
-               if (rc)
-                       return rc;
+               if (active_count == 1) {
+                       rc = sysfs_create_group(cpufreq_global_kobject,
+                                       &interactive_attr_group);
+                       interactive_kobj = kobject_create_and_add(
+                                               "gov_interactive",
+                                               cpufreq_global_kobject);
+                       kobject_uevent(interactive_kobj, KOBJ_ADD);
+                       if (rc) {
+                               mutex_unlock(&gov_state_lock);
+                               return rc;
+                       }
+               }
+               mutex_unlock(&gov_state_lock);
 
                break;
 
@@ -687,13 +691,18 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
                }
 
                flush_work(&freq_scale_down_work);
-               if (atomic_dec_return(&active_count) > 0)
-                       return 0;
+               mutex_lock(&gov_state_lock);
+
+               active_count--;
+
+               if (active_count == 0) {
+                       sysfs_remove_group(cpufreq_global_kobject,
+                                       &interactive_attr_group);
+                       kobject_uevent(interactive_kobj, KOBJ_REMOVE);
+                       kobject_put(interactive_kobj);
+               }
 
-               sysfs_remove_group(cpufreq_global_kobject,
-                               &interactive_attr_group);
-               kobject_uevent(interactive_kobj, KOBJ_REMOVE);
-               kobject_put(interactive_kobj);
+               mutex_unlock(&gov_state_lock);
 
                break;
 
@@ -771,6 +780,7 @@ static int __init cpufreq_interactive_init(void)
        spin_lock_init(&up_cpumask_lock);
        spin_lock_init(&down_cpumask_lock);
        mutex_init(&set_speed_lock);
+       mutex_init(&gov_state_lock);
 
        idle_notifier_register(&cpufreq_interactive_idle_nb);