From: Benjamin Gaignard <benjamin.gaignard@st.com>
To: <rjw@rjwysocki.net>, <viresh.kumar@linaro.org>,
<hugues.fruchet@st.com>, <mchehab@kernel.org>,
<mcoquelin.stm32@gmail.com>, <alexandre.torgue@st.com>,
<pavel@ucw.cz>, <len.brown@intel.com>
Cc: <linux-pm@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<linux-media@vger.kernel.org>,
<linux-stm32@st-md-mailman.stormreply.com>,
<linux-arm-kernel@lists.infradead.org>,
Benjamin Gaignard <benjamin.gaignard@st.com>
Subject: [RFC 1/3] PM: QoS: Introduce cpufreq minimum load QoS
Date: Fri, 24 Apr 2020 13:40:56 +0200 [thread overview]
Message-ID: <20200424114058.21199-2-benjamin.gaignard@st.com> (raw)
In-Reply-To: <20200424114058.21199-1-benjamin.gaignard@st.com>
Introduce cpufreq minimum load QoS, based on the "raw" low-level
PM QoS, to represent the minimum expected cpu load by various devices.
The cpufreq_minload_qos_limit() helper is defined to retrieve the
aggregated constraints.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
include/linux/pm_qos.h | 12 +++
kernel/power/qos.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 225 insertions(+)
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h
index 4a69d4af3ff8..e2cc099322e3 100644
--- a/include/linux/pm_qos.h
+++ b/include/linux/pm_qos.h
@@ -316,4 +316,16 @@ int freq_qos_remove_notifier(struct freq_constraints *qos,
enum freq_qos_req_type type,
struct notifier_block *notifier);
+/* Definitions related to the cpufreq minimum load QoS. */
+
+#define CPUFREQ_GOV_QOS_MIN_LOAD_DEFAULT_VALUE 0
+#define CPUFREQ_GOV_QOS_MIN_LOAD_MAX_VALUE 10
+
+s32 cpufreq_minload_qos_limit(void);
+bool cpufreq_minload_qos_request_active(struct pm_qos_request *req);
+void cpufreq_minload_qos_add_request(struct pm_qos_request *req, s32 value);
+void cpufreq_minload_qos_update_request(struct pm_qos_request *req,
+ s32 new_value);
+void cpufreq_minload_qos_remove_request(struct pm_qos_request *req);
+
#endif
diff --git a/kernel/power/qos.c b/kernel/power/qos.c
index db0bed2cae26..df2fdd962f35 100644
--- a/kernel/power/qos.c
+++ b/kernel/power/qos.c
@@ -671,3 +671,216 @@ int freq_qos_remove_notifier(struct freq_constraints *qos,
return ret;
}
EXPORT_SYMBOL_GPL(freq_qos_remove_notifier);
+
+/* Definitions related to the cpufreq minimum load QoS. */
+
+static struct pm_qos_constraints cpufreq_minload_constraints = {
+ .list = PLIST_HEAD_INIT(cpufreq_minload_constraints.list),
+ .target_value = CPUFREQ_GOV_QOS_MIN_LOAD_DEFAULT_VALUE,
+ .default_value = CPUFREQ_GOV_QOS_MIN_LOAD_DEFAULT_VALUE,
+ .no_constraint_value = CPUFREQ_GOV_QOS_MIN_LOAD_DEFAULT_VALUE,
+ .type = PM_QOS_MAX,
+};
+
+/**
+ * cpufreq_minload_qos_limit - Return current system-wide cpufreq
+ * minimum load QoS limit.
+ */
+s32 cpufreq_minload_qos_limit(void)
+{
+ return pm_qos_read_value(&cpufreq_minload_constraints);
+}
+EXPORT_SYMBOL_GPL(cpufreq_minload_qos_limit);
+
+/**
+ * cpufreq_minload_qos_request_active - Check the given PM QoS request.
+ * @req: PM QoS request to check.
+ *
+ * Return: 'true' if @req has been added to the cpufreq minimum load
+ * QoS list, 'false' otherwise.
+ */
+bool cpufreq_minload_qos_request_active(struct pm_qos_request *req)
+{
+ return req->qos == &cpufreq_minload_constraints;
+}
+EXPORT_SYMBOL_GPL(cpufreq_minload_qos_request_active);
+
+/**
+ * cpufreq_minload_qos_add_request - Add new cpufreq minimum load QoS request.
+ * @req: Pointer to a preallocated handle.
+ * @value: Requested constraint value.
+ *
+ * Use @value to initialize the request handle pointed to by @req, insert it as
+ * a new entry to the cpufreq minimum load QoS list and recompute the effective
+ * QoS constraint for that list.
+ *
+ * Callers need to save the handle for later use in updates and removal of the
+ * QoS request represented by it.
+ */
+void cpufreq_minload_qos_add_request(struct pm_qos_request *req, s32 value)
+{
+ if (!req)
+ return;
+
+ if (cpufreq_minload_qos_request_active(req)) {
+ WARN(1, KERN_ERR "%s called for already added request\n", __func__);
+ return;
+ }
+
+ trace_pm_qos_add_request(value);
+
+ req->qos = &cpufreq_minload_constraints;
+ pm_qos_update_target(req->qos, &req->node, PM_QOS_ADD_REQ, value);
+}
+EXPORT_SYMBOL_GPL(cpufreq_minload_qos_add_request);
+
+/**
+ * cpufreq_minload_qos_update_request - Modify existing cpufreq minimum load
+ * QoS request.
+ * @req : QoS request to update.
+ * @new_value: New requested constraint value.
+ *
+ * Use @new_value to update the QoS request represented by @req in the cpufreq
+ * minimum load QoS list along with updating the effective constraint value for
+ * that list.
+ */
+void cpufreq_minload_qos_update_request(struct pm_qos_request *req,
+ s32 new_value)
+{
+ if (!req)
+ return;
+
+ if (!cpufreq_minload_qos_request_active(req)) {
+ WARN(1, KERN_ERR "%s called for unknown object\n", __func__);
+ return;
+ }
+
+ trace_pm_qos_update_request(new_value);
+
+ if (new_value == req->node.prio)
+ return;
+
+ pm_qos_update_target(req->qos, &req->node, PM_QOS_UPDATE_REQ, new_value);
+}
+EXPORT_SYMBOL_GPL(cpufreq_minload_qos_update_request);
+
+/**
+ * cpufreq_minload_qos_remove_request - Remove existing cpufreq minimum load QoS
+ * request.
+ * @req: QoS request to remove.
+ *
+ * Remove the cpufreq minimum load QoS request represented by @req from the
+ * cpufreq minimum load QoS list along with updating the effective constraint
+ * value for that list.
+ */
+void cpufreq_minload_qos_remove_request(struct pm_qos_request *req)
+{
+ if (!req)
+ return;
+
+ if (!cpufreq_minload_qos_request_active(req)) {
+ WARN(1, KERN_ERR "%s called for unknown object\n", __func__);
+ return;
+ }
+
+ trace_pm_qos_remove_request(PM_QOS_DEFAULT_VALUE);
+
+ pm_qos_update_target(req->qos, &req->node,
+ PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
+ memset(req, 0, sizeof(*req));
+}
+EXPORT_SYMBOL_GPL(cpufreq_minload_qos_remove_request);
+
+/* User space interface to the cpufreq minimum load QoS via misc device. */
+
+static int cpufreq_minload_qos_open(struct inode *inode, struct file *filp)
+{
+ struct pm_qos_request *req;
+
+ req = kzalloc(sizeof(*req), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ cpufreq_minload_qos_add_request(req, PM_QOS_DEFAULT_VALUE);
+ filp->private_data = req;
+
+ return 0;
+}
+
+static int cpufreq_minload_qos_release(struct inode *inode, struct file *filp)
+{
+ struct pm_qos_request *req = filp->private_data;
+
+ filp->private_data = NULL;
+
+ cpufreq_minload_qos_remove_request(req);
+ kfree(req);
+
+ return 0;
+}
+
+static ssize_t cpufreq_minload_qos_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ struct pm_qos_request *req = filp->private_data;
+ unsigned long flags;
+ s32 value;
+
+ if (!req || !cpufreq_minload_qos_request_active(req))
+ return -EINVAL;
+
+ spin_lock_irqsave(&pm_qos_lock, flags);
+ value = pm_qos_get_value(&cpufreq_minload_constraints);
+ spin_unlock_irqrestore(&pm_qos_lock, flags);
+
+ return simple_read_from_buffer(buf, count, f_pos, &value, sizeof(s32));
+}
+
+static ssize_t cpufreq_minload_qos_write(struct file *filp,
+ const char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ s32 value;
+
+ if (count == sizeof(s32)) {
+ if (copy_from_user(&value, buf, sizeof(s32)))
+ return -EFAULT;
+ } else {
+ int ret;
+
+ ret = kstrtos32_from_user(buf, count, 16, &value);
+ if (ret)
+ return ret;
+ }
+
+ cpufreq_minload_qos_update_request(filp->private_data, value);
+
+ return count;
+}
+
+static const struct file_operations cpufreq_minload_qos_fops = {
+ .write = cpufreq_minload_qos_write,
+ .read = cpufreq_minload_qos_read,
+ .open = cpufreq_minload_qos_open,
+ .release = cpufreq_minload_qos_release,
+ .llseek = noop_llseek,
+};
+
+static struct miscdevice cpufreq_minload_qos_miscdev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "cpufreq_minimum_load",
+ .fops = &cpufreq_minload_qos_fops,
+};
+
+static int __init cpufreq_minload_qos_init(void)
+{
+ int ret;
+
+ ret = misc_register(&cpufreq_minload_qos_miscdev);
+ if (ret < 0)
+ pr_err("%s: %s setup failed\n", __func__,
+ cpufreq_minload_qos_miscdev.name);
+
+ return ret;
+}
+late_initcall(cpufreq_minload_qos_init);
--
2.15.0
next prev parent reply other threads:[~2020-04-24 11:41 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-24 11:40 [RFC 0/3] Introduce cpufreq minimum load QoS Benjamin Gaignard
2020-04-24 11:40 ` Benjamin Gaignard [this message]
2020-04-24 11:40 ` [RFC 2/3] cpufreq: governor: Use " Benjamin Gaignard
2020-04-24 11:40 ` [RFC 3/3] media: stm32-dcmi: Inform cpufreq governors about cpu load needs Benjamin Gaignard
2020-04-29 15:50 ` [RFC 0/3] Introduce cpufreq minimum load QoS Rafael J. Wysocki
2020-04-29 15:57 ` Benjamin GAIGNARD
2020-04-29 16:12 ` Valentin Schneider
2020-04-30 7:52 ` Benjamin GAIGNARD
2020-04-30 9:03 ` Rafael J. Wysocki
2020-04-30 13:46 ` Benjamin GAIGNARD
2020-04-30 14:33 ` Valentin Schneider
2020-04-30 15:37 ` Benjamin GAIGNARD
2020-04-30 15:50 ` Valentin Schneider
2020-05-04 9:17 ` Benjamin GAIGNARD
2020-05-20 7:29 ` [Linux-stm32] " Benjamin GAIGNARD
2020-04-29 17:08 ` Vincent Guittot
2020-04-30 9:00 ` Rafael J. Wysocki
2020-05-26 15:16 [RFC RESEND " Benjamin Gaignard
2020-05-26 15:16 ` [RFC 1/3] PM: QoS: " Benjamin Gaignard
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=20200424114058.21199-2-benjamin.gaignard@st.com \
--to=benjamin.gaignard@st.com \
--cc=alexandre.torgue@st.com \
--cc=hugues.fruchet@st.com \
--cc=len.brown@intel.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=linux-stm32@st-md-mailman.stormreply.com \
--cc=mchehab@kernel.org \
--cc=mcoquelin.stm32@gmail.com \
--cc=pavel@ucw.cz \
--cc=rjw@rjwysocki.net \
--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).