summaryrefslogtreecommitdiff
path: root/drivers/cpufreq/cpufreq_interactive.c
diff options
context:
space:
mode:
authorMatt Wagner <mwagner@nvidia.com>2012-09-24 12:48:39 +0530
committerSimone Willett <swillett@nvidia.com>2012-09-26 14:47:30 -0700
commit2f7e5374c321a5d4814bdc84d0a04cf1ebd94cad (patch)
treeb08f8d651637a3d6a9617ec66a30fa78cf52cf4c /drivers/cpufreq/cpufreq_interactive.c
parent3bca5808dcc371ea4e1d6ce555e3eae76fbe0e7e (diff)
Cpufreq: interactive: lock "interactive" node creation/removal
It protects code for creating and removing "interactive" node. Avoiding race at the time of governor switching and hotplugging a cpu core. bug 1050124 (cherry picked from commit ae934e1ea7243000e399486823508b4a180254b5) Reviewed-on: http://git-master/r/133360 Change-Id: Id2010b01fb224578e450507ccdbc6a4629fcb5e1 Signed-off-by: Puneet Saxena <puneets@nvidia.com> Reviewed-on: http://git-master/r/134741 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Tested-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'drivers/cpufreq/cpufreq_interactive.c')
-rw-r--r--drivers/cpufreq/cpufreq_interactive.c43
1 files changed, 30 insertions, 13 deletions
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index 14b956e5a6ec..ab0111fa01ac 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -31,7 +31,6 @@
#include <asm/cputime.h>
-static atomic_t active_count = ATOMIC_INIT(0);
struct cpufreq_interactive_cpuinfo {
struct timer_list cpu_timer;
@@ -114,6 +113,14 @@ static unsigned long midrange_freq;
static unsigned long midrange_go_maxspeed_load;
static unsigned long midrange_max_boost;
+/*
+ * gov_state_lock protects interactive node creation in governor start/stop.
+ */
+static DEFINE_MUTEX(gov_state_lock);
+
+static struct mutex gov_state_lock;
+static unsigned int active_count;
+
static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
unsigned int event);
@@ -612,19 +619,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;
+ if (active_count == 1) {
+ rc = sysfs_create_group(cpufreq_global_kobject,
+ &interactive_attr_group);
- rc = sysfs_create_group(cpufreq_global_kobject,
- &interactive_attr_group);
- if (rc)
- return rc;
+ if (rc) {
+ mutex_unlock(&gov_state_lock);
+ return rc;
+ }
+ idle_notifier_register(&cpufreq_interactive_idle_nb);
+ }
+ mutex_unlock(&gov_state_lock);
- idle_notifier_register(&cpufreq_interactive_idle_nb);
break;
case CPUFREQ_GOV_STOP:
@@ -643,12 +656,16 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
pcpu->idle_exit_time = 0;
}
- if (atomic_dec_return(&active_count) > 0)
- return 0;
+ mutex_lock(&gov_state_lock);
+ active_count--;
- idle_notifier_unregister(&cpufreq_interactive_idle_nb);
- sysfs_remove_group(cpufreq_global_kobject,
- &interactive_attr_group);
+ if (active_count == 0) {
+ idle_notifier_unregister(&cpufreq_interactive_idle_nb);
+
+ sysfs_remove_group(cpufreq_global_kobject,
+ &interactive_attr_group);
+ }
+ mutex_unlock(&gov_state_lock);
break;