diff options
author | Takashi Iwai <tiwai@suse.de> | 2015-10-07 20:11:21 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-10-07 20:11:21 +0200 |
commit | 601d62959d08a450d4666c728ddd2f47c5ba1cfe (patch) | |
tree | 52d9f3c1a2528a9de405d5a19014f3f94b16b35d /drivers/thermal/cpu_cooling.c | |
parent | 225db5762dc1a35b26850477ffa06e5cd0097243 (diff) | |
parent | e4fc141d2a022a63c87a4851b3c688eca6a1647b (diff) |
Merge tag 'asoc-fix-v4.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linussound-4.3-rc5
ASoC: Fixes for v4.3
Quite a few fixes here but they're all very small and driver specific,
none of them really stand out if you aren't using the relevant hardware
but they're all useful if you do happen to have an affected device.
Diffstat (limited to 'drivers/thermal/cpu_cooling.c')
-rw-r--r-- | drivers/thermal/cpu_cooling.c | 52 |
1 files changed, 31 insertions, 21 deletions
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index 620dcd405ff6..42c6f71bdcc1 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c @@ -262,7 +262,9 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb, * efficiently. Power is stored in mW, frequency in KHz. The * resulting table is in ascending order. * - * Return: 0 on success, -E* on error. + * Return: 0 on success, -EINVAL if there are no OPPs for any CPUs, + * -ENOMEM if we run out of memory or -EAGAIN if an OPP was + * added/enabled while the function was executing. */ static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_device, u32 capacitance) @@ -273,8 +275,6 @@ static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_device, int num_opps = 0, cpu, i, ret = 0; unsigned long freq; - rcu_read_lock(); - for_each_cpu(cpu, &cpufreq_device->allowed_cpus) { dev = get_cpu_device(cpu); if (!dev) { @@ -284,24 +284,20 @@ static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_device, } num_opps = dev_pm_opp_get_opp_count(dev); - if (num_opps > 0) { + if (num_opps > 0) break; - } else if (num_opps < 0) { - ret = num_opps; - goto unlock; - } + else if (num_opps < 0) + return num_opps; } - if (num_opps == 0) { - ret = -EINVAL; - goto unlock; - } + if (num_opps == 0) + return -EINVAL; power_table = kcalloc(num_opps, sizeof(*power_table), GFP_KERNEL); - if (!power_table) { - ret = -ENOMEM; - goto unlock; - } + if (!power_table) + return -ENOMEM; + + rcu_read_lock(); for (freq = 0, i = 0; opp = dev_pm_opp_find_freq_ceil(dev, &freq), !IS_ERR(opp); @@ -309,6 +305,12 @@ static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_device, u32 freq_mhz, voltage_mv; u64 power; + if (i >= num_opps) { + rcu_read_unlock(); + ret = -EAGAIN; + goto free_power_table; + } + freq_mhz = freq / 1000000; voltage_mv = dev_pm_opp_get_voltage(opp) / 1000; @@ -326,17 +328,22 @@ static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_device, power_table[i].power = power; } - if (i == 0) { + rcu_read_unlock(); + + if (i != num_opps) { ret = PTR_ERR(opp); - goto unlock; + goto free_power_table; } cpufreq_device->cpu_dev = dev; cpufreq_device->dyn_power_table = power_table; cpufreq_device->dyn_power_table_entries = i; -unlock: - rcu_read_unlock(); + return 0; + +free_power_table: + kfree(power_table); + return ret; } @@ -847,7 +854,7 @@ __cpufreq_cooling_register(struct device_node *np, ret = get_idr(&cpufreq_idr, &cpufreq_dev->id); if (ret) { cool_dev = ERR_PTR(ret); - goto free_table; + goto free_power_table; } snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d", @@ -889,6 +896,8 @@ __cpufreq_cooling_register(struct device_node *np, remove_idr: release_idr(&cpufreq_idr, cpufreq_dev->id); +free_power_table: + kfree(cpufreq_dev->dyn_power_table); free_table: kfree(cpufreq_dev->freq_table); free_time_in_idle_timestamp: @@ -1039,6 +1048,7 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) thermal_cooling_device_unregister(cpufreq_dev->cool_dev); release_idr(&cpufreq_idr, cpufreq_dev->id); + kfree(cpufreq_dev->dyn_power_table); kfree(cpufreq_dev->time_in_idle_timestamp); kfree(cpufreq_dev->time_in_idle); kfree(cpufreq_dev->freq_table); |