diff options
author | Matt Wagner <mwagner@nvidia.com> | 2012-09-24 12:48:39 +0530 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-09-26 14:47:30 -0700 |
commit | 2f7e5374c321a5d4814bdc84d0a04cf1ebd94cad (patch) | |
tree | b08f8d651637a3d6a9617ec66a30fa78cf52cf4c /drivers/cpufreq/cpufreq_interactive.c | |
parent | 3bca5808dcc371ea4e1d6ce555e3eae76fbe0e7e (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.c | 43 |
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; |