aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/cpufreq/cpufreq.c69
1 files changed, 53 insertions, 16 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 1d041aff4d48..e0ace3d9382c 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -44,6 +44,7 @@
44 */ 44 */
45static struct cpufreq_driver *cpufreq_driver; 45static struct cpufreq_driver *cpufreq_driver;
46static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data); 46static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
47static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data_fallback);
47static DEFINE_RWLOCK(cpufreq_driver_lock); 48static DEFINE_RWLOCK(cpufreq_driver_lock);
48static DEFINE_MUTEX(cpufreq_governor_lock); 49static DEFINE_MUTEX(cpufreq_governor_lock);
49 50
@@ -946,6 +947,20 @@ static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling,
946} 947}
947#endif 948#endif
948 949
950static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu)
951{
952 struct cpufreq_policy *policy;
953 unsigned long flags;
954
955 write_lock_irqsave(&cpufreq_driver_lock, flags);
956
957 policy = per_cpu(cpufreq_cpu_data_fallback, cpu);
958
959 write_unlock_irqrestore(&cpufreq_driver_lock, flags);
960
961 return policy;
962}
963
949static struct cpufreq_policy *cpufreq_policy_alloc(void) 964static struct cpufreq_policy *cpufreq_policy_alloc(void)
950{ 965{
951 struct cpufreq_policy *policy; 966 struct cpufreq_policy *policy;
@@ -1023,7 +1038,12 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
1023 goto module_out; 1038 goto module_out;
1024 } 1039 }
1025 1040
1026 policy = cpufreq_policy_alloc(); 1041 if (frozen)
1042 /* Restore the saved policy when doing light-weight init */
1043 policy = cpufreq_policy_restore(cpu);
1044 else
1045 policy = cpufreq_policy_alloc();
1046
1027 if (!policy) 1047 if (!policy)
1028 goto nomem_out; 1048 goto nomem_out;
1029 1049
@@ -1204,6 +1224,10 @@ static int __cpufreq_remove_dev(struct device *dev,
1204 data = per_cpu(cpufreq_cpu_data, cpu); 1224 data = per_cpu(cpufreq_cpu_data, cpu);
1205 per_cpu(cpufreq_cpu_data, cpu) = NULL; 1225 per_cpu(cpufreq_cpu_data, cpu) = NULL;
1206 1226
1227 /* Save the policy somewhere when doing a light-weight tear-down */
1228 if (frozen)
1229 per_cpu(cpufreq_cpu_data_fallback, cpu) = data;
1230
1207 write_unlock_irqrestore(&cpufreq_driver_lock, flags); 1231 write_unlock_irqrestore(&cpufreq_driver_lock, flags);
1208 1232
1209 if (!data) { 1233 if (!data) {
@@ -1249,27 +1273,40 @@ static int __cpufreq_remove_dev(struct device *dev,
1249 if (cpufreq_driver->target) 1273 if (cpufreq_driver->target)
1250 __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT); 1274 __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
1251 1275
1252 lock_policy_rwsem_read(cpu); 1276 if (!frozen) {
1253 kobj = &data->kobj; 1277 lock_policy_rwsem_read(cpu);
1254 cmp = &data->kobj_unregister; 1278 kobj = &data->kobj;
1255 unlock_policy_rwsem_read(cpu); 1279 cmp = &data->kobj_unregister;
1256 kobject_put(kobj); 1280 unlock_policy_rwsem_read(cpu);
1281 kobject_put(kobj);
1282
1283 /*
1284 * We need to make sure that the underlying kobj is
1285 * actually not referenced anymore by anybody before we
1286 * proceed with unloading.
1287 */
1288 pr_debug("waiting for dropping of refcount\n");
1289 wait_for_completion(cmp);
1290 pr_debug("wait complete\n");
1291 }
1257 1292
1258 /* we need to make sure that the underlying kobj is actually 1293 /*
1259 * not referenced anymore by anybody before we proceed with 1294 * Perform the ->exit() even during light-weight tear-down,
1260 * unloading. 1295 * since this is a core component, and is essential for the
1296 * subsequent light-weight ->init() to succeed.
1261 */ 1297 */
1262 pr_debug("waiting for dropping of refcount\n");
1263 wait_for_completion(cmp);
1264 pr_debug("wait complete\n");
1265
1266 if (cpufreq_driver->exit) 1298 if (cpufreq_driver->exit)
1267 cpufreq_driver->exit(data); 1299 cpufreq_driver->exit(data);
1268 1300
1269 cpufreq_policy_free(data); 1301 if (!frozen)
1302 cpufreq_policy_free(data);
1270 } else { 1303 } else {
1271 pr_debug("%s: removing link, cpu: %d\n", __func__, cpu); 1304
1272 cpufreq_cpu_put(data); 1305 if (!frozen) {
1306 pr_debug("%s: removing link, cpu: %d\n", __func__, cpu);
1307 cpufreq_cpu_put(data);
1308 }
1309
1273 if (cpufreq_driver->target) { 1310 if (cpufreq_driver->target) {
1274 __cpufreq_governor(data, CPUFREQ_GOV_START); 1311 __cpufreq_governor(data, CPUFREQ_GOV_START);
1275 __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); 1312 __cpufreq_governor(data, CPUFREQ_GOV_LIMITS);