diff options
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 63 |
1 files changed, 31 insertions, 32 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 02d534da22dd..fab042e1ee90 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -845,8 +845,7 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy) | |||
845 | 845 | ||
846 | #ifdef CONFIG_HOTPLUG_CPU | 846 | #ifdef CONFIG_HOTPLUG_CPU |
847 | static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, | 847 | static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, |
848 | unsigned int cpu, struct device *dev, | 848 | unsigned int cpu, struct device *dev) |
849 | bool frozen) | ||
850 | { | 849 | { |
851 | int ret = 0; | 850 | int ret = 0; |
852 | unsigned long flags; | 851 | unsigned long flags; |
@@ -877,11 +876,7 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, | |||
877 | } | 876 | } |
878 | } | 877 | } |
879 | 878 | ||
880 | /* Don't touch sysfs links during light-weight init */ | 879 | return sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq"); |
881 | if (!frozen) | ||
882 | ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq"); | ||
883 | |||
884 | return ret; | ||
885 | } | 880 | } |
886 | #endif | 881 | #endif |
887 | 882 | ||
@@ -926,6 +921,27 @@ err_free_policy: | |||
926 | return NULL; | 921 | return NULL; |
927 | } | 922 | } |
928 | 923 | ||
924 | static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy) | ||
925 | { | ||
926 | struct kobject *kobj; | ||
927 | struct completion *cmp; | ||
928 | |||
929 | down_read(&policy->rwsem); | ||
930 | kobj = &policy->kobj; | ||
931 | cmp = &policy->kobj_unregister; | ||
932 | up_read(&policy->rwsem); | ||
933 | kobject_put(kobj); | ||
934 | |||
935 | /* | ||
936 | * We need to make sure that the underlying kobj is | ||
937 | * actually not referenced anymore by anybody before we | ||
938 | * proceed with unloading. | ||
939 | */ | ||
940 | pr_debug("waiting for dropping of refcount\n"); | ||
941 | wait_for_completion(cmp); | ||
942 | pr_debug("wait complete\n"); | ||
943 | } | ||
944 | |||
929 | static void cpufreq_policy_free(struct cpufreq_policy *policy) | 945 | static void cpufreq_policy_free(struct cpufreq_policy *policy) |
930 | { | 946 | { |
931 | free_cpumask_var(policy->related_cpus); | 947 | free_cpumask_var(policy->related_cpus); |
@@ -986,7 +1002,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, | |||
986 | list_for_each_entry(tpolicy, &cpufreq_policy_list, policy_list) { | 1002 | list_for_each_entry(tpolicy, &cpufreq_policy_list, policy_list) { |
987 | if (cpumask_test_cpu(cpu, tpolicy->related_cpus)) { | 1003 | if (cpumask_test_cpu(cpu, tpolicy->related_cpus)) { |
988 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); | 1004 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); |
989 | ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev, frozen); | 1005 | ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev); |
990 | up_read(&cpufreq_rwsem); | 1006 | up_read(&cpufreq_rwsem); |
991 | return ret; | 1007 | return ret; |
992 | } | 1008 | } |
@@ -1096,7 +1112,10 @@ err_get_freq: | |||
1096 | if (cpufreq_driver->exit) | 1112 | if (cpufreq_driver->exit) |
1097 | cpufreq_driver->exit(policy); | 1113 | cpufreq_driver->exit(policy); |
1098 | err_set_policy_cpu: | 1114 | err_set_policy_cpu: |
1115 | if (frozen) | ||
1116 | cpufreq_policy_put_kobj(policy); | ||
1099 | cpufreq_policy_free(policy); | 1117 | cpufreq_policy_free(policy); |
1118 | |||
1100 | nomem_out: | 1119 | nomem_out: |
1101 | up_read(&cpufreq_rwsem); | 1120 | up_read(&cpufreq_rwsem); |
1102 | 1121 | ||
@@ -1118,7 +1137,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) | |||
1118 | } | 1137 | } |
1119 | 1138 | ||
1120 | static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, | 1139 | static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, |
1121 | unsigned int old_cpu, bool frozen) | 1140 | unsigned int old_cpu) |
1122 | { | 1141 | { |
1123 | struct device *cpu_dev; | 1142 | struct device *cpu_dev; |
1124 | int ret; | 1143 | int ret; |
@@ -1126,10 +1145,6 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, | |||
1126 | /* first sibling now owns the new sysfs dir */ | 1145 | /* first sibling now owns the new sysfs dir */ |
1127 | cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu)); | 1146 | cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu)); |
1128 | 1147 | ||
1129 | /* Don't touch sysfs files during light-weight tear-down */ | ||
1130 | if (frozen) | ||
1131 | return cpu_dev->id; | ||
1132 | |||
1133 | sysfs_remove_link(&cpu_dev->kobj, "cpufreq"); | 1148 | sysfs_remove_link(&cpu_dev->kobj, "cpufreq"); |
1134 | ret = kobject_move(&policy->kobj, &cpu_dev->kobj); | 1149 | ret = kobject_move(&policy->kobj, &cpu_dev->kobj); |
1135 | if (ret) { | 1150 | if (ret) { |
@@ -1196,7 +1211,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, | |||
1196 | if (!frozen) | 1211 | if (!frozen) |
1197 | sysfs_remove_link(&dev->kobj, "cpufreq"); | 1212 | sysfs_remove_link(&dev->kobj, "cpufreq"); |
1198 | } else if (cpus > 1) { | 1213 | } else if (cpus > 1) { |
1199 | new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu, frozen); | 1214 | new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu); |
1200 | if (new_cpu >= 0) { | 1215 | if (new_cpu >= 0) { |
1201 | update_policy_cpu(policy, new_cpu); | 1216 | update_policy_cpu(policy, new_cpu); |
1202 | 1217 | ||
@@ -1218,8 +1233,6 @@ static int __cpufreq_remove_dev_finish(struct device *dev, | |||
1218 | int ret; | 1233 | int ret; |
1219 | unsigned long flags; | 1234 | unsigned long flags; |
1220 | struct cpufreq_policy *policy; | 1235 | struct cpufreq_policy *policy; |
1221 | struct kobject *kobj; | ||
1222 | struct completion *cmp; | ||
1223 | 1236 | ||
1224 | read_lock_irqsave(&cpufreq_driver_lock, flags); | 1237 | read_lock_irqsave(&cpufreq_driver_lock, flags); |
1225 | policy = per_cpu(cpufreq_cpu_data, cpu); | 1238 | policy = per_cpu(cpufreq_cpu_data, cpu); |
@@ -1249,22 +1262,8 @@ static int __cpufreq_remove_dev_finish(struct device *dev, | |||
1249 | } | 1262 | } |
1250 | } | 1263 | } |
1251 | 1264 | ||
1252 | if (!frozen) { | 1265 | if (!frozen) |
1253 | down_read(&policy->rwsem); | 1266 | cpufreq_policy_put_kobj(policy); |
1254 | kobj = &policy->kobj; | ||
1255 | cmp = &policy->kobj_unregister; | ||
1256 | up_read(&policy->rwsem); | ||
1257 | kobject_put(kobj); | ||
1258 | |||
1259 | /* | ||
1260 | * We need to make sure that the underlying kobj is | ||
1261 | * actually not referenced anymore by anybody before we | ||
1262 | * proceed with unloading. | ||
1263 | */ | ||
1264 | pr_debug("waiting for dropping of refcount\n"); | ||
1265 | wait_for_completion(cmp); | ||
1266 | pr_debug("wait complete\n"); | ||
1267 | } | ||
1268 | 1267 | ||
1269 | /* | 1268 | /* |
1270 | * Perform the ->exit() even during light-weight tear-down, | 1269 | * Perform the ->exit() even during light-weight tear-down, |