diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-05-29 17:05:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-05-29 17:05:57 -0400 |
commit | f035b3d32256b93a4c39622afe6ac7ade8eedbea (patch) | |
tree | 15241c777bb8482d65bd6dfcc26ddfca8252010c | |
parent | 15a7b60ea157d4e7cb498ac88515a558d79d7da2 (diff) | |
parent | 9b961aa99b8155ecc07dd727643ca97424544256 (diff) |
Merge tag 'pm+acpi-3.15-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI and power management fixes from Rafael Wysocki:
"These are three stable-candidate fixes, one for the ACPI thermal
driver and two for cpufreq drivers.
Specifics:
- A workqueue is destroyed too early during the ACPI thermal driver
module unload which leads to a NULL pointer dereference in the
driver's remove callback. Fix from Aaron Lu.
- A wrong argument is passed to devm_regulator_get_optional() in the
probe routine of the cpu0 cpufreq driver which leads to resource
leaks if the driver is unbound from the cpufreq platform device.
Fix from Lucas Stach.
- A lock is missing in cpufreq_governor_dbs() which leads to memory
corruption and NULL pointer dereferences during system
suspend/resume, for example. Fix from Bibek Basu"
* tag 'pm+acpi-3.15-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
ACPI / thermal: fix workqueue destroy order
cpufreq: cpu0: drop wrong devm usage
cpufreq: remove race while accessing cur_policy
-rw-r--r-- | drivers/acpi/thermal.c | 2 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq-cpu0.c | 16 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq_governor.c | 6 |
3 files changed, 18 insertions, 6 deletions
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index c1e31a41f949..25bbc55dca89 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
@@ -1278,8 +1278,8 @@ static int __init acpi_thermal_init(void) | |||
1278 | 1278 | ||
1279 | static void __exit acpi_thermal_exit(void) | 1279 | static void __exit acpi_thermal_exit(void) |
1280 | { | 1280 | { |
1281 | destroy_workqueue(acpi_thermal_pm_queue); | ||
1282 | acpi_bus_unregister_driver(&acpi_thermal_driver); | 1281 | acpi_bus_unregister_driver(&acpi_thermal_driver); |
1282 | destroy_workqueue(acpi_thermal_pm_queue); | ||
1283 | 1283 | ||
1284 | return; | 1284 | return; |
1285 | } | 1285 | } |
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index 1bf6bbac3e03..09b9129c7bd3 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c | |||
@@ -130,7 +130,7 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev) | |||
130 | return -ENOENT; | 130 | return -ENOENT; |
131 | } | 131 | } |
132 | 132 | ||
133 | cpu_reg = devm_regulator_get_optional(cpu_dev, "cpu0"); | 133 | cpu_reg = regulator_get_optional(cpu_dev, "cpu0"); |
134 | if (IS_ERR(cpu_reg)) { | 134 | if (IS_ERR(cpu_reg)) { |
135 | /* | 135 | /* |
136 | * If cpu0 regulator supply node is present, but regulator is | 136 | * If cpu0 regulator supply node is present, but regulator is |
@@ -145,23 +145,23 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev) | |||
145 | PTR_ERR(cpu_reg)); | 145 | PTR_ERR(cpu_reg)); |
146 | } | 146 | } |
147 | 147 | ||
148 | cpu_clk = devm_clk_get(cpu_dev, NULL); | 148 | cpu_clk = clk_get(cpu_dev, NULL); |
149 | if (IS_ERR(cpu_clk)) { | 149 | if (IS_ERR(cpu_clk)) { |
150 | ret = PTR_ERR(cpu_clk); | 150 | ret = PTR_ERR(cpu_clk); |
151 | pr_err("failed to get cpu0 clock: %d\n", ret); | 151 | pr_err("failed to get cpu0 clock: %d\n", ret); |
152 | goto out_put_node; | 152 | goto out_put_reg; |
153 | } | 153 | } |
154 | 154 | ||
155 | ret = of_init_opp_table(cpu_dev); | 155 | ret = of_init_opp_table(cpu_dev); |
156 | if (ret) { | 156 | if (ret) { |
157 | pr_err("failed to init OPP table: %d\n", ret); | 157 | pr_err("failed to init OPP table: %d\n", ret); |
158 | goto out_put_node; | 158 | goto out_put_clk; |
159 | } | 159 | } |
160 | 160 | ||
161 | ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); | 161 | ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); |
162 | if (ret) { | 162 | if (ret) { |
163 | pr_err("failed to init cpufreq table: %d\n", ret); | 163 | pr_err("failed to init cpufreq table: %d\n", ret); |
164 | goto out_put_node; | 164 | goto out_put_clk; |
165 | } | 165 | } |
166 | 166 | ||
167 | of_property_read_u32(np, "voltage-tolerance", &voltage_tolerance); | 167 | of_property_read_u32(np, "voltage-tolerance", &voltage_tolerance); |
@@ -216,6 +216,12 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev) | |||
216 | 216 | ||
217 | out_free_table: | 217 | out_free_table: |
218 | dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); | 218 | dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); |
219 | out_put_clk: | ||
220 | if (!IS_ERR(cpu_clk)) | ||
221 | clk_put(cpu_clk); | ||
222 | out_put_reg: | ||
223 | if (!IS_ERR(cpu_reg)) | ||
224 | regulator_put(cpu_reg); | ||
219 | out_put_node: | 225 | out_put_node: |
220 | of_node_put(np); | 226 | of_node_put(np); |
221 | return ret; | 227 | return ret; |
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index ba43991ba98a..e1c6433b16e0 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c | |||
@@ -366,6 +366,11 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
366 | break; | 366 | break; |
367 | 367 | ||
368 | case CPUFREQ_GOV_LIMITS: | 368 | case CPUFREQ_GOV_LIMITS: |
369 | mutex_lock(&dbs_data->mutex); | ||
370 | if (!cpu_cdbs->cur_policy) { | ||
371 | mutex_unlock(&dbs_data->mutex); | ||
372 | break; | ||
373 | } | ||
369 | mutex_lock(&cpu_cdbs->timer_mutex); | 374 | mutex_lock(&cpu_cdbs->timer_mutex); |
370 | if (policy->max < cpu_cdbs->cur_policy->cur) | 375 | if (policy->max < cpu_cdbs->cur_policy->cur) |
371 | __cpufreq_driver_target(cpu_cdbs->cur_policy, | 376 | __cpufreq_driver_target(cpu_cdbs->cur_policy, |
@@ -375,6 +380,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
375 | policy->min, CPUFREQ_RELATION_L); | 380 | policy->min, CPUFREQ_RELATION_L); |
376 | dbs_check_cpu(dbs_data, cpu); | 381 | dbs_check_cpu(dbs_data, cpu); |
377 | mutex_unlock(&cpu_cdbs->timer_mutex); | 382 | mutex_unlock(&cpu_cdbs->timer_mutex); |
383 | mutex_unlock(&dbs_data->mutex); | ||
378 | break; | 384 | break; |
379 | } | 385 | } |
380 | return 0; | 386 | return 0; |