From: Matthias Kaehlcke <mka@chromium.org>
To: Leonard Crestez <leonard.crestez@nxp.com>
Cc: "MyungJoo Ham" <myungjoo.ham@samsung.com>,
"Kyungmin Park" <kyungmin.park@samsung.com>,
"Chanwoo Choi" <cw00.choi@samsung.com>,
"Artur Świgoń" <a.swigon@partner.samsung.com>,
"Saravana Kannan" <saravanak@google.com>,
"Krzysztof Kozlowski" <krzk@kernel.org>,
"Alexandre Bailon" <abailon@baylibre.com>,
"Georgi Djakov" <georgi.djakov@linaro.org>,
"Abel Vesa" <abel.vesa@nxp.com>, "Jacky Bai" <ping.bai@nxp.com>,
"Viresh Kumar" <viresh.kumar@linaro.org>,
"Lukasz Luba" <l.luba@partner.samsung.com>,
linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
"NXP Linux Team" <linux-imx@nxp.com>
Subject: Re: [PATCH v6 4/6] PM / devfreq: Introduce devfreq_get_freq_range
Date: Mon, 23 Sep 2019 11:16:24 -0700 [thread overview]
Message-ID: <20190923181624.GZ133864@google.com> (raw)
In-Reply-To: <4e274855585940ec6fb0e219c7539d4cf600d9f1.1569252537.git.leonard.crestez@nxp.com>
On Mon, Sep 23, 2019 at 06:51:07PM +0300, Leonard Crestez wrote:
> Moving handling of min/max freq to a single function and call it from
> update_devfreq and for printing min/max freq values in sysfs.
>
> This changes the behavior of out-of-range min_freq/max_freq: clamping
> is now done at evaluation time. This means that if an out-of-range
> constraint is imposed by sysfs and it later becomes valid then it will
> be enforced.
>
> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
> Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
> ---
> drivers/devfreq/devfreq.c | 111 +++++++++++++++++++++-----------------
> 1 file changed, 63 insertions(+), 48 deletions(-)
>
> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
> index 0eee4dd79fbb..b6acb827fee5 100644
> --- a/drivers/devfreq/devfreq.c
> +++ b/drivers/devfreq/devfreq.c
> @@ -24,10 +24,12 @@
> #include <linux/printk.h>
> #include <linux/hrtimer.h>
> #include <linux/of.h>
> #include "governor.h"
>
> +#define HZ_PER_KHZ 1000
> +
> #define CREATE_TRACE_POINTS
> #include <trace/events/devfreq.h>
>
> static struct class *devfreq_class;
>
> @@ -96,10 +98,50 @@ static unsigned long find_available_max_freq(struct devfreq *devfreq)
> dev_pm_opp_put(opp);
>
> return max_freq;
> }
>
> +/**
> + * 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 devfreq_get_freq_range(struct devfreq *devfreq,
> + unsigned long *min_freq,
> + unsigned long *max_freq)
> +{
> + unsigned long *freq_table = devfreq->profile->freq_table;
> +
> + lockdep_assert_held(&devfreq->lock);
> +
> + /* Init min/max frequency from freq table */
> + if (freq_table[0] < freq_table[devfreq->profile->max_state - 1]) {
> + *min_freq = freq_table[0];
> + *max_freq = freq_table[devfreq->profile->max_state - 1];
> + } else {
> + *min_freq = freq_table[devfreq->profile->max_state - 1];
> + *max_freq = freq_table[0];
> + }
> +
> + /* constraints from sysfs: */
one more nit if you are respinning anyway: remove colon
> + *min_freq = max(*min_freq, devfreq->min_freq);
> + *max_freq = min(*max_freq, devfreq->max_freq);
> +
> + /* constraints from OPP interface: */
ditto
> + *min_freq = max(*min_freq, devfreq->scaling_min_freq);
> + /* scaling_max_freq can be zero on error */
> + if (devfreq->scaling_max_freq)
> + *max_freq = min(*max_freq, devfreq->scaling_max_freq);
> +
> + /* max_freq takes precedence over min_freq */
> + if (*min_freq > *max_freq)
> + *min_freq = *max_freq;
> +}
> +
> /**
> * devfreq_get_freq_level() - Lookup freq_table for the frequency
> * @devfreq: the devfreq instance
> * @freq: the target frequency
> */
> @@ -348,21 +390,13 @@ int update_devfreq(struct devfreq *devfreq)
>
> /* Reevaluate the proper frequency */
> err = devfreq->governor->get_target_freq(devfreq, &freq);
> if (err)
> return err;
> + devfreq_get_freq_range(devfreq, &min_freq, &max_freq);
>
> - /*
> - * Adjust the frequency with user freq, QoS and available freq.
> - *
> - * List from the highest priority
> - * max_freq
> - * min_freq
> - */
> - max_freq = min(devfreq->scaling_max_freq, devfreq->max_freq);
> - min_freq = max(devfreq->scaling_min_freq, devfreq->min_freq);
> -
> + /* max freq takes priority over min freq */
> if (freq < min_freq) {
> freq = min_freq;
> flags &= ~DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use GLB */
> }
> if (freq > max_freq) {
> @@ -1297,40 +1331,28 @@ static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr,
> ret = sscanf(buf, "%lu", &value);
> if (ret != 1)
> return -EINVAL;
>
> mutex_lock(&df->lock);
> -
> - if (value) {
> - if (value > df->max_freq) {
> - ret = -EINVAL;
> - goto unlock;
> - }
> - } else {
> - unsigned long *freq_table = df->profile->freq_table;
> -
> - /* Get minimum frequency according to sorting order */
> - if (freq_table[0] < freq_table[df->profile->max_state - 1])
> - value = freq_table[0];
> - else
> - value = freq_table[df->profile->max_state - 1];
> - }
> -
> df->min_freq = value;
> update_devfreq(df);
> - ret = count;
> -unlock:
> mutex_unlock(&df->lock);
> - return ret;
> +
> + return count;
> }
>
> static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr,
> char *buf)
> {
> struct devfreq *df = to_devfreq(dev);
> + unsigned long min_freq, max_freq;
>
> - return sprintf(buf, "%lu\n", max(df->scaling_min_freq, df->min_freq));
> + mutex_lock(&df->lock);
> + devfreq_get_freq_range(df, &min_freq, &max_freq);
> + mutex_unlock(&df->lock);
> +
> + return sprintf(buf, "%lu\n", min_freq);
> }
>
> static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
> const char *buf, size_t count)
> {
> @@ -1342,40 +1364,33 @@ static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
> if (ret != 1)
> return -EINVAL;
>
> mutex_lock(&df->lock);
>
> - if (value) {
> - if (value < df->min_freq) {
> - ret = -EINVAL;
> - goto unlock;
> - }
> - } else {
> - unsigned long *freq_table = df->profile->freq_table;
> -
> - /* Get maximum frequency according to sorting order */
> - if (freq_table[0] < freq_table[df->profile->max_state - 1])
> - value = freq_table[df->profile->max_state - 1];
> - else
> - value = freq_table[0];
> - }
> + /* Interpret zero as "don't care" */
> + if (!value)
> + value = ULONG_MAX;
>
> df->max_freq = value;
> update_devfreq(df);
> - ret = count;
> -unlock:
> mutex_unlock(&df->lock);
> - return ret;
> +
> + return count;
> }
> static DEVICE_ATTR_RW(min_freq);
>
> static ssize_t max_freq_show(struct device *dev, struct device_attribute *attr,
> char *buf)
> {
> struct devfreq *df = to_devfreq(dev);
> + unsigned long min_freq, max_freq;
> +
> + mutex_lock(&df->lock);
> + devfreq_get_freq_range(df, &min_freq, &max_freq);
> + mutex_unlock(&df->lock);
>
> - return sprintf(buf, "%lu\n", min(df->scaling_max_freq, df->max_freq));
> + return sprintf(buf, "%lu\n", max_freq);
> }
> static DEVICE_ATTR_RW(max_freq);
>
> static ssize_t available_frequencies_show(struct device *d,
> struct device_attribute *attr,
WARNING: multiple messages have this Message-ID (diff)
From: Matthias Kaehlcke <mka@chromium.org>
To: Leonard Crestez <leonard.crestez@nxp.com>
Cc: "Artur Świgoń" <a.swigon@partner.samsung.com>,
"Abel Vesa" <abel.vesa@nxp.com>,
"Saravana Kannan" <saravanak@google.com>,
linux-pm@vger.kernel.org,
"Viresh Kumar" <viresh.kumar@linaro.org>,
"NXP Linux Team" <linux-imx@nxp.com>,
"Krzysztof Kozlowski" <krzk@kernel.org>,
"Lukasz Luba" <l.luba@partner.samsung.com>,
"Chanwoo Choi" <cw00.choi@samsung.com>,
"Kyungmin Park" <kyungmin.park@samsung.com>,
"MyungJoo Ham" <myungjoo.ham@samsung.com>,
"Alexandre Bailon" <abailon@baylibre.com>,
"Georgi Djakov" <georgi.djakov@linaro.org>,
linux-arm-kernel@lists.infradead.org,
"Jacky Bai" <ping.bai@nxp.com>
Subject: Re: [PATCH v6 4/6] PM / devfreq: Introduce devfreq_get_freq_range
Date: Mon, 23 Sep 2019 11:16:24 -0700 [thread overview]
Message-ID: <20190923181624.GZ133864@google.com> (raw)
In-Reply-To: <4e274855585940ec6fb0e219c7539d4cf600d9f1.1569252537.git.leonard.crestez@nxp.com>
On Mon, Sep 23, 2019 at 06:51:07PM +0300, Leonard Crestez wrote:
> Moving handling of min/max freq to a single function and call it from
> update_devfreq and for printing min/max freq values in sysfs.
>
> This changes the behavior of out-of-range min_freq/max_freq: clamping
> is now done at evaluation time. This means that if an out-of-range
> constraint is imposed by sysfs and it later becomes valid then it will
> be enforced.
>
> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
> Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
> ---
> drivers/devfreq/devfreq.c | 111 +++++++++++++++++++++-----------------
> 1 file changed, 63 insertions(+), 48 deletions(-)
>
> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
> index 0eee4dd79fbb..b6acb827fee5 100644
> --- a/drivers/devfreq/devfreq.c
> +++ b/drivers/devfreq/devfreq.c
> @@ -24,10 +24,12 @@
> #include <linux/printk.h>
> #include <linux/hrtimer.h>
> #include <linux/of.h>
> #include "governor.h"
>
> +#define HZ_PER_KHZ 1000
> +
> #define CREATE_TRACE_POINTS
> #include <trace/events/devfreq.h>
>
> static struct class *devfreq_class;
>
> @@ -96,10 +98,50 @@ static unsigned long find_available_max_freq(struct devfreq *devfreq)
> dev_pm_opp_put(opp);
>
> return max_freq;
> }
>
> +/**
> + * 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 devfreq_get_freq_range(struct devfreq *devfreq,
> + unsigned long *min_freq,
> + unsigned long *max_freq)
> +{
> + unsigned long *freq_table = devfreq->profile->freq_table;
> +
> + lockdep_assert_held(&devfreq->lock);
> +
> + /* Init min/max frequency from freq table */
> + if (freq_table[0] < freq_table[devfreq->profile->max_state - 1]) {
> + *min_freq = freq_table[0];
> + *max_freq = freq_table[devfreq->profile->max_state - 1];
> + } else {
> + *min_freq = freq_table[devfreq->profile->max_state - 1];
> + *max_freq = freq_table[0];
> + }
> +
> + /* constraints from sysfs: */
one more nit if you are respinning anyway: remove colon
> + *min_freq = max(*min_freq, devfreq->min_freq);
> + *max_freq = min(*max_freq, devfreq->max_freq);
> +
> + /* constraints from OPP interface: */
ditto
> + *min_freq = max(*min_freq, devfreq->scaling_min_freq);
> + /* scaling_max_freq can be zero on error */
> + if (devfreq->scaling_max_freq)
> + *max_freq = min(*max_freq, devfreq->scaling_max_freq);
> +
> + /* max_freq takes precedence over min_freq */
> + if (*min_freq > *max_freq)
> + *min_freq = *max_freq;
> +}
> +
> /**
> * devfreq_get_freq_level() - Lookup freq_table for the frequency
> * @devfreq: the devfreq instance
> * @freq: the target frequency
> */
> @@ -348,21 +390,13 @@ int update_devfreq(struct devfreq *devfreq)
>
> /* Reevaluate the proper frequency */
> err = devfreq->governor->get_target_freq(devfreq, &freq);
> if (err)
> return err;
> + devfreq_get_freq_range(devfreq, &min_freq, &max_freq);
>
> - /*
> - * Adjust the frequency with user freq, QoS and available freq.
> - *
> - * List from the highest priority
> - * max_freq
> - * min_freq
> - */
> - max_freq = min(devfreq->scaling_max_freq, devfreq->max_freq);
> - min_freq = max(devfreq->scaling_min_freq, devfreq->min_freq);
> -
> + /* max freq takes priority over min freq */
> if (freq < min_freq) {
> freq = min_freq;
> flags &= ~DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use GLB */
> }
> if (freq > max_freq) {
> @@ -1297,40 +1331,28 @@ static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr,
> ret = sscanf(buf, "%lu", &value);
> if (ret != 1)
> return -EINVAL;
>
> mutex_lock(&df->lock);
> -
> - if (value) {
> - if (value > df->max_freq) {
> - ret = -EINVAL;
> - goto unlock;
> - }
> - } else {
> - unsigned long *freq_table = df->profile->freq_table;
> -
> - /* Get minimum frequency according to sorting order */
> - if (freq_table[0] < freq_table[df->profile->max_state - 1])
> - value = freq_table[0];
> - else
> - value = freq_table[df->profile->max_state - 1];
> - }
> -
> df->min_freq = value;
> update_devfreq(df);
> - ret = count;
> -unlock:
> mutex_unlock(&df->lock);
> - return ret;
> +
> + return count;
> }
>
> static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr,
> char *buf)
> {
> struct devfreq *df = to_devfreq(dev);
> + unsigned long min_freq, max_freq;
>
> - return sprintf(buf, "%lu\n", max(df->scaling_min_freq, df->min_freq));
> + mutex_lock(&df->lock);
> + devfreq_get_freq_range(df, &min_freq, &max_freq);
> + mutex_unlock(&df->lock);
> +
> + return sprintf(buf, "%lu\n", min_freq);
> }
>
> static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
> const char *buf, size_t count)
> {
> @@ -1342,40 +1364,33 @@ static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
> if (ret != 1)
> return -EINVAL;
>
> mutex_lock(&df->lock);
>
> - if (value) {
> - if (value < df->min_freq) {
> - ret = -EINVAL;
> - goto unlock;
> - }
> - } else {
> - unsigned long *freq_table = df->profile->freq_table;
> -
> - /* Get maximum frequency according to sorting order */
> - if (freq_table[0] < freq_table[df->profile->max_state - 1])
> - value = freq_table[df->profile->max_state - 1];
> - else
> - value = freq_table[0];
> - }
> + /* Interpret zero as "don't care" */
> + if (!value)
> + value = ULONG_MAX;
>
> df->max_freq = value;
> update_devfreq(df);
> - ret = count;
> -unlock:
> mutex_unlock(&df->lock);
> - return ret;
> +
> + return count;
> }
> static DEVICE_ATTR_RW(min_freq);
>
> static ssize_t max_freq_show(struct device *dev, struct device_attribute *attr,
> char *buf)
> {
> struct devfreq *df = to_devfreq(dev);
> + unsigned long min_freq, max_freq;
> +
> + mutex_lock(&df->lock);
> + devfreq_get_freq_range(df, &min_freq, &max_freq);
> + mutex_unlock(&df->lock);
>
> - return sprintf(buf, "%lu\n", min(df->scaling_max_freq, df->max_freq));
> + return sprintf(buf, "%lu\n", max_freq);
> }
> static DEVICE_ATTR_RW(max_freq);
>
> static ssize_t available_frequencies_show(struct device *d,
> struct device_attribute *attr,
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2019-09-23 18:16 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-09-23 15:51 [PATCH v6 0/6] PM / devfreq: Add dev_pm_qos support Leonard Crestez
2019-09-23 15:51 ` Leonard Crestez
2019-09-23 15:51 ` [PATCH v6 1/6] PM / devfreq: Don't fail devfreq_dev_release if not in list Leonard Crestez
2019-09-23 15:51 ` Leonard Crestez
2019-09-23 15:51 ` [PATCH v6 2/6] PM / devfreq: Move more initialization before registration Leonard Crestez
2019-09-23 15:51 ` Leonard Crestez
2019-09-23 18:10 ` Matthias Kaehlcke
2019-09-23 18:10 ` Matthias Kaehlcke
2019-09-23 18:56 ` Leonard Crestez
2019-09-23 18:56 ` Leonard Crestez
2019-09-23 19:11 ` Matthias Kaehlcke
2019-09-23 19:11 ` Matthias Kaehlcke
2019-09-23 19:56 ` Leonard Crestez
2019-09-23 19:56 ` Leonard Crestez
2019-09-23 21:17 ` Matthias Kaehlcke
2019-09-23 21:17 ` Matthias Kaehlcke
2019-09-23 15:51 ` [PATCH v6 3/6] PM / devfreq: Don't take lock in devfreq_add_device Leonard Crestez
2019-09-23 15:51 ` Leonard Crestez
2019-09-23 15:51 ` [PATCH v6 4/6] PM / devfreq: Introduce devfreq_get_freq_range Leonard Crestez
2019-09-23 15:51 ` Leonard Crestez
2019-09-23 18:16 ` Matthias Kaehlcke [this message]
2019-09-23 18:16 ` Matthias Kaehlcke
2019-09-23 15:51 ` [PATCH v6 5/6] PM / devfreq: Add PM QoS support Leonard Crestez
2019-09-23 15:51 ` Leonard Crestez
2019-09-23 18:28 ` Matthias Kaehlcke
2019-09-23 18:28 ` Matthias Kaehlcke
2019-09-23 15:51 ` [PATCH v6 6/6] PM / devfreq: Use PM QoS for sysfs min/max_freq Leonard Crestez
2019-09-23 15:51 ` Leonard Crestez
2019-09-23 18:47 ` Matthias Kaehlcke
2019-09-23 18:47 ` Matthias Kaehlcke
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190923181624.GZ133864@google.com \
--to=mka@chromium.org \
--cc=a.swigon@partner.samsung.com \
--cc=abailon@baylibre.com \
--cc=abel.vesa@nxp.com \
--cc=cw00.choi@samsung.com \
--cc=georgi.djakov@linaro.org \
--cc=krzk@kernel.org \
--cc=kyungmin.park@samsung.com \
--cc=l.luba@partner.samsung.com \
--cc=leonard.crestez@nxp.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-imx@nxp.com \
--cc=linux-pm@vger.kernel.org \
--cc=myungjoo.ham@samsung.com \
--cc=ping.bai@nxp.com \
--cc=saravanak@google.com \
--cc=viresh.kumar@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.