From: Matthias Kaehlcke <mka@chromium.org>
To: MyungJoo Ham <myungjoo.ham@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>,
Chanwoo Choi <cw00.choi@samsung.com>,
Arnd Bergmann <arnd@arndb.de>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
linux-pm@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
Brian Norris <briannorris@chromium.org>,
Douglas Anderson <dianders@chromium.org>,
Enric Balletbo i Serra <enric.balletbo@collabora.com>,
"Rafael J . Wysocki" <rjw@rjwysocki.net>,
Viresh Kumar <viresh.kumar@linaro.org>,
Lee Jones <lee.jones@linaro.org>,
Matthias Kaehlcke <mka@chromium.org>
Subject: [PATCH v3 05/12] PM / devfreg: Add support for policy notifiers
Date: Thu, 14 Jun 2018 12:47:05 -0700 [thread overview]
Message-ID: <20180614194712.102134-6-mka@chromium.org> (raw)
In-Reply-To: <20180614194712.102134-1-mka@chromium.org>
Policy notifiers are called before a frequency change and may narrow
the min/max frequency range in devfreq_policy, which is used to adjust
the target frequency if it is beyond this range.
Also add a few helpers:
- devfreq_verify_within_[dev_]limits()
- should be used by the notifiers for policy adjustments.
- dev_to_devfreq()
- lookup a devfreq strict from a device pointer
Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
---
Changes in v3:
- devfreq.h: fixed misspelling of struct devfreq_policy
Changes in v2:
- performance, powersave and simpleondemand governors don't need changes
with "PM / devfreq: Don't adjust to user limits in governors"
- formatting fixes
drivers/devfreq/devfreq.c | 48 ++++++++++++++++++++++-------
include/linux/devfreq.h | 65 +++++++++++++++++++++++++++++++++++++++
2 files changed, 102 insertions(+), 11 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 21604d6ae2b8..4cbaa7ad1972 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -72,6 +72,21 @@ static struct devfreq *find_device_devfreq(struct device *dev)
return ERR_PTR(-ENODEV);
}
+/**
+ * dev_to_devfreq() - find devfreq struct using device pointer
+ * @dev: device pointer used to lookup device devfreq.
+ */
+struct devfreq *dev_to_devfreq(struct device *dev)
+{
+ struct devfreq *devfreq;
+
+ mutex_lock(&devfreq_list_lock);
+ devfreq = find_device_devfreq(dev);
+ mutex_unlock(&devfreq_list_lock);
+
+ return devfreq;
+}
+
static unsigned long find_available_min_freq(struct devfreq *devfreq)
{
struct dev_pm_opp *opp;
@@ -269,20 +284,21 @@ int update_devfreq(struct devfreq *devfreq)
if (!policy->governor)
return -EINVAL;
+ policy->min = policy->devinfo.min_freq;
+ policy->max = policy->devinfo.max_freq;
+
+ srcu_notifier_call_chain(&devfreq->policy_notifier_list,
+ DEVFREQ_ADJUST, policy);
+
/* Reevaluate the proper frequency */
err = policy->governor->get_target_freq(devfreq, &freq);
if (err)
return err;
- /*
- * Adjust the frequency with user freq, QoS and available freq.
- *
- * List from the highest priority
- * max_freq
- * min_freq
- */
- max_freq = MIN(policy->devinfo.max_freq, policy->user.max_freq);
- min_freq = MAX(policy->devinfo.min_freq, policy->user.min_freq);
+ /* Adjust the frequency */
+
+ max_freq = MIN(policy->max, policy->user.max_freq);
+ min_freq = MAX(policy->min, policy->user.min_freq);
if (freq < min_freq) {
freq = min_freq;
@@ -645,6 +661,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
devfreq->last_stat_updated = jiffies;
srcu_init_notifier_head(&devfreq->transition_notifier_list);
+ srcu_init_notifier_head(&devfreq->policy_notifier_list);
mutex_unlock(&devfreq->lock);
@@ -1445,7 +1462,7 @@ EXPORT_SYMBOL(devm_devfreq_unregister_opp_notifier);
* devfreq_register_notifier() - Register a driver with devfreq
* @devfreq: The devfreq object.
* @nb: The notifier block to register.
- * @list: DEVFREQ_TRANSITION_NOTIFIER.
+ * @list: DEVFREQ_TRANSITION_NOTIFIER or DEVFREQ_POLICY_NOTIFIER.
*/
int devfreq_register_notifier(struct devfreq *devfreq,
struct notifier_block *nb,
@@ -1461,6 +1478,10 @@ int devfreq_register_notifier(struct devfreq *devfreq,
ret = srcu_notifier_chain_register(
&devfreq->transition_notifier_list, nb);
break;
+ case DEVFREQ_POLICY_NOTIFIER:
+ ret = srcu_notifier_chain_register(
+ &devfreq->policy_notifier_list, nb);
+ break;
default:
ret = -EINVAL;
}
@@ -1473,7 +1494,7 @@ EXPORT_SYMBOL(devfreq_register_notifier);
* devfreq_unregister_notifier() - Unregister a driver with devfreq
* @devfreq: The devfreq object.
* @nb: The notifier block to be unregistered.
- * @list: DEVFREQ_TRANSITION_NOTIFIER.
+ * @list: DEVFREQ_TRANSITION_NOTIFIER or DEVFREQ_POLICY_NOTIFIER.
*/
int devfreq_unregister_notifier(struct devfreq *devfreq,
struct notifier_block *nb,
@@ -1489,6 +1510,11 @@ int devfreq_unregister_notifier(struct devfreq *devfreq,
ret = srcu_notifier_chain_unregister(
&devfreq->transition_notifier_list, nb);
break;
+ case DEVFREQ_POLICY_NOTIFIER:
+ ret = srcu_notifier_chain_unregister(
+ &devfreq->policy_notifier_list, nb);
+ break;
+
default:
ret = -EINVAL;
}
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index 9bf23b976f4d..7c8dce96db73 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -33,6 +33,10 @@
#define DEVFREQ_PRECHANGE (0)
#define DEVFREQ_POSTCHANGE (1)
+#define DEVFREQ_POLICY_NOTIFIER 1
+
+#define DEVFREQ_ADJUST 0
+
struct devfreq;
struct devfreq_governor;
@@ -121,12 +125,16 @@ struct devfreq_freq_limits {
/**
* struct devfreq_policy - Devfreq policy
+ * @min: minimum frequency (adjustable by policy notifiers)
+ * @min: maximum frequency (adjustable by policy notifiers)
* @user: frequency limits requested by the user
* @devinfo: frequency limits of the device (available OPPs)
* @governor: method how to choose frequency based on the usage.
* @governor_name: devfreq governor name for use with this devfreq
*/
struct devfreq_policy {
+ unsigned long min;
+ unsigned long max;
struct devfreq_freq_limits user;
struct devfreq_freq_limits devinfo;
const struct devfreq_governor *governor;
@@ -155,6 +163,7 @@ struct devfreq_policy {
* @time_in_state: Statistics of devfreq states
* @last_stat_updated: The last time stat updated
* @transition_notifier_list: list head of DEVFREQ_TRANSITION_NOTIFIER notifier
+ * @policy_notifier_list: list head of DEVFREQ_POLICY_NOTIFIER notifier
*
* This structure stores the devfreq information for a give device.
*
@@ -188,6 +197,7 @@ struct devfreq {
unsigned long last_stat_updated;
struct srcu_notifier_head transition_notifier_list;
+ struct srcu_notifier_head policy_notifier_list;
};
struct devfreq_freqs {
@@ -240,6 +250,45 @@ extern void devm_devfreq_unregister_notifier(struct device *dev,
extern struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev,
int index);
+/**
+ * devfreq_verify_within_limits() - Adjust a devfreq policy if needed to make
+ * sure its min/max values are within a
+ * specified range.
+ * @policy: the policy
+ * @min: the minimum frequency
+ * @max: the maximum frequency
+ */
+static inline void devfreq_verify_within_limits(struct devfreq_policy *policy,
+ unsigned int min, unsigned int max)
+{
+ if (policy->min < min)
+ policy->min = min;
+ if (policy->max < min)
+ policy->max = min;
+ if (policy->min > max)
+ policy->min = max;
+ if (policy->max > max)
+ policy->max = max;
+ if (policy->min > policy->max)
+ policy->min = policy->max;
+}
+
+/**
+ * devfreq_verify_within_dev_limits() - Adjust a devfreq policy if needed to
+ * make sure its min/max values are within
+ * the frequency range supported by the
+ * device.
+ * @policy: the policy
+ */
+static inline void
+devfreq_verify_within_dev_limits(struct devfreq_policy *policy)
+{
+ devfreq_verify_within_limits(policy, policy->devinfo.min_freq,
+ policy->devinfo.max_freq);
+}
+
+struct devfreq *dev_to_devfreq(struct device *dev);
+
#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
/**
* struct devfreq_simple_ondemand_data - void *data fed to struct devfreq
@@ -394,10 +443,26 @@ static inline struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev,
return ERR_PTR(-ENODEV);
}
+static inline void devfreq_verify_within_limits(struct devfreq_policy *policy,
+ unsigned int min, unsigned int max)
+{
+}
+
+static inline void
+devfreq_verify_within_dev_limits(struct devfreq_policy *policy)
+{
+}
+
static inline int devfreq_update_stats(struct devfreq *df)
{
return -EINVAL;
}
+
+static inline struct devfreq *dev_to_devfreq(struct device *dev)
+{
+ return NULL;
+}
+
#endif /* CONFIG_PM_DEVFREQ */
#endif /* __LINUX_DEVFREQ_H__ */
--
2.18.0.rc1.242.g61856ae69a-goog
next prev parent reply other threads:[~2018-06-14 19:47 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-14 19:47 [PATCH v3 00/12] Add throttler driver for non-thermal throttling Matthias Kaehlcke
2018-06-14 19:47 ` [PATCH v3 01/12] PM / devfreq: Init user limits from OPP limits, not viceversa Matthias Kaehlcke
2018-06-15 21:06 ` Brian Norris
2018-06-15 21:25 ` Matthias Kaehlcke
2018-06-14 19:47 ` [PATCH v3 02/12] PM / devfreq: Fix handling of min/max_freq == 0 Matthias Kaehlcke
2018-06-18 20:12 ` Brian Norris
2018-06-14 19:47 ` [PATCH v3 03/12] PM / devfreq: Don't adjust to user limits in governors Matthias Kaehlcke
2018-06-14 19:47 ` [PATCH v3 04/12] PM / devfreq: Add struct devfreq_policy Matthias Kaehlcke
2018-06-14 19:47 ` Matthias Kaehlcke [this message]
2018-06-14 19:47 ` [PATCH v3 06/12] PM / devfreq: Make update_devfreq() public Matthias Kaehlcke
2018-06-14 19:47 ` [PATCH v3 07/12] PM / devfreq: export devfreq_class Matthias Kaehlcke
2018-06-14 19:47 ` [PATCH v3 08/12] cpufreq: Add stub for cpufreq_update_policy() Matthias Kaehlcke
2018-06-14 19:47 ` [PATCH v3 09/12] dt-bindings: PM / OPP: add opp-throttlers property Matthias Kaehlcke
2018-06-14 19:47 ` [PATCH v3 10/12] misc: throttler: Add core support for non-thermal throttling Matthias Kaehlcke
2018-06-18 23:03 ` Brian Norris
2018-06-18 23:59 ` Matthias Kaehlcke
2018-06-14 19:47 ` [PATCH v3 11/12] misc: throttler: Add Chrome OS EC throttler Matthias Kaehlcke
2018-06-18 23:34 ` Brian Norris
2018-06-14 19:47 ` [PATCH v3 12/12] mfd: cros_ec: Add throttler sub-device Matthias Kaehlcke
2018-06-18 23:21 ` Brian Norris
2018-06-19 8:41 ` Enric Balletbo Serra
2018-06-19 17:55 ` Matthias Kaehlcke
2018-06-19 17:43 ` 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=20180614194712.102134-6-mka@chromium.org \
--to=mka@chromium.org \
--cc=arnd@arndb.de \
--cc=briannorris@chromium.org \
--cc=cw00.choi@samsung.com \
--cc=devicetree@vger.kernel.org \
--cc=dianders@chromium.org \
--cc=enric.balletbo@collabora.com \
--cc=gregkh@linuxfoundation.org \
--cc=kyungmin.park@samsung.com \
--cc=lee.jones@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=myungjoo.ham@samsung.com \
--cc=rjw@rjwysocki.net \
--cc=robh+dt@kernel.org \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).