aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/cpufreq/cpufreq.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 2d5d575e889d..75d293eeb3ee 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1113,6 +1113,8 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
1113 unsigned int cpu = sys_dev->id; 1113 unsigned int cpu = sys_dev->id;
1114 unsigned long flags; 1114 unsigned long flags;
1115 struct cpufreq_policy *data; 1115 struct cpufreq_policy *data;
1116 struct kobject *kobj;
1117 struct completion *cmp;
1116#ifdef CONFIG_SMP 1118#ifdef CONFIG_SMP
1117 struct sys_device *cpu_sys_dev; 1119 struct sys_device *cpu_sys_dev;
1118 unsigned int j; 1120 unsigned int j;
@@ -1141,10 +1143,11 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
1141 dprintk("removing link\n"); 1143 dprintk("removing link\n");
1142 cpumask_clear_cpu(cpu, data->cpus); 1144 cpumask_clear_cpu(cpu, data->cpus);
1143 spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 1145 spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
1144 sysfs_remove_link(&sys_dev->kobj, "cpufreq"); 1146 kobj = &sys_dev->kobj;
1145 cpufreq_cpu_put(data); 1147 cpufreq_cpu_put(data);
1146 cpufreq_debug_enable_ratelimit(); 1148 cpufreq_debug_enable_ratelimit();
1147 unlock_policy_rwsem_write(cpu); 1149 unlock_policy_rwsem_write(cpu);
1150 sysfs_remove_link(kobj, "cpufreq");
1148 return 0; 1151 return 0;
1149 } 1152 }
1150#endif 1153#endif
@@ -1181,7 +1184,10 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
1181 data->governor->name, CPUFREQ_NAME_LEN); 1184 data->governor->name, CPUFREQ_NAME_LEN);
1182#endif 1185#endif
1183 cpu_sys_dev = get_cpu_sysdev(j); 1186 cpu_sys_dev = get_cpu_sysdev(j);
1184 sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq"); 1187 kobj = &cpu_sys_dev->kobj;
1188 unlock_policy_rwsem_write(cpu);
1189 sysfs_remove_link(kobj, "cpufreq");
1190 lock_policy_rwsem_write(cpu);
1185 cpufreq_cpu_put(data); 1191 cpufreq_cpu_put(data);
1186 } 1192 }
1187 } 1193 }
@@ -1192,19 +1198,22 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
1192 if (cpufreq_driver->target) 1198 if (cpufreq_driver->target)
1193 __cpufreq_governor(data, CPUFREQ_GOV_STOP); 1199 __cpufreq_governor(data, CPUFREQ_GOV_STOP);
1194 1200
1195 kobject_put(&data->kobj); 1201 kobj = &data->kobj;
1202 cmp = &data->kobj_unregister;
1203 unlock_policy_rwsem_write(cpu);
1204 kobject_put(kobj);
1196 1205
1197 /* we need to make sure that the underlying kobj is actually 1206 /* we need to make sure that the underlying kobj is actually
1198 * not referenced anymore by anybody before we proceed with 1207 * not referenced anymore by anybody before we proceed with
1199 * unloading. 1208 * unloading.
1200 */ 1209 */
1201 dprintk("waiting for dropping of refcount\n"); 1210 dprintk("waiting for dropping of refcount\n");
1202 wait_for_completion(&data->kobj_unregister); 1211 wait_for_completion(cmp);
1203 dprintk("wait complete\n"); 1212 dprintk("wait complete\n");
1204 1213
1214 lock_policy_rwsem_write(cpu);
1205 if (cpufreq_driver->exit) 1215 if (cpufreq_driver->exit)
1206 cpufreq_driver->exit(data); 1216 cpufreq_driver->exit(data);
1207
1208 unlock_policy_rwsem_write(cpu); 1217 unlock_policy_rwsem_write(cpu);
1209 1218
1210 free_cpumask_var(data->related_cpus); 1219 free_cpumask_var(data->related_cpus);