diff options
author | Puneet Saxena <puneets@nvidia.com> | 2013-08-14 21:04:00 +0530 |
---|---|---|
committer | Gabby Lee <galee@nvidia.com> | 2013-09-08 21:50:07 -0700 |
commit | 911ee1b291e0486611a55ff358f6660219810c6a (patch) | |
tree | bffa810a4460fda6e5c1b568c5409ccf0a350146 /drivers | |
parent | 272a641310c17b4abc72fac4da7e6410cedd1db6 (diff) |
Cpufreq: protect policy & module refcount
percpu policy pointer needs to be updated with "cpufreq_cpu_data"
synchronously.
This will avoid different virtue of policy pointer of an
online cpu.
It protects ref counting while releasing policy object
Bug 1327428
Signed-off-by: Puneet Saxena <puneets@nvidia.com>
Reviewed-on: http://git-master/r/261609
(cherry picked from commit e1f0ddb9f2a50a7697864f180fbab745add08682)
Change-Id: I817a78c2ead921546f97e4af8943fb5c4ffcfcc6
Signed-off-by: Jinyoung Park <jinyoungp@nvidia.com>
Reviewed-on: http://git-master/r/269944
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Gabby Lee <galee@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 4ac58b57830e..a4bc8070c5ef 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -668,6 +668,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, goto no_policy; policy = freqobj->cpu_policy; + policy = cpufreq_cpu_get(policy->cpu); if (!policy) goto no_policy; @@ -814,6 +815,7 @@ static int cpufreq_add_dev_policy(unsigned int cpu, spin_lock_irqsave(&cpufreq_driver_lock, flags); cpumask_copy(managed_policy->cpus, policy->cpus); per_cpu(cpufreq_cpu_data, cpu) = managed_policy; + cpu_sysnode[cpu].cpu_policy = managed_policy; spin_unlock_irqrestore(&cpufreq_driver_lock, flags); pr_debug("CPU already managed, adding link\n"); @@ -884,6 +886,7 @@ static int cpufreq_add_dev_interface(unsigned int cpu, if (!cpu_online(j)) continue; per_cpu(cpufreq_cpu_data, j) = policy; + cpu_sysnode[j].cpu_policy = policy; per_cpu(cpufreq_policy_cpu, j) = policy->cpu; } spin_unlock_irqrestore(&cpufreq_driver_lock, flags); @@ -1004,7 +1007,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) blocking_notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_START, policy); - policy->kobj = &cpu_sysnode[cpu].cpu_kobj; + policy->kobj = &cpu_sysnode[policy->cpu].cpu_kobj; ret = cpufreq_add_dev_policy(cpu, policy, dev); if (ret) { @@ -1030,8 +1033,10 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) err_out_unregister: spin_lock_irqsave(&cpufreq_driver_lock, flags); - for_each_cpu(j, policy->cpus) + for_each_cpu(j, policy->cpus) { per_cpu(cpufreq_cpu_data, j) = NULL; + cpu_sysnode[j].cpu_policy = NULL; + } spin_unlock_irqrestore(&cpufreq_driver_lock, flags); kobject_put(policy->kobj); err_unlock_policy: @@ -1088,7 +1093,6 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif cpumask_clear_cpu(cpu, data->cpus); spin_unlock_irqrestore(&cpufreq_driver_lock, flags); kobj = &dev->kobj; - cpufreq_cpu_put(data); unlock_policy_rwsem_write(cpu); sysfs_remove_link(kobj, "cpufreq"); return 0; @@ -1112,6 +1116,7 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif if (j == cpu) continue; per_cpu(cpufreq_cpu_data, j) = NULL; + cpu_sysnode[j].cpu_policy = NULL; } } @@ -1131,7 +1136,6 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif unlock_policy_rwsem_write(cpu); sysfs_remove_link(kobj, "cpufreq"); lock_policy_rwsem_write(cpu); - cpufreq_cpu_put(data); } } #else |