Pull devfreq fixes for 5.19-rc5 from Chanwoo Choi: "1. Fix devfreq passive governor issue when cpufreq policies are not ready during kernel boot because some CPUs turn on after kernel booting or others. - Re-initialize the vairables of struct devfreq_passive_data when PROBE_DEFER happens when cpufreq_get() returns NULL. - Use dev_err_probe to mute warning when PROBE_DEFER. - Fix cpufreq passive unregister erroring on PROBE_DEFER by using the allocated parent_cpu_data list to free resouce instead of for_each_possible_cpu(). - Remove duplicate cpufreq passive unregister and warning when PROBE_DEFER. - Use HZ_PER_KZH macro in units.h. - Fix wrong indentation in SPDX-License line. 2. Fix reference count leak in exynos-ppmu.c by using of_node_put(). 3. Rework freq_table to be local to devfreq struct - struct devfreq_dev_profile includes freq_table array to store the supported frequencies. If devfreq driver doesn't initialize the freq_table, devfreq core allocates the memory and initializes the freq_table. On a devfreq PROBE_DEFER, the freq_table in the driver profile struct is never reset and may be left in an undefined state. To fix this and correctly handle PROBE_DEFER, use a local freq_table and max_state in the devfreq struct." * tag 'devfreq-fixes-for-5.19-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux: PM / devfreq: passive: revert an editing accident in SPDX-License line PM / devfreq: Fix kernel warning with cpufreq passive register fail PM / devfreq: Rework freq_table to be local to devfreq struct PM / devfreq: exynos-ppmu: Fix refcount leak in of_get_devfreq_events PM / devfreq: passive: Use HZ_PER_KHZ macro in units.h PM / devfreq: Fix cpufreq passive unregister erroring on PROBE_DEFER PM / devfreq: Mute warning on governor PROBE_DEFER PM / devfreq: Fix kernel panic with cpu based scaling to passive gov
Unified · Split
| @@ -123,7 +123,7 @@ void devfreq_get_freq_range(struct devfreq *devfreq, · 122 unmodified lines | ||
| 123 | 123 | unsigned long *min_freq, |
| 124 | 124 | unsigned long *max_freq) |
| 125 | 125 | { |
| 126 | − unsigned long *freq_table = devfreq->profile->freq_table; | |
| 126 | + unsigned long *freq_table = devfreq->freq_table; | |
| 127 | 127 | s32 qos_min_freq, qos_max_freq; |
| 128 | 128 | |
| 129 | 129 | lockdep_assert_held(&devfreq->lock); |
| @@ -133,11 +133,11 @@ void devfreq_get_freq_range(struct devfreq *devfreq, · 3 unmodified lines | ||
| 133 | 133 | * The devfreq drivers can initialize this in either ascending or |
| 134 | 134 | * descending order and devfreq core supports both. |
| 135 | 135 | */ |
| 136 | − if (freq_table[0] < freq_table[devfreq->profile->max_state - 1]) { | |
| 136 | + if (freq_table[0] < freq_table[devfreq->max_state - 1]) { | |
| 137 | 137 | *min_freq = freq_table[0]; |
| 138 | − *max_freq = freq_table[devfreq->profile->max_state - 1]; | |
| 138 | + *max_freq = freq_table[devfreq->max_state - 1]; | |
| 139 | 139 | } else { |
| 140 | − *min_freq = freq_table[devfreq->profile->max_state - 1]; | |
| 140 | + *min_freq = freq_table[devfreq->max_state - 1]; | |
| 141 | 141 | *max_freq = freq_table[0]; |
| 142 | 142 | } |
| 143 | 143 | |
| @@ -169,8 +169,8 @@ static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq) · 25 unmodified lines | ||
| 169 | 169 | { |
| 170 | 170 | int lev; |
| 171 | 171 | |
| 172 | − for (lev = 0; lev < devfreq->profile->max_state; lev++) | |
| 173 | − if (freq == devfreq->profile->freq_table[lev]) | |
| 172 | + for (lev = 0; lev < devfreq->max_state; lev++) | |
| 173 | + if (freq == devfreq->freq_table[lev]) | |
| 174 | 174 | return lev; |
| 175 | 175 | |
| 176 | 176 | return -EINVAL; |
| @@ -178,7 +178,6 @@ static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq) · 1 unmodified line | ||
| 178 | 178 | |
| 179 | 179 | static int set_freq_table(struct devfreq *devfreq) |
| 180 | 180 | { |
| 181 | − struct devfreq_dev_profile *profile = devfreq->profile; | |
| 182 | 181 | struct dev_pm_opp *opp; |
| 183 | 182 | unsigned long freq; |
| 184 | 183 | int i, count; |
| @@ -188,25 +187,22 @@ static int set_freq_table(struct devfreq *devfreq) · 3 unmodified lines | ||
| 188 | 187 | if (count <= 0) |
| 189 | 188 | return -EINVAL; |
| 190 | 189 | |
| 191 | − profile->max_state = count; | |
| 192 | − profile->freq_table = devm_kcalloc(devfreq->dev.parent, | |
| 193 | − profile->max_state, | |
| 194 | − sizeof(*profile->freq_table), | |
| 195 | − GFP_KERNEL); | |
| 196 | − if (!profile->freq_table) { | |
| 197 | − profile->max_state = 0; | |
| 190 | + devfreq->max_state = count; | |
| 191 | + devfreq->freq_table = devm_kcalloc(devfreq->dev.parent, | |
| 192 | + devfreq->max_state, | |
| 193 | + sizeof(*devfreq->freq_table), | |
| 194 | + GFP_KERNEL); | |
| 195 | + if (!devfreq->freq_table) | |
| 198 | 196 | return -ENOMEM; |
| 199 | − } | |
| 200 | 197 | |
| 201 | − for (i = 0, freq = 0; i < profile->max_state; i++, freq++) { | |
| 198 | + for (i = 0, freq = 0; i < devfreq->max_state; i++, freq++) { | |
| 202 | 199 | opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &freq); |
| 203 | 200 | if (IS_ERR(opp)) { |
| 204 | − devm_kfree(devfreq->dev.parent, profile->freq_table); | |
| 205 | − profile->max_state = 0; | |
| 201 | + devm_kfree(devfreq->dev.parent, devfreq->freq_table); | |
| 206 | 202 | return PTR_ERR(opp); |
| 207 | 203 | } |
| 208 | 204 | dev_pm_opp_put(opp); |
| 209 | − profile->freq_table[i] = freq; | |
| 205 | + devfreq->freq_table[i] = freq; | |
| 210 | 206 | } |
| 211 | 207 | |
| 212 | 208 | return 0; |
| @@ -246,7 +242,7 @@ int devfreq_update_status(struct devfreq *devfreq, unsigned long freq) · 33 unmodified lines | ||
| 246 | 242 | |
| 247 | 243 | if (lev != prev_lev) { |
| 248 | 244 | devfreq->stats.trans_table[ |
| 249 | − (prev_lev * devfreq->profile->max_state) + lev]++; | |
| 245 | + (prev_lev * devfreq->max_state) + lev]++; | |
| 250 | 246 | devfreq->stats.total_trans++; |
| 251 | 247 | } |
| 252 | 248 | |
| @@ -835,6 +831,9 @@ struct devfreq *devfreq_add_device(struct device *dev, · 582 unmodified lines | ||
| 835 | 831 | if (err < 0) |
| 836 | 832 | goto err_dev; |
| 837 | 833 | mutex_lock(&devfreq->lock); |
| 834 | + } else { | |
| 835 | + devfreq->freq_table = devfreq->profile->freq_table; | |
| 836 | + devfreq->max_state = devfreq->profile->max_state; | |
| 838 | 837 | } |
| 839 | 838 | |
| 840 | 839 | devfreq->scaling_min_freq = find_available_min_freq(devfreq); |
| @@ -870,8 +869,8 @@ struct devfreq *devfreq_add_device(struct device *dev, · 29 unmodified lines | ||
| 870 | 869 | |
| 871 | 870 | devfreq->stats.trans_table = devm_kzalloc(&devfreq->dev, |
| 872 | 871 | array3_size(sizeof(unsigned int), |
| 873 | − devfreq->profile->max_state, | |
| 874 | − devfreq->profile->max_state), | |
| 872 | + devfreq->max_state, | |
| 873 | + devfreq->max_state), | |
| 875 | 874 | GFP_KERNEL); |
| 876 | 875 | if (!devfreq->stats.trans_table) { |
| 877 | 876 | mutex_unlock(&devfreq->lock); |
| @@ -880,7 +879,7 @@ struct devfreq *devfreq_add_device(struct device *dev, · 2 unmodified lines | ||
| 880 | 879 | } |
| 881 | 880 | |
| 882 | 881 | devfreq->stats.time_in_state = devm_kcalloc(&devfreq->dev, |
| 883 | − devfreq->profile->max_state, | |
| 882 | + devfreq->max_state, | |
| 884 | 883 | sizeof(*devfreq->stats.time_in_state), |
| 885 | 884 | GFP_KERNEL); |
| 886 | 885 | if (!devfreq->stats.time_in_state) { |
| @@ -932,8 +931,9 @@ struct devfreq *devfreq_add_device(struct device *dev, · 45 unmodified lines | ||
| 932 | 931 | err = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_START, |
| 933 | 932 | NULL); |
| 934 | 933 | if (err) { |
| 935 | − dev_err(dev, "%s: Unable to start governor for the device\n", | |
| 936 | − __func__); | |
| 934 | + dev_err_probe(dev, err, | |
| 935 | + "%s: Unable to start governor for the device\n", | |
| 936 | + __func__); | |
| 937 | 937 | goto err_init; |
| 938 | 938 | } |
| 939 | 939 | create_sysfs_files(devfreq, devfreq->governor); |
| @@ -1665,9 +1665,9 @@ static ssize_t available_frequencies_show(struct device *d, · 725 unmodified lines | ||
| 1665 | 1665 | |
| 1666 | 1666 | mutex_lock(&df->lock); |
| 1667 | 1667 | |
| 1668 | − for (i = 0; i < df->profile->max_state; i++) | |
| 1668 | + for (i = 0; i < df->max_state; i++) | |
| 1669 | 1669 | count += scnprintf(&buf[count], (PAGE_SIZE - count - 2), |
| 1670 | − "%lu ", df->profile->freq_table[i]); | |
| 1670 | + "%lu ", df->freq_table[i]); | |
| 1671 | 1671 | |
| 1672 | 1672 | mutex_unlock(&df->lock); |
| 1673 | 1673 | /* Truncate the trailing space */ |
| @@ -1690,7 +1690,7 @@ static ssize_t trans_stat_show(struct device *dev, · 16 unmodified lines | ||
| 1690 | 1690 | |
| 1691 | 1691 | if (!df->profile) |
| 1692 | 1692 | return -EINVAL; |
| 1693 | − max_state = df->profile->max_state; | |
| 1693 | + max_state = df->max_state; | |
| 1694 | 1694 | |
| 1695 | 1695 | if (max_state == 0) |
| 1696 | 1696 | return sprintf(buf, "Not Supported.\n"); |
| @@ -1707,19 +1707,17 @@ static ssize_t trans_stat_show(struct device *dev, · 10 unmodified lines | ||
| 1707 | 1707 | len += sprintf(buf + len, " :"); |
| 1708 | 1708 | for (i = 0; i < max_state; i++) |
| 1709 | 1709 | len += sprintf(buf + len, "%10lu", |
| 1710 | − df->profile->freq_table[i]); | |
| 1710 | + df->freq_table[i]); | |
| 1711 | 1711 | |
| 1712 | 1712 | len += sprintf(buf + len, " time(ms)\n"); |
| 1713 | 1713 | |
| 1714 | 1714 | for (i = 0; i < max_state; i++) { |
| 1715 | − if (df->profile->freq_table[i] | |
| 1716 | − == df->previous_freq) { | |
| 1715 | + if (df->freq_table[i] == df->previous_freq) | |
| 1717 | 1716 | len += sprintf(buf + len, "*"); |
| 1718 | − } else { | |
| 1717 | + else | |
| 1719 | 1718 | len += sprintf(buf + len, " "); |
| 1720 | − } | |
| 1721 | − len += sprintf(buf + len, "%10lu:", | |
| 1722 | − df->profile->freq_table[i]); | |
| 1719 | + | |
| 1720 | + len += sprintf(buf + len, "%10lu:", df->freq_table[i]); | |
| 1723 | 1721 | for (j = 0; j < max_state; j++) |
| 1724 | 1722 | len += sprintf(buf + len, "%10u", |
| 1725 | 1723 | df->stats.trans_table[(i * max_state) + j]); |
| @@ -1743,7 +1741,7 @@ static ssize_t trans_stat_store(struct device *dev, · 17 unmodified lines | ||
| 1743 | 1741 | if (!df->profile) |
| 1744 | 1742 | return -EINVAL; |
| 1745 | 1743 | |
| 1746 | − if (df->profile->max_state == 0) | |
| 1744 | + if (df->max_state == 0) | |
| 1747 | 1745 | return count; |
| 1748 | 1746 | |
| 1749 | 1747 | err = kstrtoint(buf, 10, &value); |
| @@ -1751,11 +1749,11 @@ static ssize_t trans_stat_store(struct device *dev, · 1 unmodified line | ||
| 1751 | 1749 | return -EINVAL; |
| 1752 | 1750 | |
| 1753 | 1751 | mutex_lock(&df->lock); |
| 1754 | − memset(df->stats.time_in_state, 0, (df->profile->max_state * | |
| 1752 | + memset(df->stats.time_in_state, 0, (df->max_state * | |
| 1755 | 1753 | sizeof(*df->stats.time_in_state))); |
| 1756 | 1754 | memset(df->stats.trans_table, 0, array3_size(sizeof(unsigned int), |
| 1757 | − df->profile->max_state, | |
| 1758 | − df->profile->max_state)); | |
| 1755 | + df->max_state, | |
| 1756 | + df->max_state)); | |
| 1759 | 1757 | df->stats.total_trans = 0; |
| 1760 | 1758 | df->stats.last_update = get_jiffies_64(); |
| 1761 | 1759 | mutex_unlock(&df->lock); |
| @@ -519,15 +519,19 @@ static int of_get_devfreq_events(struct device_node *np, · 518 unmodified lines | ||
| 519 | 519 | |
| 520 | 520 | count = of_get_child_count(events_np); |
| 521 | 521 | desc = devm_kcalloc(dev, count, sizeof(*desc), GFP_KERNEL); |
| 522 | − if (!desc) | |
| 522 | + if (!desc) { | |
| 523 | + of_node_put(events_np); | |
| 523 | 524 | return -ENOMEM; |
| 525 | + } | |
| 524 | 526 | info->num_events = count; |
| 525 | 527 | |
| 526 | 528 | of_id = of_match_device(exynos_ppmu_id_match, dev); |
| 527 | 529 | if (of_id) |
| 528 | 530 | info->ppmu_type = (enum exynos_ppmu_type)of_id->data; |
| 529 | − else | |
| 531 | + else { | |
| 532 | + of_node_put(events_np); | |
| 530 | 533 | return -EINVAL; |
| 534 | + } | |
| 531 | 535 | |
| 532 | 536 | j = 0; |
| 533 | 537 | for_each_child_of_node(events_np, node) { |
| @@ -1,4 +1,4 @@ | ||
| 1 | − // SPDX-License-Identifier: GPL-2.0-only | |
| 1 | +// SPDX-License-Identifier: GPL-2.0-only | |
| 2 | 2 | /* |
| 3 | 3 | * linux/drivers/devfreq/governor_passive.c |
| 4 | 4 | * |
| @@ -14,10 +14,9 @@ · 9 unmodified lines | ||
| 14 | 14 | #include <linux/slab.h> |
| 15 | 15 | #include <linux/device.h> |
| 16 | 16 | #include <linux/devfreq.h> |
| 17 | +#include <linux/units.h> | |
| 17 | 18 | #include "governor.h" |
| 18 | 19 | |
| 19 | −#define HZ_PER_KHZ 1000 | |
| 20 | − | |
| 21 | 20 | static struct devfreq_cpu_data * |
| 22 | 21 | get_parent_cpu_data(struct devfreq_passive_data *p_data, |
| 23 | 22 | struct cpufreq_policy *policy) |
| @@ -34,6 +33,20 @@ get_parent_cpu_data(struct devfreq_passive_data *p_data, · 10 unmodified lines | ||
| 34 | 33 | return NULL; |
| 35 | 34 | } |
| 36 | 35 | |
| 36 | +static void delete_parent_cpu_data(struct devfreq_passive_data *p_data) | |
| 37 | +{ | |
| 38 | + struct devfreq_cpu_data *parent_cpu_data, *tmp; | |
| 39 | + | |
| 40 | + list_for_each_entry_safe(parent_cpu_data, tmp, &p_data->cpu_data_list, node) { | |
| 41 | + list_del(&parent_cpu_data->node); | |
| 42 | + | |
| 43 | + if (parent_cpu_data->opp_table) | |
| 44 | + dev_pm_opp_put_opp_table(parent_cpu_data->opp_table); | |
| 45 | + | |
| 46 | + kfree(parent_cpu_data); | |
| 47 | + } | |
| 48 | +} | |
| 49 | + | |
| 37 | 50 | static unsigned long get_target_freq_by_required_opp(struct device *p_dev, |
| 38 | 51 | struct opp_table *p_opp_table, |
| 39 | 52 | struct opp_table *opp_table, |
| @@ -131,18 +144,18 @@ static int get_target_freq_with_devfreq(struct devfreq *devfreq, · 91 unmodified lines | ||
| 131 | 144 | goto out; |
| 132 | 145 | |
| 133 | 146 | /* Use interpolation if required opps is not available */ |
| 134 | − for (i = 0; i < parent_devfreq->profile->max_state; i++) | |
| 135 | − if (parent_devfreq->profile->freq_table[i] == *freq) | |
| 147 | + for (i = 0; i < parent_devfreq->max_state; i++) | |
| 148 | + if (parent_devfreq->freq_table[i] == *freq) | |
| 136 | 149 | break; |
| 137 | 150 | |
| 138 | − if (i == parent_devfreq->profile->max_state) | |
| 151 | + if (i == parent_devfreq->max_state) | |
| 139 | 152 | return -EINVAL; |
| 140 | 153 | |
| 141 | − if (i < devfreq->profile->max_state) { | |
| 142 | − child_freq = devfreq->profile->freq_table[i]; | |
| 154 | + if (i < devfreq->max_state) { | |
| 155 | + child_freq = devfreq->freq_table[i]; | |
| 143 | 156 | } else { |
| 144 | − count = devfreq->profile->max_state; | |
| 145 | − child_freq = devfreq->profile->freq_table[count - 1]; | |
| 157 | + count = devfreq->max_state; | |
| 158 | + child_freq = devfreq->freq_table[count - 1]; | |
| 146 | 159 | } |
| 147 | 160 | |
| 148 | 161 | out: |
| @@ -222,8 +235,7 @@ static int cpufreq_passive_unregister_notifier(struct devfreq *devfreq) · 73 unmodified lines | ||
| 222 | 235 | { |
| 223 | 236 | struct devfreq_passive_data *p_data |
| 224 | 237 | = (struct devfreq_passive_data *)devfreq->data; |
| 225 | − struct devfreq_cpu_data *parent_cpu_data; | |
| 226 | − int cpu, ret = 0; | |
| 238 | + int ret; | |
| 227 | 239 | |
| 228 | 240 | if (p_data->nb.notifier_call) { |
| 229 | 241 | ret = cpufreq_unregister_notifier(&p_data->nb, |
| @@ -232,27 +244,9 @@ static int cpufreq_passive_unregister_notifier(struct devfreq *devfreq) · 2 unmodified lines | ||
| 232 | 244 | return ret; |
| 233 | 245 | } |
| 234 | 246 | |
| 235 | − for_each_possible_cpu(cpu) { | |
| 236 | − struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); | |
| 237 | − if (!policy) { | |
| 238 | − ret = -EINVAL; | |
| 239 | − continue; | |
| 240 | − } | |
| 241 | − | |
| 242 | − parent_cpu_data = get_parent_cpu_data(p_data, policy); | |
| 243 | − if (!parent_cpu_data) { | |
| 244 | − cpufreq_cpu_put(policy); | |
| 245 | − continue; | |
| 246 | − } | |
| 247 | + delete_parent_cpu_data(p_data); | |
| 247 | 248 | |
| 248 | − list_del(&parent_cpu_data->node); | |
| 249 | − if (parent_cpu_data->opp_table) | |
| 250 | − dev_pm_opp_put_opp_table(parent_cpu_data->opp_table); | |
| 251 | − kfree(parent_cpu_data); | |
| 252 | − cpufreq_cpu_put(policy); | |
| 253 | − } | |
| 254 | − | |
| 255 | − return ret; | |
| 249 | + return 0; | |
| 256 | 250 | } |
| 257 | 251 | |
| 258 | 252 | static int cpufreq_passive_register_notifier(struct devfreq *devfreq) |
| @@ -336,7 +330,6 @@ err_free_cpu_data: · 77 unmodified lines | ||
| 336 | 330 | err_put_policy: |
| 337 | 331 | cpufreq_cpu_put(policy); |
| 338 | 332 | err: |
| 339 | − WARN_ON(cpufreq_passive_unregister_notifier(devfreq)); | |
| 340 | 333 | |
| 341 | 334 | return ret; |
| 342 | 335 | } |
| @@ -407,8 +400,7 @@ static int devfreq_passive_event_handler(struct devfreq *devfreq, · 64 unmodified lines | ||
| 407 | 400 | if (!p_data) |
| 408 | 401 | return -EINVAL; |
| 409 | 402 | |
| 410 | − if (!p_data->this) | |
| 411 | − p_data->this = devfreq; | |
| 403 | + p_data->this = devfreq; | |
| 412 | 404 | |
| 413 | 405 | switch (event) { |
| 414 | 406 | case DEVFREQ_GOV_START: |
| @@ -148,6 +148,8 @@ struct devfreq_stats { · 147 unmodified lines | ||
| 148 | 148 | * reevaluate operable frequencies. Devfreq users may use |
| 149 | 149 | * devfreq.nb to the corresponding register notifier call chain. |
| 150 | 150 | * @work: delayed work for load monitoring. |
| 151 | + * @freq_table: current frequency table used by the devfreq driver. | |
| 152 | + * @max_state: count of entry present in the frequency table. | |
| 151 | 153 | * @previous_freq: previously configured frequency value. |
| 152 | 154 | * @last_status: devfreq user device info, performance statistics |
| 153 | 155 | * @data: Private data of the governor. The devfreq framework does not |
| @@ -185,6 +187,9 @@ struct devfreq { · 31 unmodified lines | ||
| 185 | 187 | struct notifier_block nb; |
| 186 | 188 | struct delayed_work work; |
| 187 | 189 | |
| 190 | + unsigned long *freq_table; | |
| 191 | + unsigned int max_state; | |
| 192 | + | |
| 188 | 193 | unsigned long previous_freq; |
| 189 | 194 | struct devfreq_dev_status last_status; |
| 190 | 195 | |