aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq
diff options
context:
space:
mode:
authorSrivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>2013-09-06 15:53:09 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-09-09 20:49:46 -0400
commitcedb70afd077b00bff7379042fdbf7eef32606c9 (patch)
tree6524564121d1f57d5a6891da9f0776ea3d048e19 /drivers/cpufreq
parenta857c0b9e24e39fe5be82451b65377795f9538d8 (diff)
cpufreq: Split __cpufreq_remove_dev() into two parts
During CPU offline, the cpufreq core invokes __cpufreq_remove_dev() to perform work such as stopping the cpufreq governor, clearing the CPU from the policy structure etc, and finally cleaning up the kobject. There are certain subtle issues related to the kobject cleanup, and it would be much easier to deal with them if we separate that part from the rest of the cleanup-work in the CPU offline phase. So split the __cpufreq_remove_dev() function into 2 parts: one that handles the kobject cleanup, and the other that handles the rest of the work. Reported-by: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r--drivers/cpufreq/cpufreq.c65
1 files changed, 53 insertions, 12 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 7e6baa58a7f2..a33174e324d1 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1141,22 +1141,14 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
1141 return cpu_dev->id; 1141 return cpu_dev->id;
1142} 1142}
1143 1143
1144/** 1144static int __cpufreq_remove_dev_prepare(struct device *dev,
1145 * __cpufreq_remove_dev - remove a CPU device 1145 struct subsys_interface *sif,
1146 * 1146 bool frozen)
1147 * Removes the cpufreq interface for a CPU device.
1148 * Caller should already have policy_rwsem in write mode for this CPU.
1149 * This routine frees the rwsem before returning.
1150 */
1151static int __cpufreq_remove_dev(struct device *dev,
1152 struct subsys_interface *sif, bool frozen)
1153{ 1147{
1154 unsigned int cpu = dev->id, cpus; 1148 unsigned int cpu = dev->id, cpus;
1155 int new_cpu, ret; 1149 int new_cpu, ret;
1156 unsigned long flags; 1150 unsigned long flags;
1157 struct cpufreq_policy *policy; 1151 struct cpufreq_policy *policy;
1158 struct kobject *kobj;
1159 struct completion *cmp;
1160 1152
1161 pr_debug("%s: unregistering CPU %u\n", __func__, cpu); 1153 pr_debug("%s: unregistering CPU %u\n", __func__, cpu);
1162 1154
@@ -1213,6 +1205,33 @@ static int __cpufreq_remove_dev(struct device *dev,
1213 } 1205 }
1214 } 1206 }
1215 1207
1208 return 0;
1209}
1210
1211static int __cpufreq_remove_dev_finish(struct device *dev,
1212 struct subsys_interface *sif,
1213 bool frozen)
1214{
1215 unsigned int cpu = dev->id, cpus;
1216 int ret;
1217 unsigned long flags;
1218 struct cpufreq_policy *policy;
1219 struct kobject *kobj;
1220 struct completion *cmp;
1221
1222 read_lock_irqsave(&cpufreq_driver_lock, flags);
1223 policy = per_cpu(cpufreq_cpu_data, cpu);
1224 read_unlock_irqrestore(&cpufreq_driver_lock, flags);
1225
1226 if (!policy) {
1227 pr_debug("%s: No cpu_data found\n", __func__);
1228 return -EINVAL;
1229 }
1230
1231 lock_policy_rwsem_read(cpu);
1232 cpus = cpumask_weight(policy->cpus);
1233 unlock_policy_rwsem_read(cpu);
1234
1216 /* If cpu is last user of policy, free policy */ 1235 /* If cpu is last user of policy, free policy */
1217 if (cpus == 1) { 1236 if (cpus == 1) {
1218 if (cpufreq_driver->target) { 1237 if (cpufreq_driver->target) {
@@ -1272,6 +1291,27 @@ static int __cpufreq_remove_dev(struct device *dev,
1272 return 0; 1291 return 0;
1273} 1292}
1274 1293
1294/**
1295 * __cpufreq_remove_dev - remove a CPU device
1296 *
1297 * Removes the cpufreq interface for a CPU device.
1298 * Caller should already have policy_rwsem in write mode for this CPU.
1299 * This routine frees the rwsem before returning.
1300 */
1301static inline int __cpufreq_remove_dev(struct device *dev,
1302 struct subsys_interface *sif,
1303 bool frozen)
1304{
1305 int ret;
1306
1307 ret = __cpufreq_remove_dev_prepare(dev, sif, frozen);
1308
1309 if (!ret)
1310 ret = __cpufreq_remove_dev_finish(dev, sif, frozen);
1311
1312 return ret;
1313}
1314
1275static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) 1315static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
1276{ 1316{
1277 unsigned int cpu = dev->id; 1317 unsigned int cpu = dev->id;
@@ -2000,7 +2040,8 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
2000 break; 2040 break;
2001 2041
2002 case CPU_DOWN_PREPARE: 2042 case CPU_DOWN_PREPARE:
2003 __cpufreq_remove_dev(dev, NULL, frozen); 2043 __cpufreq_remove_dev_prepare(dev, NULL, frozen);
2044 __cpufreq_remove_dev_finish(dev, NULL, frozen);
2004 break; 2045 break;
2005 2046
2006 case CPU_DOWN_FAILED: 2047 case CPU_DOWN_FAILED: