summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorPuneet Saxena <puneets@nvidia.com>2013-08-14 21:04:00 +0530
committerGabby Lee <galee@nvidia.com>2013-09-08 21:50:07 -0700
commit911ee1b291e0486611a55ff358f6660219810c6a (patch)
treebffa810a4460fda6e5c1b568c5409ccf0a350146 /drivers
parent272a641310c17b4abc72fac4da7e6410cedd1db6 (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.c12
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