+++ /dev/null
-From 2fb24f0d287f9cf2db2cd73f41dba8b5a6710453 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 2 Mar 2021 15:58:21 +0900
-Subject: PM / devfreq: Add cpu based scaling support to passive governor
-
-From: Saravana Kannan <skannan@codeaurora.org>
-
-[ Upstream commit a03dacb0316f74400846aaf144d6c73f4217ca08 ]
-
-Many CPU architectures have caches that can scale independent of the
-CPUs. Frequency scaling of the caches is necessary to make sure that the
-cache is not a performance bottleneck that leads to poor performance and
-power. The same idea applies for RAM/DDR.
-
-To achieve this, this patch adds support for cpu based scaling to the
-passive governor. This is accomplished by taking the current frequency
-of each CPU frequency domain and then adjust the frequency of the cache
-(or any devfreq device) based on the frequency of the CPUs. It listens
-to CPU frequency transition notifiers to keep itself up to date on the
-current CPU frequency.
-
-To decide the frequency of the device, the governor does one of the
-following:
-* Derives the optimal devfreq device opp from required-opps property of
- the parent cpu opp_table.
-
-* Scales the device frequency in proportion to the CPU frequency. So, if
- the CPUs are running at their max frequency, the device runs at its
- max frequency. If the CPUs are running at their min frequency, the
- device runs at its min frequency. It is interpolated for frequencies
- in between.
-
-Tested-by: Chen-Yu Tsai <wenst@chromium.org>
-Tested-by: Johnson Wang <johnson.wang@mediatek.com>
-Signed-off-by: Saravana Kannan <skannan@codeaurora.org>
-[Sibi: Integrated cpu-freqmap governor into passive_governor]
-Signed-off-by: Sibi Sankar <sibis@codeaurora.org>
-[Chanwoo: Fix conflict with latest code and cleanup code]
-Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
-Stable-dep-of: 08e23d05fa6d ("PM / devfreq: Fix buffer overflow in trans_stat_show")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/devfreq/governor.h | 22 +++
- drivers/devfreq/governor_passive.c | 298 +++++++++++++++++++++++++++--
- include/linux/devfreq.h | 17 +-
- 3 files changed, 323 insertions(+), 14 deletions(-)
-
-diff --git a/drivers/devfreq/governor.h b/drivers/devfreq/governor.h
-index 9a9495f94ac6..3c36c92c89a9 100644
---- a/drivers/devfreq/governor.h
-+++ b/drivers/devfreq/governor.h
-@@ -47,6 +47,28 @@
- #define DEVFREQ_GOV_ATTR_POLLING_INTERVAL BIT(0)
- #define DEVFREQ_GOV_ATTR_TIMER BIT(1)
-
-+/**
-+ * struct devfreq_cpu_data - Hold the per-cpu data
-+ * @dev: reference to cpu device.
-+ * @first_cpu: the cpumask of the first cpu of a policy.
-+ * @opp_table: reference to cpu opp table.
-+ * @cur_freq: the current frequency of the cpu.
-+ * @min_freq: the min frequency of the cpu.
-+ * @max_freq: the max frequency of the cpu.
-+ *
-+ * This structure stores the required cpu_data of a cpu.
-+ * This is auto-populated by the governor.
-+ */
-+struct devfreq_cpu_data {
-+ struct device *dev;
-+ unsigned int first_cpu;
-+
-+ struct opp_table *opp_table;
-+ unsigned int cur_freq;
-+ unsigned int min_freq;
-+ unsigned int max_freq;
-+};
-+
- /**
- * struct devfreq_governor - Devfreq policy governor
- * @node: list node - contains registered devfreq governors
-diff --git a/drivers/devfreq/governor_passive.c b/drivers/devfreq/governor_passive.c
-index fc09324a03e0..7f30088b500b 100644
---- a/drivers/devfreq/governor_passive.c
-+++ b/drivers/devfreq/governor_passive.c
-@@ -8,11 +8,85 @@
- */
-
- #include <linux/module.h>
-+#include <linux/cpu.h>
-+#include <linux/cpufreq.h>
-+#include <linux/cpumask.h>
-+#include <linux/slab.h>
- #include <linux/device.h>
- #include <linux/devfreq.h>
- #include "governor.h"
-
--static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
-+#define HZ_PER_KHZ 1000
-+
-+static unsigned long get_target_freq_by_required_opp(struct device *p_dev,
-+ struct opp_table *p_opp_table,
-+ struct opp_table *opp_table,
-+ unsigned long *freq)
-+{
-+ struct dev_pm_opp *opp = NULL, *p_opp = NULL;
-+ unsigned long target_freq;
-+
-+ if (!p_dev || !p_opp_table || !opp_table || !freq)
-+ return 0;
-+
-+ p_opp = devfreq_recommended_opp(p_dev, freq, 0);
-+ if (IS_ERR(p_opp))
-+ return 0;
-+
-+ opp = dev_pm_opp_xlate_required_opp(p_opp_table, opp_table, p_opp);
-+ dev_pm_opp_put(p_opp);
-+
-+ if (IS_ERR(opp))
-+ return 0;
-+
-+ target_freq = dev_pm_opp_get_freq(opp);
-+ dev_pm_opp_put(opp);
-+
-+ return target_freq;
-+}
-+
-+static int get_target_freq_with_cpufreq(struct devfreq *devfreq,
-+ unsigned long *target_freq)
-+{
-+ struct devfreq_passive_data *p_data =
-+ (struct devfreq_passive_data *)devfreq->data;
-+ struct devfreq_cpu_data *parent_cpu_data;
-+ unsigned long cpu, cpu_cur, cpu_min, cpu_max, cpu_percent;
-+ unsigned long dev_min, dev_max;
-+ unsigned long freq = 0;
-+
-+ for_each_online_cpu(cpu) {
-+ parent_cpu_data = p_data->parent_cpu_data[cpu];
-+ if (!parent_cpu_data || parent_cpu_data->first_cpu != cpu)
-+ continue;
-+
-+ /* Get target freq via required opps */
-+ cpu_cur = parent_cpu_data->cur_freq * HZ_PER_KHZ;
-+ freq = get_target_freq_by_required_opp(parent_cpu_data->dev,
-+ parent_cpu_data->opp_table,
-+ devfreq->opp_table, &cpu_cur);
-+ if (freq) {
-+ *target_freq = max(freq, *target_freq);
-+ continue;
-+ }
-+
-+ /* Use interpolation if required opps is not available */
-+ devfreq_get_freq_range(devfreq, &dev_min, &dev_max);
-+
-+ cpu_min = parent_cpu_data->min_freq;
-+ cpu_max = parent_cpu_data->max_freq;
-+ cpu_cur = parent_cpu_data->cur_freq;
-+
-+ cpu_percent = ((cpu_cur - cpu_min) * 100) / (cpu_max - cpu_min);
-+ freq = dev_min + mult_frac(dev_max - dev_min, cpu_percent, 100);
-+
-+ *target_freq = max(freq, *target_freq);
-+ }
-+
-+ return 0;
-+}
-+
-+static int get_target_freq_with_devfreq(struct devfreq *devfreq,
- unsigned long *freq)
- {
- struct devfreq_passive_data *p_data
-@@ -99,6 +173,181 @@ static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
- return 0;
- }
-
-+static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
-+ unsigned long *freq)
-+{
-+ struct devfreq_passive_data *p_data =
-+ (struct devfreq_passive_data *)devfreq->data;
-+ int ret;
-+
-+ if (!p_data)
-+ return -EINVAL;
-+
-+ /*
-+ * If the devfreq device with passive governor has the specific method
-+ * to determine the next frequency, should use the get_target_freq()
-+ * of struct devfreq_passive_data.
-+ */
-+ if (p_data->get_target_freq)
-+ return p_data->get_target_freq(devfreq, freq);
-+
-+ switch (p_data->parent_type) {
-+ case DEVFREQ_PARENT_DEV:
-+ ret = get_target_freq_with_devfreq(devfreq, freq);
-+ break;
-+ case CPUFREQ_PARENT_DEV:
-+ ret = get_target_freq_with_cpufreq(devfreq, freq);
-+ break;
-+ default:
-+ ret = -EINVAL;
-+ dev_err(&devfreq->dev, "Invalid parent type\n");
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+static int cpufreq_passive_notifier_call(struct notifier_block *nb,
-+ unsigned long event, void *ptr)
-+{
-+ struct devfreq_passive_data *p_data =
-+ container_of(nb, struct devfreq_passive_data, nb);
-+ struct devfreq *devfreq = (struct devfreq *)p_data->this;
-+ struct devfreq_cpu_data *parent_cpu_data;
-+ struct cpufreq_freqs *freqs = ptr;
-+ unsigned int cur_freq;
-+ int ret;
-+
-+ if (event != CPUFREQ_POSTCHANGE || !freqs ||
-+ !p_data->parent_cpu_data[freqs->policy->cpu])
-+ return 0;
-+
-+ parent_cpu_data = p_data->parent_cpu_data[freqs->policy->cpu];
-+ if (parent_cpu_data->cur_freq == freqs->new)
-+ return 0;
-+
-+ cur_freq = parent_cpu_data->cur_freq;
-+ parent_cpu_data->cur_freq = freqs->new;
-+
-+ mutex_lock(&devfreq->lock);
-+ ret = devfreq_update_target(devfreq, freqs->new);
-+ mutex_unlock(&devfreq->lock);
-+ if (ret) {
-+ parent_cpu_data->cur_freq = cur_freq;
-+ dev_err(&devfreq->dev, "failed to update the frequency.\n");
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+static int cpufreq_passive_unregister_notifier(struct devfreq *devfreq)
-+{
-+ struct devfreq_passive_data *p_data
-+ = (struct devfreq_passive_data *)devfreq->data;
-+ struct devfreq_cpu_data *parent_cpu_data;
-+ int cpu, ret;
-+
-+ if (p_data->nb.notifier_call) {
-+ ret = cpufreq_unregister_notifier(&p_data->nb,
-+ CPUFREQ_TRANSITION_NOTIFIER);
-+ if (ret < 0)
-+ return ret;
-+ }
-+
-+ for_each_possible_cpu(cpu) {
-+ parent_cpu_data = p_data->parent_cpu_data[cpu];
-+ if (!parent_cpu_data)
-+ continue;
-+
-+ if (parent_cpu_data->opp_table)
-+ dev_pm_opp_put_opp_table(parent_cpu_data->opp_table);
-+ kfree(parent_cpu_data);
-+ }
-+
-+ return 0;
-+}
-+
-+static int cpufreq_passive_register_notifier(struct devfreq *devfreq)
-+{
-+ struct devfreq_passive_data *p_data
-+ = (struct devfreq_passive_data *)devfreq->data;
-+ struct device *dev = devfreq->dev.parent;
-+ struct opp_table *opp_table = NULL;
-+ struct devfreq_cpu_data *parent_cpu_data;
-+ struct cpufreq_policy *policy;
-+ struct device *cpu_dev;
-+ unsigned int cpu;
-+ int ret;
-+
-+ p_data->nb.notifier_call = cpufreq_passive_notifier_call;
-+ ret = cpufreq_register_notifier(&p_data->nb, CPUFREQ_TRANSITION_NOTIFIER);
-+ if (ret) {
-+ dev_err(dev, "failed to register cpufreq notifier\n");
-+ p_data->nb.notifier_call = NULL;
-+ goto err;
-+ }
-+
-+ for_each_possible_cpu(cpu) {
-+ if (p_data->parent_cpu_data[cpu])
-+ continue;
-+
-+ policy = cpufreq_cpu_get(cpu);
-+ if (!policy) {
-+ ret = -EPROBE_DEFER;
-+ goto err;
-+ }
-+
-+ parent_cpu_data = kzalloc(sizeof(*parent_cpu_data),
-+ GFP_KERNEL);
-+ if (!parent_cpu_data) {
-+ ret = -ENOMEM;
-+ goto err_put_policy;
-+ }
-+
-+ cpu_dev = get_cpu_device(cpu);
-+ if (!cpu_dev) {
-+ dev_err(dev, "failed to get cpu device\n");
-+ ret = -ENODEV;
-+ goto err_free_cpu_data;
-+ }
-+
-+ opp_table = dev_pm_opp_get_opp_table(cpu_dev);
-+ if (IS_ERR(opp_table)) {
-+ dev_err(dev, "failed to get opp_table of cpu%d\n", cpu);
-+ ret = PTR_ERR(opp_table);
-+ goto err_free_cpu_data;
-+ }
-+
-+ parent_cpu_data->dev = cpu_dev;
-+ parent_cpu_data->opp_table = opp_table;
-+ parent_cpu_data->first_cpu = cpumask_first(policy->related_cpus);
-+ parent_cpu_data->cur_freq = policy->cur;
-+ parent_cpu_data->min_freq = policy->cpuinfo.min_freq;
-+ parent_cpu_data->max_freq = policy->cpuinfo.max_freq;
-+
-+ p_data->parent_cpu_data[cpu] = parent_cpu_data;
-+ cpufreq_cpu_put(policy);
-+ }
-+
-+ mutex_lock(&devfreq->lock);
-+ ret = devfreq_update_target(devfreq, 0L);
-+ mutex_unlock(&devfreq->lock);
-+ if (ret)
-+ dev_err(dev, "failed to update the frequency\n");
-+
-+ return ret;
-+
-+err_free_cpu_data:
-+ kfree(parent_cpu_data);
-+err_put_policy:
-+ cpufreq_cpu_put(policy);
-+err:
-+ WARN_ON(cpufreq_passive_unregister_notifier(devfreq));
-+
-+ return ret;
-+}
-+
- static int devfreq_passive_notifier_call(struct notifier_block *nb,
- unsigned long event, void *ptr)
- {
-@@ -131,30 +380,55 @@ static int devfreq_passive_notifier_call(struct notifier_block *nb,
- return NOTIFY_DONE;
- }
-
--static int devfreq_passive_event_handler(struct devfreq *devfreq,
-- unsigned int event, void *data)
-+static int devfreq_passive_unregister_notifier(struct devfreq *devfreq)
-+{
-+ struct devfreq_passive_data *p_data
-+ = (struct devfreq_passive_data *)devfreq->data;
-+ struct devfreq *parent = (struct devfreq *)p_data->parent;
-+ struct notifier_block *nb = &p_data->nb;
-+
-+ return devfreq_unregister_notifier(parent, nb, DEVFREQ_TRANSITION_NOTIFIER);
-+}
-+
-+static int devfreq_passive_register_notifier(struct devfreq *devfreq)
- {
- struct devfreq_passive_data *p_data
- = (struct devfreq_passive_data *)devfreq->data;
- struct devfreq *parent = (struct devfreq *)p_data->parent;
- struct notifier_block *nb = &p_data->nb;
-- int ret = 0;
-
- if (!parent)
- return -EPROBE_DEFER;
-
-+ nb->notifier_call = devfreq_passive_notifier_call;
-+ return devfreq_register_notifier(parent, nb, DEVFREQ_TRANSITION_NOTIFIER);
-+}
-+
-+static int devfreq_passive_event_handler(struct devfreq *devfreq,
-+ unsigned int event, void *data)
-+{
-+ struct devfreq_passive_data *p_data
-+ = (struct devfreq_passive_data *)devfreq->data;
-+ int ret = -EINVAL;
-+
-+ if (!p_data)
-+ return -EINVAL;
-+
-+ if (!p_data->this)
-+ p_data->this = devfreq;
-+
- switch (event) {
- case DEVFREQ_GOV_START:
-- if (!p_data->this)
-- p_data->this = devfreq;
--
-- nb->notifier_call = devfreq_passive_notifier_call;
-- ret = devfreq_register_notifier(parent, nb,
-- DEVFREQ_TRANSITION_NOTIFIER);
-+ if (p_data->parent_type == DEVFREQ_PARENT_DEV)
-+ ret = devfreq_passive_register_notifier(devfreq);
-+ else if (p_data->parent_type == CPUFREQ_PARENT_DEV)
-+ ret = cpufreq_passive_register_notifier(devfreq);
- break;
- case DEVFREQ_GOV_STOP:
-- WARN_ON(devfreq_unregister_notifier(parent, nb,
-- DEVFREQ_TRANSITION_NOTIFIER));
-+ if (p_data->parent_type == DEVFREQ_PARENT_DEV)
-+ WARN_ON(devfreq_passive_unregister_notifier(devfreq));
-+ else if (p_data->parent_type == CPUFREQ_PARENT_DEV)
-+ WARN_ON(cpufreq_passive_unregister_notifier(devfreq));
- break;
- default:
- break;
-diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
-index d94b9ed9443e..86ef2885c04b 100644
---- a/include/linux/devfreq.h
-+++ b/include/linux/devfreq.h
-@@ -38,6 +38,7 @@ enum devfreq_timer {
-
- struct devfreq;
- struct devfreq_governor;
-+struct devfreq_cpu_data;
- struct thermal_cooling_device;
-
- /**
-@@ -289,6 +290,11 @@ struct devfreq_simple_ondemand_data {
- #endif
-
- #if IS_ENABLED(CONFIG_DEVFREQ_GOV_PASSIVE)
-+enum devfreq_parent_dev_type {
-+ DEVFREQ_PARENT_DEV,
-+ CPUFREQ_PARENT_DEV,
-+};
-+
- /**
- * struct devfreq_passive_data - ``void *data`` fed to struct devfreq
- * and devfreq_add_device
-@@ -300,8 +306,11 @@ struct devfreq_simple_ondemand_data {
- * using governors except for passive governor.
- * If the devfreq device has the specific method to decide
- * the next frequency, should use this callback.
-- * @this: the devfreq instance of own device.
-- * @nb: the notifier block for DEVFREQ_TRANSITION_NOTIFIER list
-+ * @parent_type: the parent type of the device.
-+ * @this: the devfreq instance of own device.
-+ * @nb: the notifier block for DEVFREQ_TRANSITION_NOTIFIER or
-+ * CPUFREQ_TRANSITION_NOTIFIER list.
-+ * @parent_cpu_data: the state min/max/current frequency of all online cpu's.
- *
- * The devfreq_passive_data have to set the devfreq instance of parent
- * device with governors except for the passive governor. But, don't need to
-@@ -315,9 +324,13 @@ struct devfreq_passive_data {
- /* Optional callback to decide the next frequency of passvice device */
- int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
-
-+ /* Should set the type of parent device */
-+ enum devfreq_parent_dev_type parent_type;
-+
- /* For passive governor's internal use. Don't need to set them */
- struct devfreq *this;
- struct notifier_block nb;
-+ struct devfreq_cpu_data *parent_cpu_data[NR_CPUS];
- };
- #endif
-
---
-2.43.0
-
+++ /dev/null
-From 7cde1179118a6f4e0ea429fd4bb6659165ba0a96 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 1 Mar 2021 02:07:29 +0900
-Subject: PM / devfreq: Export devfreq_get_freq_range symbol within devfreq
-
-From: Chanwoo Choi <cw00.choi@samsung.com>
-
-[ Upstream commit 713472e53e6e53c985e283782b0fd76b8ecfd47e ]
-
-In order to get frequency range within devfreq governors,
-export devfreq_get_freq_range symbol within devfreq.
-
-Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
-Tested-by: Chen-Yu Tsai <wenst@chromium.org>
-Tested-by: Johnson Wang <johnson.wang@mediatek.com>
-Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
-Stable-dep-of: 08e23d05fa6d ("PM / devfreq: Fix buffer overflow in trans_stat_show")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/devfreq/devfreq.c | 20 ++++++++++++--------
- drivers/devfreq/governor.h | 2 ++
- 2 files changed, 14 insertions(+), 8 deletions(-)
-
-diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
-index 29a14b0ffe33..c8cee796a5a0 100644
---- a/drivers/devfreq/devfreq.c
-+++ b/drivers/devfreq/devfreq.c
-@@ -112,16 +112,16 @@ static unsigned long find_available_max_freq(struct devfreq *devfreq)
- }
-
- /**
-- * get_freq_range() - Get the current freq range
-+ * devfreq_get_freq_range() - Get the current freq range
- * @devfreq: the devfreq instance
- * @min_freq: the min frequency
- * @max_freq: the max frequency
- *
- * This takes into consideration all constraints.
- */
--static void get_freq_range(struct devfreq *devfreq,
-- unsigned long *min_freq,
-- unsigned long *max_freq)
-+void devfreq_get_freq_range(struct devfreq *devfreq,
-+ unsigned long *min_freq,
-+ unsigned long *max_freq)
- {
- unsigned long *freq_table = devfreq->profile->freq_table;
- s32 qos_min_freq, qos_max_freq;
-@@ -158,6 +158,7 @@ static void get_freq_range(struct devfreq *devfreq,
- if (*min_freq > *max_freq)
- *min_freq = *max_freq;
- }
-+EXPORT_SYMBOL(devfreq_get_freq_range);
-
- /**
- * devfreq_get_freq_level() - Lookup freq_table for the frequency
-@@ -418,7 +419,7 @@ int devfreq_update_target(struct devfreq *devfreq, unsigned long freq)
- err = devfreq->governor->get_target_freq(devfreq, &freq);
- if (err)
- return err;
-- get_freq_range(devfreq, &min_freq, &max_freq);
-+ devfreq_get_freq_range(devfreq, &min_freq, &max_freq);
-
- if (freq < min_freq) {
- freq = min_freq;
-@@ -785,6 +786,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
- {
- struct devfreq *devfreq;
- struct devfreq_governor *governor;
-+ unsigned long min_freq, max_freq;
- int err = 0;
-
- if (!dev || !profile || !governor_name) {
-@@ -849,6 +851,8 @@ struct devfreq *devfreq_add_device(struct device *dev,
- goto err_dev;
- }
-
-+ devfreq_get_freq_range(devfreq, &min_freq, &max_freq);
-+
- devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
- devfreq->opp_table = dev_pm_opp_get_opp_table(dev);
- if (IS_ERR(devfreq->opp_table))
-@@ -1560,7 +1564,7 @@ static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr,
- unsigned long min_freq, max_freq;
-
- mutex_lock(&df->lock);
-- get_freq_range(df, &min_freq, &max_freq);
-+ devfreq_get_freq_range(df, &min_freq, &max_freq);
- mutex_unlock(&df->lock);
-
- return sprintf(buf, "%lu\n", min_freq);
-@@ -1614,7 +1618,7 @@ static ssize_t max_freq_show(struct device *dev, struct device_attribute *attr,
- unsigned long min_freq, max_freq;
-
- mutex_lock(&df->lock);
-- get_freq_range(df, &min_freq, &max_freq);
-+ devfreq_get_freq_range(df, &min_freq, &max_freq);
- mutex_unlock(&df->lock);
-
- return sprintf(buf, "%lu\n", max_freq);
-@@ -1928,7 +1932,7 @@ static int devfreq_summary_show(struct seq_file *s, void *data)
-
- mutex_lock(&devfreq->lock);
- cur_freq = devfreq->previous_freq;
-- get_freq_range(devfreq, &min_freq, &max_freq);
-+ devfreq_get_freq_range(devfreq, &min_freq, &max_freq);
- timer = devfreq->profile->timer;
-
- if (IS_SUPPORTED_ATTR(devfreq->governor->attrs, POLLING_INTERVAL))
-diff --git a/drivers/devfreq/governor.h b/drivers/devfreq/governor.h
-index 2d69a0ce6291..9a9495f94ac6 100644
---- a/drivers/devfreq/governor.h
-+++ b/drivers/devfreq/governor.h
-@@ -86,6 +86,8 @@ int devfreq_remove_governor(struct devfreq_governor *governor);
-
- int devfreq_update_status(struct devfreq *devfreq, unsigned long freq);
- int devfreq_update_target(struct devfreq *devfreq, unsigned long freq);
-+void devfreq_get_freq_range(struct devfreq *devfreq, unsigned long *min_freq,
-+ unsigned long *max_freq);
-
- static inline int devfreq_update_stats(struct devfreq *df)
- {
---
-2.43.0
-
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
- Documentation/ABI/testing/sysfs-class-devfreq | 3 +
- drivers/devfreq/devfreq.c | 57 +++++++++++++------
- 2 files changed, 42 insertions(+), 18 deletions(-)
+ Documentation/ABI/testing/sysfs-class-devfreq | 3 +
+ drivers/devfreq/devfreq.c | 59 +++++++++++++++++---------
+ 2 files changed, 43 insertions(+), 19 deletions(-)
-diff --git a/Documentation/ABI/testing/sysfs-class-devfreq b/Documentation/ABI/testing/sysfs-class-devfreq
-index 5e6b74f30406..1e7e0bb4c14e 100644
--- a/Documentation/ABI/testing/sysfs-class-devfreq
+++ b/Documentation/ABI/testing/sysfs-class-devfreq
@@ -52,6 +52,9 @@ Description:
What: /sys/class/devfreq/.../available_frequencies
Date: October 2012
Contact: Nishanth Menon <nm@ti.com>
-diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
-index 14b83b8531d7..96dc49c207c7 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
-@@ -1656,7 +1656,7 @@ static ssize_t trans_stat_show(struct device *dev,
+@@ -1653,7 +1653,7 @@ static ssize_t trans_stat_show(struct de
struct device_attribute *attr, char *buf)
{
struct devfreq *df = to_devfreq(dev);
int i, j;
unsigned int max_state;
-@@ -1665,7 +1665,7 @@ static ssize_t trans_stat_show(struct device *dev,
- max_state = df->max_state;
+@@ -1662,7 +1662,7 @@ static ssize_t trans_stat_show(struct de
+ max_state = df->profile->max_state;
if (max_state == 0)
- return sprintf(buf, "Not Supported.\n");
mutex_lock(&df->lock);
if (!df->stop_polling &&
-@@ -1675,31 +1675,52 @@ static ssize_t trans_stat_show(struct device *dev,
+@@ -1672,33 +1672,54 @@ static ssize_t trans_stat_show(struct de
}
mutex_unlock(&df->lock);
- len += sprintf(buf + len, " :");
- for (i = 0; i < max_state; i++)
- len += sprintf(buf + len, "%10lu",
-- df->freq_table[i]);
+- df->profile->freq_table[i]);
+ len += scnprintf(buf + len, PAGE_SIZE - len, " From : To\n");
+ len += scnprintf(buf + len, PAGE_SIZE - len, " :");
+ for (i = 0; i < max_state; i++) {
+ if (len >= PAGE_SIZE - 1)
+ break;
+ len += scnprintf(buf + len, PAGE_SIZE - len, "%10lu",
-+ df->freq_table[i]);
++ df->profile->freq_table[i]);
+ }
+ if (len >= PAGE_SIZE - 1)
+ return PAGE_SIZE - 1;
for (i = 0; i < max_state; i++) {
+ if (len >= PAGE_SIZE - 1)
+ break;
- if (df->freq_table[i] == df->previous_freq)
+ if (df->profile->freq_table[i]
+ == df->previous_freq) {
- len += sprintf(buf + len, "*");
+ len += scnprintf(buf + len, PAGE_SIZE - len, "*");
- else
+ } else {
- len += sprintf(buf + len, " ");
+ len += scnprintf(buf + len, PAGE_SIZE - len, " ");
+ }
+- len += sprintf(buf + len, "%10lu:",
+- df->profile->freq_table[i]);
+- for (j = 0; j < max_state; j++)
+- len += sprintf(buf + len, "%10u",
+- df->stats.trans_table[(i * max_state) + j]);
+ if (len >= PAGE_SIZE - 1)
+ break;
+
+ len += scnprintf(buf + len, PAGE_SIZE - len, "%10lu:",
-+ df->freq_table[i]);
++ df->profile->freq_table[i]);
+ for (j = 0; j < max_state; j++) {
+ if (len >= PAGE_SIZE - 1)
+ break;
+ jiffies64_to_msecs(df->stats.time_in_state[i]));
+ }
-- len += sprintf(buf + len, "%10lu:", df->freq_table[i]);
-- for (j = 0; j < max_state; j++)
-- len += sprintf(buf + len, "%10u",
-- df->stats.trans_table[(i * max_state) + j]);
+- len += sprintf(buf + len, "%10llu\n", (u64)
+- jiffies64_to_msecs(df->stats.time_in_state[i]));
+ if (len < PAGE_SIZE - 1)
+ len += scnprintf(buf + len, PAGE_SIZE - len, "Total transition : %u\n",
+ df->stats.total_trans);
-
-- len += sprintf(buf + len, "%10llu\n", (u64)
-- jiffies64_to_msecs(df->stats.time_in_state[i]));
++
+ if (len >= PAGE_SIZE - 1) {
+ pr_warn_once("devfreq transition table exceeds PAGE_SIZE. Disabling\n");
+ return -EFBIG;
return len;
}
---
-2.43.0
-
+++ /dev/null
-From f88a95b0eed454c5ae1dd276270a92bbdcd276e9 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 14 Jun 2022 13:06:59 +0200
-Subject: PM / devfreq: Fix kernel panic with cpu based scaling to passive gov
-
-From: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
-
-[ Upstream commit 57e00b40033a376de3f3cf0bb9bf7590d2dd679d ]
-
-The cpufreq passive register notifier can PROBE_DEFER and the devfreq
-struct is freed and then reallocaed on probe retry.
-The current logic assume that the code can't PROBE_DEFER so the devfreq
-struct in the this variable in devfreq_passive_data is assumed to be
-(if already set) always correct.
-This cause kernel panic as the code try to access the wrong address.
-To correctly handle this, update the this variable in
-devfreq_passive_data to the devfreq reallocated struct.
-
-Fixes: a03dacb0316f ("PM / devfreq: Add cpu based scaling support to passive governor")
-Signed-off-by: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
-Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/devfreq/governor_passive.c | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
-diff --git a/drivers/devfreq/governor_passive.c b/drivers/devfreq/governor_passive.c
-index c516d3733267..f06d9b6b96b5 100644
---- a/drivers/devfreq/governor_passive.c
-+++ b/drivers/devfreq/governor_passive.c
-@@ -363,8 +363,7 @@ static int devfreq_passive_event_handler(struct devfreq *devfreq,
- if (!p_data)
- return -EINVAL;
-
-- if (!p_data->this)
-- p_data->this = devfreq;
-+ p_data->this = devfreq;
-
- switch (event) {
- case DEVFREQ_GOV_START:
---
-2.43.0
-
+++ /dev/null
-From a53d3ccecf54330cba08207ee470a3456b785b13 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 20 Jun 2022 00:29:39 +0200
-Subject: PM / devfreq: Fix kernel warning with cpufreq passive register fail
-
-From: Christian Marangi <ansuelsmth@gmail.com>
-
-[ Upstream commit 82c66d2bbbeda9e493487e7413769087a0b46250 ]
-
-Remove cpufreq_passive_unregister_notifier from
-cpufreq_passive_register_notifier in case of error as devfreq core
-already call unregister on GOV_START fail.
-
-This fix the kernel always printing a WARN on governor PROBE_DEFER as
-cpufreq_passive_unregister_notifier is called two times and return
-error on the second call as the cpufreq is already unregistered.
-
-Fixes: a03dacb0316f ("PM / devfreq: Add cpu based scaling support to passive governor")
-Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
-Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/devfreq/governor_passive.c | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/drivers/devfreq/governor_passive.c b/drivers/devfreq/governor_passive.c
-index 9997332af3df..c516d3733267 100644
---- a/drivers/devfreq/governor_passive.c
-+++ b/drivers/devfreq/governor_passive.c
-@@ -293,7 +293,6 @@ static int cpufreq_passive_register_notifier(struct devfreq *devfreq)
- err_put_policy:
- cpufreq_cpu_put(policy);
- err:
-- WARN_ON(cpufreq_passive_unregister_notifier(devfreq));
-
- return ret;
- }
---
-2.43.0
-
+++ /dev/null
-From c9afa575b61ed545eddab28966f19b9fc329906c Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 15 Jun 2022 01:09:50 +0200
-Subject: PM / devfreq: Mute warning on governor PROBE_DEFER
-
-From: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
-
-[ Upstream commit e52b045fe07d7874474665c843befa7521853234 ]
-
-Don't print warning when a governor PROBE_DEFER as it's not a real
-GOV_START fail.
-
-Fixes: a03dacb0316f ("PM / devfreq: Add cpu based scaling support to passive governor")
-Signed-off-by: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
-Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/devfreq/devfreq.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
-index 3fa275ba8cbd..6af8200992a3 100644
---- a/drivers/devfreq/devfreq.c
-+++ b/drivers/devfreq/devfreq.c
-@@ -951,8 +951,9 @@ struct devfreq *devfreq_add_device(struct device *dev,
- err = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_START,
- NULL);
- if (err) {
-- dev_err(dev, "%s: Unable to start governor for the device\n",
-- __func__);
-+ dev_err_probe(dev, err,
-+ "%s: Unable to start governor for the device\n",
-+ __func__);
- goto err_init;
- }
- create_sysfs_files(devfreq, devfreq->governor);
---
-2.43.0
-
+++ /dev/null
-From 38a1b2738c0915ede2421ea5df780f4ccbc99da0 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 2 Mar 2021 17:22:50 +0900
-Subject: PM / devfreq: passive: Reduce duplicate code when passive_devfreq
- case
-
-From: Chanwoo Choi <cw00.choi@samsung.com>
-
-[ Upstream commit 05723e71234b60a1a47313ea1a889797ec648f1c ]
-
-In order to keep the consistent coding style between passive_devfreq
-and passive_cpufreq, use common code for handling required opp property.
-Also remove the unneed conditional statement and unify the comment
-of both passive_devfreq and passive_cpufreq when getting the target frequency.
-
-Tested-by: Chen-Yu Tsai <wenst@chromium.org>
-Tested-by: Johnson Wang <johnson.wang@mediatek.com>
-Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
-Stable-dep-of: 08e23d05fa6d ("PM / devfreq: Fix buffer overflow in trans_stat_show")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/devfreq/governor_passive.c | 66 ++++--------------------------
- 1 file changed, 8 insertions(+), 58 deletions(-)
-
-diff --git a/drivers/devfreq/governor_passive.c b/drivers/devfreq/governor_passive.c
-index 7f30088b500b..ffcce613a48c 100644
---- a/drivers/devfreq/governor_passive.c
-+++ b/drivers/devfreq/governor_passive.c
-@@ -93,65 +93,16 @@ static int get_target_freq_with_devfreq(struct devfreq *devfreq,
- = (struct devfreq_passive_data *)devfreq->data;
- struct devfreq *parent_devfreq = (struct devfreq *)p_data->parent;
- unsigned long child_freq = ULONG_MAX;
-- struct dev_pm_opp *opp, *p_opp;
- int i, count;
-
-- /*
-- * If the devfreq device with passive governor has the specific method
-- * to determine the next frequency, should use the get_target_freq()
-- * of struct devfreq_passive_data.
-- */
-- if (p_data->get_target_freq)
-- return p_data->get_target_freq(devfreq, freq);
-+ /* Get target freq via required opps */
-+ child_freq = get_target_freq_by_required_opp(parent_devfreq->dev.parent,
-+ parent_devfreq->opp_table,
-+ devfreq->opp_table, freq);
-+ if (child_freq)
-+ goto out;
-
-- /*
-- * If the parent and passive devfreq device uses the OPP table,
-- * get the next frequency by using the OPP table.
-- */
--
-- /*
-- * - parent devfreq device uses the governors except for passive.
-- * - passive devfreq device uses the passive governor.
-- *
-- * Each devfreq has the OPP table. After deciding the new frequency
-- * from the governor of parent devfreq device, the passive governor
-- * need to get the index of new frequency on OPP table of parent
-- * device. And then the index is used for getting the suitable
-- * new frequency for passive devfreq device.
-- */
-- if (!devfreq->profile || !devfreq->profile->freq_table
-- || devfreq->profile->max_state <= 0)
-- return -EINVAL;
--
-- /*
-- * The passive governor have to get the correct frequency from OPP
-- * list of parent device. Because in this case, *freq is temporary
-- * value which is decided by ondemand governor.
-- */
-- if (devfreq->opp_table && parent_devfreq->opp_table) {
-- p_opp = devfreq_recommended_opp(parent_devfreq->dev.parent,
-- freq, 0);
-- if (IS_ERR(p_opp))
-- return PTR_ERR(p_opp);
--
-- opp = dev_pm_opp_xlate_required_opp(parent_devfreq->opp_table,
-- devfreq->opp_table, p_opp);
-- dev_pm_opp_put(p_opp);
--
-- if (IS_ERR(opp))
-- goto no_required_opp;
--
-- *freq = dev_pm_opp_get_freq(opp);
-- dev_pm_opp_put(opp);
--
-- return 0;
-- }
--
--no_required_opp:
-- /*
-- * Get the OPP table's index of decided frequency by governor
-- * of parent device.
-- */
-+ /* Use interpolation if required opps is not available */
- for (i = 0; i < parent_devfreq->profile->max_state; i++)
- if (parent_devfreq->profile->freq_table[i] == *freq)
- break;
-@@ -159,7 +110,6 @@ static int get_target_freq_with_devfreq(struct devfreq *devfreq,
- if (i == parent_devfreq->profile->max_state)
- return -EINVAL;
-
-- /* Get the suitable frequency by using index of parent device. */
- if (i < devfreq->profile->max_state) {
- child_freq = devfreq->profile->freq_table[i];
- } else {
-@@ -167,7 +117,7 @@ static int get_target_freq_with_devfreq(struct devfreq *devfreq,
- child_freq = devfreq->profile->freq_table[count - 1];
- }
-
-- /* Return the suitable frequency for passive device. */
-+out:
- *freq = child_freq;
-
- return 0;
---
-2.43.0
-
+++ /dev/null
-From 648562db5d7b7e518c785b460472ccd2fbdb1ecc Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 20 Jun 2022 00:03:51 +0200
-Subject: PM / devfreq: Rework freq_table to be local to devfreq struct
-
-From: Christian Marangi <ansuelsmth@gmail.com>
-
-[ Upstream commit b5d281f6c16dd432b618bdfd36ddba1a58d5b603 ]
-
-On a devfreq PROBE_DEFER, the freq_table in the driver profile struct,
-is never reset and may be leaved in an undefined state.
-
-This comes from the fact that we store the freq_table in the driver
-profile struct that is commonly defined as static and not reset on
-PROBE_DEFER.
-We currently skip the reinit of the freq_table if we found
-it's already defined since a driver may declare his own freq_table.
-
-This logic is flawed in the case devfreq core generate a freq_table, set
-it in the profile struct and then PROBE_DEFER, freeing the freq_table.
-In this case devfreq will found a NOT NULL freq_table that has been
-freed, skip the freq_table generation and probe the driver based on the
-wrong table.
-
-To fix this and correctly handle PROBE_DEFER, use a local freq_table and
-max_state in the devfreq struct and never modify the freq_table present
-in the profile struct if it does provide it.
-
-Fixes: 0ec09ac2cebe ("PM / devfreq: Set the freq_table of devfreq device")
-Cc: stable@vger.kernel.org
-Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
-Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
-Stable-dep-of: 08e23d05fa6d ("PM / devfreq: Fix buffer overflow in trans_stat_show")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/devfreq/devfreq.c | 71 ++++++++++++++----------------
- drivers/devfreq/governor_passive.c | 14 +++---
- include/linux/devfreq.h | 5 +++
- 3 files changed, 46 insertions(+), 44 deletions(-)
-
-diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
-index c8cee796a5a0..14b83b8531d7 100644
---- a/drivers/devfreq/devfreq.c
-+++ b/drivers/devfreq/devfreq.c
-@@ -123,7 +123,7 @@ void devfreq_get_freq_range(struct devfreq *devfreq,
- unsigned long *min_freq,
- unsigned long *max_freq)
- {
-- unsigned long *freq_table = devfreq->profile->freq_table;
-+ unsigned long *freq_table = devfreq->freq_table;
- s32 qos_min_freq, qos_max_freq;
-
- lockdep_assert_held(&devfreq->lock);
-@@ -133,11 +133,11 @@ void devfreq_get_freq_range(struct devfreq *devfreq,
- * The devfreq drivers can initialize this in either ascending or
- * descending order and devfreq core supports both.
- */
-- if (freq_table[0] < freq_table[devfreq->profile->max_state - 1]) {
-+ if (freq_table[0] < freq_table[devfreq->max_state - 1]) {
- *min_freq = freq_table[0];
-- *max_freq = freq_table[devfreq->profile->max_state - 1];
-+ *max_freq = freq_table[devfreq->max_state - 1];
- } else {
-- *min_freq = freq_table[devfreq->profile->max_state - 1];
-+ *min_freq = freq_table[devfreq->max_state - 1];
- *max_freq = freq_table[0];
- }
-
-@@ -169,8 +169,8 @@ static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq)
- {
- int lev;
-
-- for (lev = 0; lev < devfreq->profile->max_state; lev++)
-- if (freq == devfreq->profile->freq_table[lev])
-+ for (lev = 0; lev < devfreq->max_state; lev++)
-+ if (freq == devfreq->freq_table[lev])
- return lev;
-
- return -EINVAL;
-@@ -178,7 +178,6 @@ static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq)
-
- static int set_freq_table(struct devfreq *devfreq)
- {
-- struct devfreq_dev_profile *profile = devfreq->profile;
- struct dev_pm_opp *opp;
- unsigned long freq;
- int i, count;
-@@ -188,25 +187,22 @@ static int set_freq_table(struct devfreq *devfreq)
- if (count <= 0)
- return -EINVAL;
-
-- profile->max_state = count;
-- profile->freq_table = devm_kcalloc(devfreq->dev.parent,
-- profile->max_state,
-- sizeof(*profile->freq_table),
-- GFP_KERNEL);
-- if (!profile->freq_table) {
-- profile->max_state = 0;
-+ devfreq->max_state = count;
-+ devfreq->freq_table = devm_kcalloc(devfreq->dev.parent,
-+ devfreq->max_state,
-+ sizeof(*devfreq->freq_table),
-+ GFP_KERNEL);
-+ if (!devfreq->freq_table)
- return -ENOMEM;
-- }
-
-- for (i = 0, freq = 0; i < profile->max_state; i++, freq++) {
-+ for (i = 0, freq = 0; i < devfreq->max_state; i++, freq++) {
- opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &freq);
- if (IS_ERR(opp)) {
-- devm_kfree(devfreq->dev.parent, profile->freq_table);
-- profile->max_state = 0;
-+ devm_kfree(devfreq->dev.parent, devfreq->freq_table);
- return PTR_ERR(opp);
- }
- dev_pm_opp_put(opp);
-- profile->freq_table[i] = freq;
-+ devfreq->freq_table[i] = freq;
- }
-
- return 0;
-@@ -246,7 +242,7 @@ int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
-
- if (lev != prev_lev) {
- devfreq->stats.trans_table[
-- (prev_lev * devfreq->profile->max_state) + lev]++;
-+ (prev_lev * devfreq->max_state) + lev]++;
- devfreq->stats.total_trans++;
- }
-
-@@ -835,6 +831,9 @@ struct devfreq *devfreq_add_device(struct device *dev,
- if (err < 0)
- goto err_dev;
- mutex_lock(&devfreq->lock);
-+ } else {
-+ devfreq->freq_table = devfreq->profile->freq_table;
-+ devfreq->max_state = devfreq->profile->max_state;
- }
-
- devfreq->scaling_min_freq = find_available_min_freq(devfreq);
-@@ -870,8 +869,8 @@ struct devfreq *devfreq_add_device(struct device *dev,
-
- devfreq->stats.trans_table = devm_kzalloc(&devfreq->dev,
- array3_size(sizeof(unsigned int),
-- devfreq->profile->max_state,
-- devfreq->profile->max_state),
-+ devfreq->max_state,
-+ devfreq->max_state),
- GFP_KERNEL);
- if (!devfreq->stats.trans_table) {
- mutex_unlock(&devfreq->lock);
-@@ -880,7 +879,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
- }
-
- devfreq->stats.time_in_state = devm_kcalloc(&devfreq->dev,
-- devfreq->profile->max_state,
-+ devfreq->max_state,
- sizeof(*devfreq->stats.time_in_state),
- GFP_KERNEL);
- if (!devfreq->stats.time_in_state) {
-@@ -1638,9 +1637,9 @@ static ssize_t available_frequencies_show(struct device *d,
-
- mutex_lock(&df->lock);
-
-- for (i = 0; i < df->profile->max_state; i++)
-+ for (i = 0; i < df->max_state; i++)
- count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
-- "%lu ", df->profile->freq_table[i]);
-+ "%lu ", df->freq_table[i]);
-
- mutex_unlock(&df->lock);
- /* Truncate the trailing space */
-@@ -1663,7 +1662,7 @@ static ssize_t trans_stat_show(struct device *dev,
-
- if (!df->profile)
- return -EINVAL;
-- max_state = df->profile->max_state;
-+ max_state = df->max_state;
-
- if (max_state == 0)
- return sprintf(buf, "Not Supported.\n");
-@@ -1680,19 +1679,17 @@ static ssize_t trans_stat_show(struct device *dev,
- len += sprintf(buf + len, " :");
- for (i = 0; i < max_state; i++)
- len += sprintf(buf + len, "%10lu",
-- df->profile->freq_table[i]);
-+ df->freq_table[i]);
-
- len += sprintf(buf + len, " time(ms)\n");
-
- for (i = 0; i < max_state; i++) {
-- if (df->profile->freq_table[i]
-- == df->previous_freq) {
-+ if (df->freq_table[i] == df->previous_freq)
- len += sprintf(buf + len, "*");
-- } else {
-+ else
- len += sprintf(buf + len, " ");
-- }
-- len += sprintf(buf + len, "%10lu:",
-- df->profile->freq_table[i]);
-+
-+ len += sprintf(buf + len, "%10lu:", df->freq_table[i]);
- for (j = 0; j < max_state; j++)
- len += sprintf(buf + len, "%10u",
- df->stats.trans_table[(i * max_state) + j]);
-@@ -1716,7 +1713,7 @@ static ssize_t trans_stat_store(struct device *dev,
- if (!df->profile)
- return -EINVAL;
-
-- if (df->profile->max_state == 0)
-+ if (df->max_state == 0)
- return count;
-
- err = kstrtoint(buf, 10, &value);
-@@ -1724,11 +1721,11 @@ static ssize_t trans_stat_store(struct device *dev,
- return -EINVAL;
-
- mutex_lock(&df->lock);
-- memset(df->stats.time_in_state, 0, (df->profile->max_state *
-+ memset(df->stats.time_in_state, 0, (df->max_state *
- sizeof(*df->stats.time_in_state)));
- memset(df->stats.trans_table, 0, array3_size(sizeof(unsigned int),
-- df->profile->max_state,
-- df->profile->max_state));
-+ df->max_state,
-+ df->max_state));
- df->stats.total_trans = 0;
- df->stats.last_update = get_jiffies_64();
- mutex_unlock(&df->lock);
-diff --git a/drivers/devfreq/governor_passive.c b/drivers/devfreq/governor_passive.c
-index ffcce613a48c..9997332af3df 100644
---- a/drivers/devfreq/governor_passive.c
-+++ b/drivers/devfreq/governor_passive.c
-@@ -103,18 +103,18 @@ static int get_target_freq_with_devfreq(struct devfreq *devfreq,
- goto out;
-
- /* Use interpolation if required opps is not available */
-- for (i = 0; i < parent_devfreq->profile->max_state; i++)
-- if (parent_devfreq->profile->freq_table[i] == *freq)
-+ for (i = 0; i < parent_devfreq->max_state; i++)
-+ if (parent_devfreq->freq_table[i] == *freq)
- break;
-
-- if (i == parent_devfreq->profile->max_state)
-+ if (i == parent_devfreq->max_state)
- return -EINVAL;
-
-- if (i < devfreq->profile->max_state) {
-- child_freq = devfreq->profile->freq_table[i];
-+ if (i < devfreq->max_state) {
-+ child_freq = devfreq->freq_table[i];
- } else {
-- count = devfreq->profile->max_state;
-- child_freq = devfreq->profile->freq_table[count - 1];
-+ count = devfreq->max_state;
-+ child_freq = devfreq->freq_table[count - 1];
- }
-
- out:
-diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
-index 86ef2885c04b..6084003ea509 100644
---- a/include/linux/devfreq.h
-+++ b/include/linux/devfreq.h
-@@ -148,6 +148,8 @@ struct devfreq_stats {
- * reevaluate operable frequencies. Devfreq users may use
- * devfreq.nb to the corresponding register notifier call chain.
- * @work: delayed work for load monitoring.
-+ * @freq_table: current frequency table used by the devfreq driver.
-+ * @max_state: count of entry present in the frequency table.
- * @previous_freq: previously configured frequency value.
- * @last_status: devfreq user device info, performance statistics
- * @data: devfreq driver pass to governors, governor should not change it.
-@@ -185,6 +187,9 @@ struct devfreq {
- struct notifier_block nb;
- struct delayed_work work;
-
-+ unsigned long *freq_table;
-+ unsigned int max_state;
-+
- unsigned long previous_freq;
- struct devfreq_dev_status last_status;
-
---
-2.43.0
-
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
- drivers/devfreq/devfreq.c | 24 ++++++++++++++++++++++--
+ drivers/devfreq/devfreq.c | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
-diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
-index 96dc49c207c7..3fa275ba8cbd 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
-@@ -461,10 +461,14 @@ static void devfreq_monitor(struct work_struct *work)
+@@ -464,10 +464,14 @@ static void devfreq_monitor(struct work_
if (err)
dev_err(&devfreq->dev, "dvfs failed with (%d) error\n", err);
trace_devfreq_monitor(devfreq);
}
-@@ -482,6 +486,10 @@ void devfreq_monitor_start(struct devfreq *devfreq)
+@@ -485,6 +489,10 @@ void devfreq_monitor_start(struct devfre
if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN))
return;
switch (devfreq->profile->timer) {
case DEVFREQ_TIMER_DEFERRABLE:
INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor);
-@@ -490,12 +498,16 @@ void devfreq_monitor_start(struct devfreq *devfreq)
+@@ -493,12 +501,16 @@ void devfreq_monitor_start(struct devfre
INIT_DELAYED_WORK(&devfreq->work, devfreq_monitor);
break;
default:
}
EXPORT_SYMBOL(devfreq_monitor_start);
-@@ -512,6 +524,14 @@ void devfreq_monitor_stop(struct devfreq *devfreq)
+@@ -515,6 +527,14 @@ void devfreq_monitor_stop(struct devfreq
if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN))
return;
cancel_delayed_work_sync(&devfreq->work);
}
EXPORT_SYMBOL(devfreq_monitor_stop);
---
-2.43.0
-
media-mtk-jpeg-fix-use-after-free-bug-due-to-error-p.patch
mm-use-__pfn_to_section-instead-of-open-coding-it.patch
mm-sparsemem-fix-race-in-accessing-memory_section-us.patch
-pm-devfreq-export-devfreq_get_freq_range-symbol-with.patch
-pm-devfreq-add-cpu-based-scaling-support-to-passive-.patch
-pm-devfreq-passive-reduce-duplicate-code-when-passiv.patch
-pm-devfreq-rework-freq_table-to-be-local-to-devfreq-.patch
pm-devfreq-fix-buffer-overflow-in-trans_stat_show.patch
btrfs-add-definition-for-extent_tree_v2.patch
nfsd-modernize-nfsd4_release_lockowner.patch
hid-apple-add-2021-magic-keyboard-fn-key-mapping.patch
bonding-remove-print-in-bond_verify_device_path.patch
asoc-codecs-lpass-wsa-macro-fix-compander-volume-hack.patch
-pm-devfreq-fix-kernel-warning-with-cpufreq-passive-r.patch
-pm-devfreq-mute-warning-on-governor-probe_defer.patch
-pm-devfreq-fix-kernel-panic-with-cpu-based-scaling-t.patch
pm-devfreq-exynos-bus-fix-null-pointer-dereference.patch
dmaengine-fsl-dpaa2-qdma-fix-the-size-of-dma-pools.patch
dmaengine-ti-k3-udma-report-short-packet-errors.patch