History

Merge tag 'devfreq-fixes-for-5.19-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux

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

Rafael J. Wysocki committed 4 years ago

Commit 589cb2c2 parents 03c765b f08fe6f4 files · +75 −76Browse files

Unified · Split

4 files
  1. drivers/devfreq/devfreq.c +37 −39
  2. drivers/devfreq/event/exynos-ppmu.c +6 −2
  3. drivers/devfreq/governor_passive.c +27 −35
  4. include/linux/devfreq.h +5 −0
drivers/devfreq/devfreq.c+37−39
@@ -123,7 +123,7 @@ void devfreq_get_freq_range(struct devfreq *devfreq, · 122 unmodified lines
123 unsigned long *min_freq,123 unsigned long *min_freq,
124 unsigned long *max_freq)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 s32 qos_min_freq, qos_max_freq;127 s32 qos_min_freq, qos_max_freq;
128 128
129 lockdep_assert_held(&devfreq->lock);129 lockdep_assert_held(&devfreq->lock);
@@ -133,11 +133,11 @@ void devfreq_get_freq_range(struct devfreq *devfreq, · 3 unmodified lines
133 * The devfreq drivers can initialize this in either ascending or133 * The devfreq drivers can initialize this in either ascending or
134 * descending order and devfreq core supports both.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 *min_freq = freq_table[0];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 } else {139 } else {
140 *min_freq = freq_table[devfreq->profile->max_state - 1];140 *min_freq = freq_table[devfreq->max_state - 1];
141 *max_freq = freq_table[0];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 int lev;170 int lev;
171 171
172 for (lev = 0; lev < devfreq->profile->max_state; lev++)172 for (lev = 0; lev < devfreq->max_state; lev++)
173 if (freq == devfreq->profile->freq_table[lev])173 if (freq == devfreq->freq_table[lev])
174 return lev;174 return lev;
175 175
176 return -EINVAL;176 return -EINVAL;
@@ -178,7 +178,6 @@ static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq) · 1 unmodified line
178 178
179static int set_freq_table(struct devfreq *devfreq)179static int set_freq_table(struct devfreq *devfreq)
180{180{
181 struct devfreq_dev_profile *profile = devfreq->profile;
182 struct dev_pm_opp *opp;181 struct dev_pm_opp *opp;
183 unsigned long freq;182 unsigned long freq;
184 int i, count;183 int i, count;
@@ -188,25 +187,22 @@ static int set_freq_table(struct devfreq *devfreq) · 3 unmodified lines
188 if (count <= 0)187 if (count <= 0)
189 return -EINVAL;188 return -EINVAL;
190 189
191 profile->max_state = count;190 devfreq->max_state = count;
192 profile->freq_table = devm_kcalloc(devfreq->dev.parent,191 devfreq->freq_table = devm_kcalloc(devfreq->dev.parent,
193 profile->max_state,192 devfreq->max_state,
194 sizeof(*profile->freq_table),193 sizeof(*devfreq->freq_table),
195 GFP_KERNEL);194 GFP_KERNEL);
196 if (!profile->freq_table) {195 if (!devfreq->freq_table)
197 profile->max_state = 0;
198 return -ENOMEM;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 opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &freq);199 opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &freq);
203 if (IS_ERR(opp)) {200 if (IS_ERR(opp)) {
204 devm_kfree(devfreq->dev.parent, profile->freq_table);201 devm_kfree(devfreq->dev.parent, devfreq->freq_table);
205 profile->max_state = 0;
206 return PTR_ERR(opp);202 return PTR_ERR(opp);
207 }203 }
208 dev_pm_opp_put(opp);204 dev_pm_opp_put(opp);
209 profile->freq_table[i] = freq;205 devfreq->freq_table[i] = freq;
210 }206 }
211 207
212 return 0;208 return 0;
@@ -246,7 +242,7 @@ int devfreq_update_status(struct devfreq *devfreq, unsigned long freq) · 33 unmodified lines
246 242
247 if (lev != prev_lev) {243 if (lev != prev_lev) {
248 devfreq->stats.trans_table[244 devfreq->stats.trans_table[
249 (prev_lev * devfreq->profile->max_state) + lev]++;245 (prev_lev * devfreq->max_state) + lev]++;
250 devfreq->stats.total_trans++;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 if (err < 0)831 if (err < 0)
836 goto err_dev;832 goto err_dev;
837 mutex_lock(&devfreq->lock);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 devfreq->scaling_min_freq = find_available_min_freq(devfreq);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 devfreq->stats.trans_table = devm_kzalloc(&devfreq->dev,870 devfreq->stats.trans_table = devm_kzalloc(&devfreq->dev,
872 array3_size(sizeof(unsigned int),871 array3_size(sizeof(unsigned int),
873 devfreq->profile->max_state,872 devfreq->max_state,
874 devfreq->profile->max_state),873 devfreq->max_state),
875 GFP_KERNEL);874 GFP_KERNEL);
876 if (!devfreq->stats.trans_table) {875 if (!devfreq->stats.trans_table) {
877 mutex_unlock(&devfreq->lock);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 devfreq->stats.time_in_state = devm_kcalloc(&devfreq->dev,881 devfreq->stats.time_in_state = devm_kcalloc(&devfreq->dev,
883 devfreq->profile->max_state,882 devfreq->max_state,
884 sizeof(*devfreq->stats.time_in_state),883 sizeof(*devfreq->stats.time_in_state),
885 GFP_KERNEL);884 GFP_KERNEL);
886 if (!devfreq->stats.time_in_state) {885 if (!devfreq->stats.time_in_state) {
@@ -932,8 +931,9 @@ struct devfreq *devfreq_add_device(struct device *dev, · 45 unmodified lines
932 err = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_START,931 err = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_START,
933 NULL);932 NULL);
934 if (err) {933 if (err) {
935 dev_err(dev, "%s: Unable to start governor for the device\n",934 dev_err_probe(dev, err,
936 __func__);935 "%s: Unable to start governor for the device\n",
936 __func__);
937 goto err_init;937 goto err_init;
938 }938 }
939 create_sysfs_files(devfreq, devfreq->governor);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 mutex_lock(&df->lock);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 count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),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 mutex_unlock(&df->lock);1672 mutex_unlock(&df->lock);
1673 /* Truncate the trailing space */1673 /* Truncate the trailing space */
@@ -1690,7 +1690,7 @@ static ssize_t trans_stat_show(struct device *dev, · 16 unmodified lines
1690 1690
1691 if (!df->profile)1691 if (!df->profile)
1692 return -EINVAL;1692 return -EINVAL;
1693 max_state = df->profile->max_state;1693 max_state = df->max_state;
1694 1694
1695 if (max_state == 0)1695 if (max_state == 0)
1696 return sprintf(buf, "Not Supported.\n");1696 return sprintf(buf, "Not Supported.\n");
@@ -1707,19 +1707,17 @@ static ssize_t trans_stat_show(struct device *dev, · 10 unmodified lines
1707 len += sprintf(buf + len, " :");1707 len += sprintf(buf + len, " :");
1708 for (i = 0; i < max_state; i++)1708 for (i = 0; i < max_state; i++)
1709 len += sprintf(buf + len, "%10lu",1709 len += sprintf(buf + len, "%10lu",
1710 df->profile->freq_table[i]);1710 df->freq_table[i]);
1711 1711
1712 len += sprintf(buf + len, " time(ms)\n");1712 len += sprintf(buf + len, " time(ms)\n");
1713 1713
1714 for (i = 0; i < max_state; i++) {1714 for (i = 0; i < max_state; i++) {
1715 if (df->profile->freq_table[i]1715 if (df->freq_table[i] == df->previous_freq)
1716 == df->previous_freq) {
1717 len += sprintf(buf + len, "*");1716 len += sprintf(buf + len, "*");
1718 } else {1717 else
1719 len += sprintf(buf + len, " ");1718 len += sprintf(buf + len, " ");
1720 }1719
1721 len += sprintf(buf + len, "%10lu:",1720 len += sprintf(buf + len, "%10lu:", df->freq_table[i]);
1722 df->profile->freq_table[i]);
1723 for (j = 0; j < max_state; j++)1721 for (j = 0; j < max_state; j++)
1724 len += sprintf(buf + len, "%10u",1722 len += sprintf(buf + len, "%10u",
1725 df->stats.trans_table[(i * max_state) + j]);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 if (!df->profile)1741 if (!df->profile)
1744 return -EINVAL;1742 return -EINVAL;
1745 1743
1746 if (df->profile->max_state == 0)1744 if (df->max_state == 0)
1747 return count;1745 return count;
1748 1746
1749 err = kstrtoint(buf, 10, &value);1747 err = kstrtoint(buf, 10, &value);
@@ -1751,11 +1749,11 @@ static ssize_t trans_stat_store(struct device *dev, · 1 unmodified line
1751 return -EINVAL;1749 return -EINVAL;
1752 1750
1753 mutex_lock(&df->lock);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 sizeof(*df->stats.time_in_state)));1753 sizeof(*df->stats.time_in_state)));
1756 memset(df->stats.trans_table, 0, array3_size(sizeof(unsigned int),1754 memset(df->stats.trans_table, 0, array3_size(sizeof(unsigned int),
1757 df->profile->max_state,1755 df->max_state,
1758 df->profile->max_state));1756 df->max_state));
1759 df->stats.total_trans = 0;1757 df->stats.total_trans = 0;
1760 df->stats.last_update = get_jiffies_64();1758 df->stats.last_update = get_jiffies_64();
1761 mutex_unlock(&df->lock);1759 mutex_unlock(&df->lock);
drivers/devfreq/event/exynos-ppmu.c+6−2
@@ -519,15 +519,19 @@ static int of_get_devfreq_events(struct device_node *np, · 518 unmodified lines
519 519
520 count = of_get_child_count(events_np);520 count = of_get_child_count(events_np);
521 desc = devm_kcalloc(dev, count, sizeof(*desc), GFP_KERNEL);521 desc = devm_kcalloc(dev, count, sizeof(*desc), GFP_KERNEL);
522 if (!desc)522 if (!desc) {
523 of_node_put(events_np);
523 return -ENOMEM;524 return -ENOMEM;
525 }
524 info->num_events = count;526 info->num_events = count;
525 527
526 of_id = of_match_device(exynos_ppmu_id_match, dev);528 of_id = of_match_device(exynos_ppmu_id_match, dev);
527 if (of_id)529 if (of_id)
528 info->ppmu_type = (enum exynos_ppmu_type)of_id->data;530 info->ppmu_type = (enum exynos_ppmu_type)of_id->data;
529 else531 else {
532 of_node_put(events_np);
530 return -EINVAL;533 return -EINVAL;
534 }
531 535
532 j = 0;536 j = 0;
533 for_each_child_of_node(events_np, node) {537 for_each_child_of_node(events_np, node) {
drivers/devfreq/governor_passive.c+27−35
@@ -1,4 +1,4 @@
1 // SPDX-License-Identifier: GPL-2.0-only1// SPDX-License-Identifier: GPL-2.0-only
2/*2/*
3 * linux/drivers/devfreq/governor_passive.c3 * linux/drivers/devfreq/governor_passive.c
4 *4 *
@@ -14,10 +14,9 @@ · 9 unmodified lines
14#include <linux/slab.h>14#include <linux/slab.h>
15#include <linux/device.h>15#include <linux/device.h>
16#include <linux/devfreq.h>16#include <linux/devfreq.h>
17#include <linux/units.h>
17#include "governor.h"18#include "governor.h"
18 19
19#define HZ_PER_KHZ 1000
20
21static struct devfreq_cpu_data *20static struct devfreq_cpu_data *
22get_parent_cpu_data(struct devfreq_passive_data *p_data,21get_parent_cpu_data(struct devfreq_passive_data *p_data,
23 struct cpufreq_policy *policy)22 struct cpufreq_policy *policy)
@@ -34,6 +33,20 @@ get_parent_cpu_data(struct devfreq_passive_data *p_data, · 10 unmodified lines
34 return NULL;33 return NULL;
35}34}
36 35
36static 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
37static unsigned long get_target_freq_by_required_opp(struct device *p_dev,50static unsigned long get_target_freq_by_required_opp(struct device *p_dev,
38 struct opp_table *p_opp_table,51 struct opp_table *p_opp_table,
39 struct opp_table *opp_table,52 struct opp_table *opp_table,
@@ -131,18 +144,18 @@ static int get_target_freq_with_devfreq(struct devfreq *devfreq, · 91 unmodified lines
131 goto out;144 goto out;
132 145
133 /* Use interpolation if required opps is not available */146 /* Use interpolation if required opps is not available */
134 for (i = 0; i < parent_devfreq->profile->max_state; i++)147 for (i = 0; i < parent_devfreq->max_state; i++)
135 if (parent_devfreq->profile->freq_table[i] == *freq)148 if (parent_devfreq->freq_table[i] == *freq)
136 break;149 break;
137 150
138 if (i == parent_devfreq->profile->max_state)151 if (i == parent_devfreq->max_state)
139 return -EINVAL;152 return -EINVAL;
140 153
141 if (i < devfreq->profile->max_state) {154 if (i < devfreq->max_state) {
142 child_freq = devfreq->profile->freq_table[i];155 child_freq = devfreq->freq_table[i];
143 } else {156 } else {
144 count = devfreq->profile->max_state;157 count = devfreq->max_state;
145 child_freq = devfreq->profile->freq_table[count - 1];158 child_freq = devfreq->freq_table[count - 1];
146 }159 }
147 160
148out:161out:
@@ -222,8 +235,7 @@ static int cpufreq_passive_unregister_notifier(struct devfreq *devfreq) · 73 unmodified lines
222{235{
223 struct devfreq_passive_data *p_data236 struct devfreq_passive_data *p_data
224 = (struct devfreq_passive_data *)devfreq->data;237 = (struct devfreq_passive_data *)devfreq->data;
225 struct devfreq_cpu_data *parent_cpu_data;238 int ret;
226 int cpu, ret = 0;
227 239
228 if (p_data->nb.notifier_call) {240 if (p_data->nb.notifier_call) {
229 ret = cpufreq_unregister_notifier(&p_data->nb,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 return ret;244 return ret;
233 }245 }
234 246
235 for_each_possible_cpu(cpu) {247 delete_parent_cpu_data(p_data);
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 248
248 list_del(&parent_cpu_data->node);249 return 0;
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;
256}250}
257 251
258static int cpufreq_passive_register_notifier(struct devfreq *devfreq)252static int cpufreq_passive_register_notifier(struct devfreq *devfreq)
@@ -336,7 +330,6 @@ err_free_cpu_data: · 77 unmodified lines
336err_put_policy:330err_put_policy:
337 cpufreq_cpu_put(policy);331 cpufreq_cpu_put(policy);
338err:332err:
339 WARN_ON(cpufreq_passive_unregister_notifier(devfreq));
340 333
341 return ret;334 return ret;
342}335}
@@ -407,8 +400,7 @@ static int devfreq_passive_event_handler(struct devfreq *devfreq, · 64 unmodified lines
407 if (!p_data)400 if (!p_data)
408 return -EINVAL;401 return -EINVAL;
409 402
410 if (!p_data->this)403 p_data->this = devfreq;
411 p_data->this = devfreq;
412 404
413 switch (event) {405 switch (event) {
414 case DEVFREQ_GOV_START:406 case DEVFREQ_GOV_START:
include/linux/devfreq.h+5−0
@@ -148,6 +148,8 @@ struct devfreq_stats { · 147 unmodified lines
148 * reevaluate operable frequencies. Devfreq users may use148 * reevaluate operable frequencies. Devfreq users may use
149 * devfreq.nb to the corresponding register notifier call chain.149 * devfreq.nb to the corresponding register notifier call chain.
150 * @work: delayed work for load monitoring.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 * @previous_freq: previously configured frequency value.153 * @previous_freq: previously configured frequency value.
152 * @last_status: devfreq user device info, performance statistics154 * @last_status: devfreq user device info, performance statistics
153 * @data: Private data of the governor. The devfreq framework does not155 * @data: Private data of the governor. The devfreq framework does not
@@ -185,6 +187,9 @@ struct devfreq { · 31 unmodified lines
185 struct notifier_block nb;187 struct notifier_block nb;
186 struct delayed_work work;188 struct delayed_work work;
187 189
190 unsigned long *freq_table;
191 unsigned int max_state;
192
188 unsigned long previous_freq;193 unsigned long previous_freq;
189 struct devfreq_dev_status last_status;194 struct devfreq_dev_status last_status;
190 195