From: Viresh Kumar <viresh.kumar@linaro.org>
To: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Linux PM <linux-pm@vger.kernel.org>,
Linux ACPI <linux-acpi@vger.kernel.org>,
LKML <linux-kernel@vger.kernel.org>,
Sudeep Holla <sudeep.holla@arm.com>,
Dmitry Osipenko <digetx@gmail.com>
Subject: Re: [RFT][PATCH 1/3] PM: QoS: Introduce frequency QoS
Date: Thu, 17 Oct 2019 15:11:43 +0530 [thread overview]
Message-ID: <20191017094143.fhmhgltv6ujccxlp@vireshk-i7> (raw)
In-Reply-To: <4551555.oysnf1Sd0E@kreacher>
On 16-10-19, 12:41, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> Introduce frequency QoS, based on the "raw" low-level PM QoS, to
> represent min and max frequency requests and aggregate constraints.
>
> The min and max frequency requests are to be represented by
> struct freq_qos_request objects and the aggregate constraints are to
> be represented by struct freq_constraints objects. The latter are
> expected to be initialized with the help of freq_constraints_init().
>
> The freq_qos_read_value() helper is defined to retrieve the aggregate
> constraints values from a given struct freq_constraints object and
> there are the freq_qos_add_request(), freq_qos_update_request() and
> freq_qos_remove_request() helpers to manipulate the min and max
> frequency requests. It is assumed that the the helpers will not
> run concurrently with each other for the same struct freq_qos_request
> object, so if that may be the case, their uses must ensure proper
> synchronization between them (e.g. through locking).
>
> In addition, freq_qos_add_notifier() and freq_qos_remove_notifier()
> are provided to add and remove notifiers that will trigger on aggregate
> constraint changes to and from a given struct freq_constraints object,
> respectively.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
> include/linux/pm_qos.h | 44 ++++++++
> kernel/power/qos.c | 240 +++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 284 insertions(+)
>
> Index: linux-pm/include/linux/pm_qos.h
> ===================================================================
> --- linux-pm.orig/include/linux/pm_qos.h
> +++ linux-pm/include/linux/pm_qos.h
> @@ -267,4 +267,48 @@ static inline s32 dev_pm_qos_raw_resume_
> }
> #endif
>
> +#define FREQ_QOS_MIN_DEFAULT_VALUE 0
> +#define FREQ_QOS_MAX_DEFAULT_VALUE (-1)
> +
> +enum freq_qos_req_type {
> + FREQ_QOS_MIN = 1,
> + FREQ_QOS_MAX,
> +};
> +
> +struct freq_constraints {
> + struct pm_qos_constraints min_freq;
> + struct blocking_notifier_head min_freq_notifiers;
> + struct pm_qos_constraints max_freq;
> + struct blocking_notifier_head max_freq_notifiers;
> +};
> +
> +struct freq_qos_request {
> + enum freq_qos_req_type type;
> + struct plist_node pnode;
> + struct freq_constraints *qos;
> +};
> +
> +static inline int freq_qos_request_active(struct freq_qos_request *req)
> +{
> + return !IS_ERR_OR_NULL(req->qos);
> +}
> +
> +void freq_constraints_init(struct freq_constraints *qos);
> +
> +s32 freq_qos_read_value(struct freq_constraints *qos,
> + enum freq_qos_req_type type);
> +
> +int freq_qos_add_request(struct freq_constraints *qos,
> + struct freq_qos_request *req,
> + enum freq_qos_req_type type, s32 value);
> +int freq_qos_update_request(struct freq_qos_request *req, s32 new_value);
> +int freq_qos_remove_request(struct freq_qos_request *req);
> +
> +int freq_qos_add_notifier(struct freq_constraints *qos,
> + enum freq_qos_req_type type,
> + struct notifier_block *notifier);
> +int freq_qos_remove_notifier(struct freq_constraints *qos,
> + enum freq_qos_req_type type,
> + struct notifier_block *notifier);
> +
> #endif
> Index: linux-pm/kernel/power/qos.c
> ===================================================================
> --- linux-pm.orig/kernel/power/qos.c
> +++ linux-pm/kernel/power/qos.c
> @@ -650,3 +650,243 @@ static int __init pm_qos_power_init(void
> }
>
> late_initcall(pm_qos_power_init);
> +
> +/* Definitions related to the frequency QoS below. */
> +
> +/**
> + * freq_constraints_init - Initialize frequency QoS constraints.
> + * @qos: Frequency QoS constraints to initialize.
> + */
> +void freq_constraints_init(struct freq_constraints *qos)
> +{
> + struct pm_qos_constraints *c;
> +
> + c = &qos->min_freq;
> + plist_head_init(&c->list);
> + c->target_value = FREQ_QOS_MIN_DEFAULT_VALUE;
> + c->default_value = FREQ_QOS_MIN_DEFAULT_VALUE;
> + c->no_constraint_value = FREQ_QOS_MIN_DEFAULT_VALUE;
> + c->type = PM_QOS_MAX;
should this be MIN ?
> + c->notifiers = &qos->min_freq_notifiers;
> + BLOCKING_INIT_NOTIFIER_HEAD(c->notifiers);
> +
> + c = &qos->max_freq;
> + plist_head_init(&c->list);
> + c->target_value = FREQ_QOS_MAX_DEFAULT_VALUE;
> + c->default_value = FREQ_QOS_MAX_DEFAULT_VALUE;
> + c->no_constraint_value = FREQ_QOS_MAX_DEFAULT_VALUE;
> + c->type = PM_QOS_MIN;
and this MAX ?
> + c->notifiers = &qos->max_freq_notifiers;
> + BLOCKING_INIT_NOTIFIER_HEAD(c->notifiers);
> +}
> +
> +/**
> + * freq_qos_read_value - Get frequency QoS constraint for a given list.
> + * @qos: Constraints to evaluate.
> + * @type: QoS request type.
> + */
> +s32 freq_qos_read_value(struct freq_constraints *qos,
> + enum freq_qos_req_type type)
> +{
> + s32 ret;
> +
> + switch (type) {
> + case FREQ_QOS_MIN:
> + ret = IS_ERR_OR_NULL(qos) ?
> + FREQ_QOS_MIN_DEFAULT_VALUE :
> + pm_qos_read_value(&qos->min_freq);
> + break;
> + case FREQ_QOS_MAX:
> + ret = IS_ERR_OR_NULL(qos) ?
> + FREQ_QOS_MAX_DEFAULT_VALUE :
> + pm_qos_read_value(&qos->max_freq);
> + break;
> + default:
> + WARN_ON(1);
> + ret = 0;
> + }
> +
> + return ret;
> +}
> +
> +/**
> + * freq_qos_apply - Add/modify/remove frequency QoS request.
> + * @req: Constraint request to apply.
> + * @action: Action to perform (add/update/remove).
> + * @value: Value to assign to the QoS request.
> + */
> +static int freq_qos_apply(struct freq_qos_request *req,
> + enum pm_qos_req_action action, s32 value)
> +{
> + int ret;
> +
> + switch(req->type) {
> + case FREQ_QOS_MIN:
> + ret = pm_qos_update_target(&req->qos->min_freq, &req->pnode,
> + action, value);
> + break;
> + case FREQ_QOS_MAX:
> + ret = pm_qos_update_target(&req->qos->max_freq, &req->pnode,
> + action, value);
> + break;
> + default:
> + ret = -EINVAL;
> + }
> +
> + return ret;
> +}
> +
> +/**
> + * freq_qos_add_request - Insert new frequency QoS request into a given list.
> + * @qos: Constraints to update.
> + * @req: Preallocated request object.
> + * @type: Request type.
> + * @value: Request value.
> + *
> + * Insert a new entry into the @qos list of requests, recompute the effective
> + * QoS constraint value for that list and initialize the @req object. The
> + * caller needs to save that object for later use in updates and removal.
> + *
> + * Return 1 if the effective constraint value has changed, 0 if the effective
> + * constraint value has not changed, or a negative error code on failures.
> + */
> +int freq_qos_add_request(struct freq_constraints *qos,
> + struct freq_qos_request *req,
> + enum freq_qos_req_type type, s32 value)
> +{
> + int ret;
> +
> + if (IS_ERR_OR_NULL(qos) || !req)
> + return -EINVAL;
> +
> + if (WARN(freq_qos_request_active(req),
> + "%s() called for active request\n", __func__))
> + return -EINVAL;
> +
> + req->qos = qos;
> + req->type = type;
> + ret = freq_qos_apply(req, PM_QOS_ADD_REQ, value);
> + if (ret < 0) {
> + req->qos = NULL;
> + req->type = 0;
> + }
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(freq_qos_add_request);
> +
> +/**
> + * freq_qos_update_request - Modify existing frequency QoS request.
> + * @req: Request to modify.
> + * @new_value: New request value.
> + *
> + * Update an existing frequency QoS request along with the effective constraint
> + * value for the list of requests it belongs to.
> + *
> + * Return 1 if the effective constraint value has changed, 0 if the effective
> + * constraint value has not changed, or a negative error code on failures.
> + */
> +int freq_qos_update_request(struct freq_qos_request *req, s32 new_value)
> +{
> + if (!req)
> + return -EINVAL;
> +
> + if (WARN(!freq_qos_request_active(req),
> + "%s() called for unknown object\n", __func__))
> + return -EINVAL;
> +
> + if (req->pnode.prio == new_value)
> + return 0;
> +
> + return freq_qos_apply(req, PM_QOS_UPDATE_REQ, new_value);
> +}
> +EXPORT_SYMBOL_GPL(freq_qos_update_request);
> +
> +/**
> + * freq_qos_remove_request - Remove frequency QoS request from its list.
> + * @req: Request to remove.
> + *
> + * Remove the given frequency QoS request from the list of constraints it
> + * belongs to and recompute the effective constraint value for that list.
> + *
> + * Return 1 if the effective constraint value has changed, 0 if the effective
> + * constraint value has not changed, or a negative error code on failures.
> + */
> +int freq_qos_remove_request(struct freq_qos_request *req)
> +{
> + if (!req)
> + return -EINVAL;
> +
> + if (WARN(!freq_qos_request_active(req),
> + "%s() called for unknown object\n", __func__))
> + return -EINVAL;
> +
> + return freq_qos_apply(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
> +}
> +EXPORT_SYMBOL_GPL(freq_qos_remove_request);
> +
> +/**
> + * freq_qos_add_notifier - Add frequency QoS change notifier.
> + * @qos: List of requests to add the notifier to.
> + * @type: Request type.
> + * @notifier: Notifier block to add.
> + */
> +int freq_qos_add_notifier(struct freq_constraints *qos,
> + enum freq_qos_req_type type,
> + struct notifier_block *notifier)
> +{
> + int ret;
> +
> + if (IS_ERR_OR_NULL(qos) || !notifier)
> + return -EINVAL;
> +
> + switch (type) {
> + case FREQ_QOS_MIN:
> + ret = blocking_notifier_chain_register(qos->min_freq.notifiers,
> + notifier);
> + break;
> + case FREQ_QOS_MAX:
> + ret = blocking_notifier_chain_register(qos->max_freq.notifiers,
> + notifier);
> + break;
> + default:
> + WARN_ON(1);
> + ret = -EINVAL;
> + }
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(freq_qos_add_notifier);
> +
> +/**
> + * freq_qos_remove_notifier - Remove frequency QoS change notifier.
> + * @qos: List of requests to remove the notifier from.
> + * @type: Request type.
> + * @notifier: Notifier block to remove.
> + */
> +int freq_qos_remove_notifier(struct freq_constraints *qos,
> + enum freq_qos_req_type type,
> + struct notifier_block *notifier)
> +{
> + int ret;
> +
> + if (IS_ERR_OR_NULL(qos) || !notifier)
> + return -EINVAL;
> +
> + switch (type) {
> + case FREQ_QOS_MIN:
> + ret = blocking_notifier_chain_unregister(qos->min_freq.notifiers,
> + notifier);
> + break;
> + case FREQ_QOS_MAX:
> + ret = blocking_notifier_chain_unregister(qos->max_freq.notifiers,
> + notifier);
> + break;
> + default:
> + WARN_ON(1);
> + ret = -EINVAL;
> + }
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(freq_qos_remove_notifier);
>
>
--
viresh
next prev parent reply other threads:[~2019-10-17 9:41 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-10-16 10:37 [RFT][PATCH 0/3] cpufreq / PM: QoS: Introduce frequency QoS and use it in cpufreq Rafael J. Wysocki
2019-10-16 10:41 ` [RFT][PATCH 1/3] PM: QoS: Introduce frequency QoS Rafael J. Wysocki
2019-10-17 9:41 ` Viresh Kumar [this message]
2019-10-17 14:16 ` Rafael J. Wysocki
2019-10-18 5:41 ` Viresh Kumar
2019-10-24 19:01 ` Leonard Crestez
2019-10-24 19:34 ` Leonard Crestez
2019-11-17 7:34 ` Doug Smythies
2019-11-17 16:13 ` Doug Smythies
2019-11-19 14:35 ` Doug Smythies
2019-11-19 19:17 ` Rafael J. Wysocki
2019-11-19 22:13 ` Rafael J. Wysocki
2019-11-20 6:55 ` Doug Smythies
2019-11-20 9:08 ` Rafael J. Wysocki
2019-10-16 10:47 ` [RFT][PATCH 2/3] cpufreq: Use per-policy " Rafael J. Wysocki
2019-10-16 18:01 ` Dmitry Osipenko
2019-10-17 21:29 ` Dmitry Osipenko
2019-10-18 9:29 ` Viresh Kumar
2019-10-18 15:31 ` Dmitry Osipenko
2019-10-16 10:47 ` [RFT][PATCH 3/3] PM: QoS: Drop frequency QoS types from device PM QoS Rafael J. Wysocki
2019-10-16 14:23 ` [RFT][PATCH 0/3] cpufreq / PM: QoS: Introduce frequency QoS and use it in cpufreq Sudeep Holla
2019-10-17 9:57 ` Viresh Kumar
2019-10-17 9:59 ` Sudeep Holla
2019-10-17 16:34 ` Rafael J. Wysocki
2019-10-17 16:42 ` Sudeep Holla
2019-10-18 5:44 ` Viresh Kumar
2019-10-18 8:24 ` Rafael J. Wysocki
2019-10-18 8:27 ` Viresh Kumar
2019-10-18 8:30 ` Rafael J. Wysocki
2019-10-18 9:24 ` Viresh Kumar
2019-10-18 9:26 ` Rafael J. Wysocki
2019-10-18 9:28 ` Viresh Kumar
2019-10-17 17:14 ` Sudeep Holla
2019-10-17 9:46 ` Viresh Kumar
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=20191017094143.fhmhgltv6ujccxlp@vireshk-i7 \
--to=viresh.kumar@linaro.org \
--cc=digetx@gmail.com \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=rjw@rjwysocki.net \
--cc=sudeep.holla@arm.com \
/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).