* [PATCH V2 1/5] PM / QOS: Pass request type to dev_pm_qos_{add|remove}_notifier()
2019-02-21 11:29 [PATCH V2 0/5] cpufreq: Use QoS layer to manage freq-constraints Viresh Kumar
@ 2019-02-21 11:29 ` Viresh Kumar
2019-02-21 11:29 ` [PATCH V2 2/5] PM / QOS: Pass request type to dev_pm_qos_read_value() Viresh Kumar
` (4 subsequent siblings)
5 siblings, 0 replies; 16+ messages in thread
From: Viresh Kumar @ 2019-02-21 11:29 UTC (permalink / raw)
To: Rafael Wysocki, Len Brown, Pavel Machek, Kevin Hilman, Ulf Hansson
Cc: Viresh Kumar, linux-pm, Vincent Guittot, mka, juri.lelli,
Qais.Yousef, linux-kernel
In order to use the same set of routines to register notifiers for
different request types, update the existing
dev_pm_qos_{add|remove}_notifier() routines with an additional
parameter: request-type.
For now, it only supports resume-latency request type.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
Documentation/power/pm_qos_interface.txt | 10 ++++++----
drivers/base/power/domain.c | 8 +++++---
drivers/base/power/qos.c | 14 ++++++++++++--
include/linux/pm_qos.h | 12 ++++++++----
4 files changed, 31 insertions(+), 13 deletions(-)
diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt
index 19c5f7b1a7ba..ec7d662d1707 100644
--- a/Documentation/power/pm_qos_interface.txt
+++ b/Documentation/power/pm_qos_interface.txt
@@ -164,12 +164,14 @@ directory.
Notification mechanisms:
The per-device PM QoS framework has a per-device notification tree.
-int dev_pm_qos_add_notifier(device, notifier):
-Adds a notification callback function for the device.
+int dev_pm_qos_add_notifier(device, notifier, type):
+Adds a notification callback function for the device for a particular request
+type.
+
The callback is called when the aggregated value of the device constraints list
-is changed (for resume latency device PM QoS only).
+is changed.
-int dev_pm_qos_remove_notifier(device, notifier):
+int dev_pm_qos_remove_notifier(device, notifier, type):
Removes the notification callback function for the device.
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 2c334c01fc43..d8c37945a26d 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1486,7 +1486,8 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
if (ret)
genpd_free_dev_data(dev, gpd_data);
else
- dev_pm_qos_add_notifier(dev, &gpd_data->nb);
+ dev_pm_qos_add_notifier(dev, &gpd_data->nb,
+ DEV_PM_QOS_RESUME_LATENCY);
return ret;
}
@@ -1519,7 +1520,8 @@ static int genpd_remove_device(struct generic_pm_domain *genpd,
pdd = dev->power.subsys_data->domain_data;
gpd_data = to_gpd_data(pdd);
- dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
+ dev_pm_qos_remove_notifier(dev, &gpd_data->nb,
+ DEV_PM_QOS_RESUME_LATENCY);
genpd_lock(genpd);
@@ -1546,7 +1548,7 @@ static int genpd_remove_device(struct generic_pm_domain *genpd,
out:
genpd_unlock(genpd);
- dev_pm_qos_add_notifier(dev, &gpd_data->nb);
+ dev_pm_qos_add_notifier(dev, &gpd_data->nb, DEV_PM_QOS_RESUME_LATENCY);
return ret;
}
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c
index 3382542b39b7..49672f9dc8c4 100644
--- a/drivers/base/power/qos.c
+++ b/drivers/base/power/qos.c
@@ -471,6 +471,7 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request);
*
* @dev: target device for the constraint
* @notifier: notifier block managed by caller.
+ * @type: request type.
*
* Will register the notifier into a notification chain that gets called
* upon changes to the target value for the device.
@@ -478,10 +479,14 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request);
* If the device's constraints object doesn't exist when this routine is called,
* it will be created (or error code will be returned if that fails).
*/
-int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
+int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier,
+ enum dev_pm_qos_req_type type)
{
int ret = 0;
+ if (WARN_ON(type != DEV_PM_QOS_RESUME_LATENCY))
+ return -EINVAL;
+
mutex_lock(&dev_pm_qos_mtx);
if (IS_ERR(dev->power.qos))
@@ -504,15 +509,20 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_add_notifier);
*
* @dev: target device for the constraint
* @notifier: notifier block to be removed.
+ * @type: request type.
*
* Will remove the notifier from the notification chain that gets called
* upon changes to the target value.
*/
int dev_pm_qos_remove_notifier(struct device *dev,
- struct notifier_block *notifier)
+ struct notifier_block *notifier,
+ enum dev_pm_qos_req_type type)
{
int retval = 0;
+ if (WARN_ON(type != DEV_PM_QOS_RESUME_LATENCY))
+ return -EINVAL;
+
mutex_lock(&dev_pm_qos_mtx);
/* Silently return if the constraints object is not present. */
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h
index 6ea1ae373d77..1f4d456e8fff 100644
--- a/include/linux/pm_qos.h
+++ b/include/linux/pm_qos.h
@@ -146,9 +146,11 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value);
int dev_pm_qos_remove_request(struct dev_pm_qos_request *req);
int dev_pm_qos_add_notifier(struct device *dev,
- struct notifier_block *notifier);
+ struct notifier_block *notifier,
+ enum dev_pm_qos_req_type type);
int dev_pm_qos_remove_notifier(struct device *dev,
- struct notifier_block *notifier);
+ struct notifier_block *notifier,
+ enum dev_pm_qos_req_type type);
void dev_pm_qos_constraints_init(struct device *dev);
void dev_pm_qos_constraints_destroy(struct device *dev);
int dev_pm_qos_add_ancestor_request(struct device *dev,
@@ -202,10 +204,12 @@ static inline int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
static inline int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
{ return 0; }
static inline int dev_pm_qos_add_notifier(struct device *dev,
- struct notifier_block *notifier)
+ struct notifier_block *notifier,
+ enum dev_pm_qos_req_type type);
{ return 0; }
static inline int dev_pm_qos_remove_notifier(struct device *dev,
- struct notifier_block *notifier)
+ struct notifier_block *notifier,
+ enum dev_pm_qos_req_type type)
{ return 0; }
static inline void dev_pm_qos_constraints_init(struct device *dev)
{
--
2.21.0.rc0.269.g1a574e7a288b
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH V2 2/5] PM / QOS: Pass request type to dev_pm_qos_read_value()
2019-02-21 11:29 [PATCH V2 0/5] cpufreq: Use QoS layer to manage freq-constraints Viresh Kumar
2019-02-21 11:29 ` [PATCH V2 1/5] PM / QOS: Pass request type to dev_pm_qos_{add|remove}_notifier() Viresh Kumar
@ 2019-02-21 11:29 ` Viresh Kumar
2019-02-21 11:29 ` [PATCH V2 3/5] PM / QoS: Add support for MIN/MAX frequency constraints Viresh Kumar
` (3 subsequent siblings)
5 siblings, 0 replies; 16+ messages in thread
From: Viresh Kumar @ 2019-02-21 11:29 UTC (permalink / raw)
To: Rafael Wysocki, Len Brown, Pavel Machek, Kevin Hilman,
Ulf Hansson, Daniel Lezcano
Cc: Viresh Kumar, linux-pm, Vincent Guittot, mka, juri.lelli,
Qais.Yousef, linux-kernel
In order to use dev_pm_qos_read_value(), and other internal routines to
it, to read values for different QoS requests, pass request type as a
parameter to these routines.
For now, it only supports resume-latency request type.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
Documentation/power/pm_qos_interface.txt | 2 +-
drivers/base/power/domain_governor.c | 4 +--
drivers/base/power/qos.c | 10 +++---
drivers/base/power/runtime.c | 2 +-
drivers/cpuidle/governor.c | 2 +-
include/linux/pm_qos.h | 41 +++++++++++++++++-------
6 files changed, 40 insertions(+), 21 deletions(-)
diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt
index ec7d662d1707..cfcb1df39799 100644
--- a/Documentation/power/pm_qos_interface.txt
+++ b/Documentation/power/pm_qos_interface.txt
@@ -123,7 +123,7 @@ Will remove the element. After removal it will update the aggregate target and
call the notification trees if the target was changed as a result of removing
the request.
-s32 dev_pm_qos_read_value(device):
+s32 dev_pm_qos_read_value(device, type):
Returns the aggregated value for a given device's constraints list.
enum pm_qos_flags_status dev_pm_qos_flags(device, mask)
diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c
index 99896fbf18e4..c36925adba69 100644
--- a/drivers/base/power/domain_governor.c
+++ b/drivers/base/power/domain_governor.c
@@ -32,7 +32,7 @@ static int dev_update_qos_constraint(struct device *dev, void *data)
* take its current PM QoS constraint (that's the only thing
* known at this point anyway).
*/
- constraint_ns = dev_pm_qos_read_value(dev);
+ constraint_ns = dev_pm_qos_read_value(dev, DEV_PM_QOS_RESUME_LATENCY);
constraint_ns *= NSEC_PER_USEC;
}
@@ -65,7 +65,7 @@ static bool default_suspend_ok(struct device *dev)
td->constraint_changed = false;
td->cached_suspend_ok = false;
td->effective_constraint_ns = 0;
- constraint_ns = __dev_pm_qos_read_value(dev);
+ constraint_ns = __dev_pm_qos_read_value(dev, DEV_PM_QOS_RESUME_LATENCY);
spin_unlock_irqrestore(&dev->power.lock, flags);
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c
index 49672f9dc8c4..fda7266970e9 100644
--- a/drivers/base/power/qos.c
+++ b/drivers/base/power/qos.c
@@ -96,27 +96,29 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_flags);
/**
* __dev_pm_qos_read_value - Get PM QoS constraint for a given device.
* @dev: Device to get the PM QoS constraint value for.
+ * @type: QoS request type.
*
* This routine must be called with dev->power.lock held.
*/
-s32 __dev_pm_qos_read_value(struct device *dev)
+s32 __dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type)
{
lockdep_assert_held(&dev->power.lock);
- return dev_pm_qos_raw_read_value(dev);
+ return dev_pm_qos_raw_read_value(dev, type);
}
/**
* dev_pm_qos_read_value - Get PM QoS constraint for a given device (locked).
* @dev: Device to get the PM QoS constraint value for.
+ * @type: QoS request type.
*/
-s32 dev_pm_qos_read_value(struct device *dev)
+s32 dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type)
{
unsigned long flags;
s32 ret;
spin_lock_irqsave(&dev->power.lock, flags);
- ret = __dev_pm_qos_read_value(dev);
+ ret = __dev_pm_qos_read_value(dev, type);
spin_unlock_irqrestore(&dev->power.lock, flags);
return ret;
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 04407d9f76fd..997cd420accc 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -267,7 +267,7 @@ static int rpm_check_suspend_allowed(struct device *dev)
|| (dev->power.request_pending
&& dev->power.request == RPM_REQ_RESUME))
retval = -EAGAIN;
- else if (__dev_pm_qos_read_value(dev) == 0)
+ else if (__dev_pm_qos_read_value(dev, DEV_PM_QOS_RESUME_LATENCY) == 0)
retval = -EPERM;
else if (dev->power.runtime_status == RPM_SUSPENDED)
retval = 1;
diff --git a/drivers/cpuidle/governor.c b/drivers/cpuidle/governor.c
index bb93e5cf6a4a..251d3ef4a1e5 100644
--- a/drivers/cpuidle/governor.c
+++ b/drivers/cpuidle/governor.c
@@ -109,7 +109,7 @@ int cpuidle_governor_latency_req(unsigned int cpu)
{
int global_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
struct device *device = get_cpu_device(cpu);
- int device_req = dev_pm_qos_raw_read_value(device);
+ int device_req = dev_pm_qos_raw_read_value(device, DEV_PM_QOS_RESUME_LATENCY);
return device_req < global_req ? device_req : global_req;
}
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h
index 1f4d456e8fff..55814d48c39c 100644
--- a/include/linux/pm_qos.h
+++ b/include/linux/pm_qos.h
@@ -139,8 +139,8 @@ s32 pm_qos_read_value(struct pm_qos_constraints *c);
#ifdef CONFIG_PM
enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask);
enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask);
-s32 __dev_pm_qos_read_value(struct device *dev);
-s32 dev_pm_qos_read_value(struct device *dev);
+s32 __dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type);
+s32 dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type);
int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
enum dev_pm_qos_req_type type, s32 value);
int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value);
@@ -176,11 +176,19 @@ static inline s32 dev_pm_qos_requested_flags(struct device *dev)
return dev->power.qos->flags_req->data.flr.flags;
}
-static inline s32 dev_pm_qos_raw_read_value(struct device *dev)
+static inline s32 dev_pm_qos_raw_read_value(struct device *dev,
+ enum dev_pm_qos_req_type type)
{
- return IS_ERR_OR_NULL(dev->power.qos) ?
- PM_QOS_RESUME_LATENCY_NO_CONSTRAINT :
- pm_qos_read_value(&dev->power.qos->resume_latency);
+ struct dev_pm_qos *qos = dev->power.qos;
+
+ switch (type) {
+ case DEV_PM_QOS_RESUME_LATENCY:
+ return IS_ERR_OR_NULL(qos) ? PM_QOS_RESUME_LATENCY_NO_CONSTRAINT
+ : pm_qos_read_value(&qos->resume_latency);
+ default:
+ WARN_ON(1);
+ return 0;
+ }
}
#else
static inline enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev,
@@ -189,10 +197,6 @@ static inline enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev,
static inline enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev,
s32 mask)
{ return PM_QOS_FLAGS_UNDEFINED; }
-static inline s32 __dev_pm_qos_read_value(struct device *dev)
- { return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; }
-static inline s32 dev_pm_qos_read_value(struct device *dev)
- { return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; }
static inline int dev_pm_qos_add_request(struct device *dev,
struct dev_pm_qos_request *req,
enum dev_pm_qos_req_type type,
@@ -245,10 +249,23 @@ static inline s32 dev_pm_qos_requested_resume_latency(struct device *dev)
return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
}
static inline s32 dev_pm_qos_requested_flags(struct device *dev) { return 0; }
-static inline s32 dev_pm_qos_raw_read_value(struct device *dev)
+
+static inline s32 dev_pm_qos_raw_read_value(struct device *dev,
+ enum dev_pm_qos_req_type type)
{
- return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
+ switch type {
+ case DEV_PM_QOS_RESUME_LATENCY:
+ return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
+ default:
+ WARN_ON(1);
+ return 0;
+ }
}
+
+static inline s32 __dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type)
+ { return dev_pm_qos_raw_read_value(dev, type); }
+static inline s32 dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type)
+ { return dev_pm_qos_raw_read_value(dev, type); }
#endif
#endif
--
2.21.0.rc0.269.g1a574e7a288b
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH V2 3/5] PM / QoS: Add support for MIN/MAX frequency constraints
2019-02-21 11:29 [PATCH V2 0/5] cpufreq: Use QoS layer to manage freq-constraints Viresh Kumar
2019-02-21 11:29 ` [PATCH V2 1/5] PM / QOS: Pass request type to dev_pm_qos_{add|remove}_notifier() Viresh Kumar
2019-02-21 11:29 ` [PATCH V2 2/5] PM / QOS: Pass request type to dev_pm_qos_read_value() Viresh Kumar
@ 2019-02-21 11:29 ` Viresh Kumar
2019-02-21 11:29 ` [PATCH V2 4/5] cpufreq: Register notifiers with the PM QoS framework Viresh Kumar
` (2 subsequent siblings)
5 siblings, 0 replies; 16+ messages in thread
From: Viresh Kumar @ 2019-02-21 11:29 UTC (permalink / raw)
To: Rafael Wysocki, Pavel Machek, Len Brown
Cc: Viresh Kumar, linux-pm, Vincent Guittot, mka, juri.lelli,
Qais.Yousef, linux-kernel
This patch introduces the min-frequency and max-frequency device
constraints, which will be used by the cpufreq core to begin with.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
drivers/base/power/qos.c | 103 +++++++++++++++++++++++++++++++++------
include/linux/pm_qos.h | 18 +++++++
2 files changed, 107 insertions(+), 14 deletions(-)
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c
index fda7266970e9..30fe1e98b343 100644
--- a/drivers/base/power/qos.c
+++ b/drivers/base/power/qos.c
@@ -155,6 +155,14 @@ static int apply_constraint(struct dev_pm_qos_request *req,
req->dev->power.set_latency_tolerance(req->dev, value);
}
break;
+ case DEV_PM_QOS_MIN_FREQUENCY:
+ ret = pm_qos_update_target(&qos->min_frequency,
+ &req->data.pnode, action, value);
+ break;
+ case DEV_PM_QOS_MAX_FREQUENCY:
+ ret = pm_qos_update_target(&qos->max_frequency,
+ &req->data.pnode, action, value);
+ break;
case DEV_PM_QOS_FLAGS:
ret = pm_qos_update_flags(&qos->flags, &req->data.flr,
action, value);
@@ -183,12 +191,11 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
if (!qos)
return -ENOMEM;
- n = kzalloc(sizeof(*n), GFP_KERNEL);
+ n = kzalloc(3 * sizeof(*n), GFP_KERNEL);
if (!n) {
kfree(qos);
return -ENOMEM;
}
- BLOCKING_INIT_NOTIFIER_HEAD(n);
c = &qos->resume_latency;
plist_head_init(&c->list);
@@ -197,6 +204,7 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
c->no_constraint_value = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
c->type = PM_QOS_MIN;
c->notifiers = n;
+ BLOCKING_INIT_NOTIFIER_HEAD(n);
c = &qos->latency_tolerance;
plist_head_init(&c->list);
@@ -205,6 +213,24 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
c->no_constraint_value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT;
c->type = PM_QOS_MIN;
+ c = &qos->min_frequency;
+ plist_head_init(&c->list);
+ c->target_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE;
+ c->default_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE;
+ c->no_constraint_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE;
+ c->type = PM_QOS_MAX;
+ c->notifiers = ++n;
+ BLOCKING_INIT_NOTIFIER_HEAD(n);
+
+ c = &qos->max_frequency;
+ plist_head_init(&c->list);
+ c->target_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
+ c->default_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
+ c->no_constraint_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
+ c->type = PM_QOS_MIN;
+ c->notifiers = ++n;
+ BLOCKING_INIT_NOTIFIER_HEAD(n);
+
INIT_LIST_HEAD(&qos->flags.list);
spin_lock_irq(&dev->power.lock);
@@ -258,11 +284,25 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
memset(req, 0, sizeof(*req));
}
+
c = &qos->latency_tolerance;
plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
memset(req, 0, sizeof(*req));
}
+
+ c = &qos->min_frequency;
+ plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
+ apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE);
+ memset(req, 0, sizeof(*req));
+ }
+
+ c = &qos->max_frequency;
+ plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
+ apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
+ memset(req, 0, sizeof(*req));
+ }
+
f = &qos->flags;
list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) {
apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
@@ -374,6 +414,8 @@ static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req,
switch(req->type) {
case DEV_PM_QOS_RESUME_LATENCY:
case DEV_PM_QOS_LATENCY_TOLERANCE:
+ case DEV_PM_QOS_MIN_FREQUENCY:
+ case DEV_PM_QOS_MAX_FREQUENCY:
curr_value = req->data.pnode.prio;
break;
case DEV_PM_QOS_FLAGS:
@@ -486,9 +528,6 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier,
{
int ret = 0;
- if (WARN_ON(type != DEV_PM_QOS_RESUME_LATENCY))
- return -EINVAL;
-
mutex_lock(&dev_pm_qos_mtx);
if (IS_ERR(dev->power.qos))
@@ -496,10 +535,28 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier,
else if (!dev->power.qos)
ret = dev_pm_qos_constraints_allocate(dev);
- if (!ret)
+ if (ret)
+ goto unlock;
+
+ switch (type) {
+ case DEV_PM_QOS_RESUME_LATENCY:
ret = blocking_notifier_chain_register(dev->power.qos->resume_latency.notifiers,
notifier);
+ break;
+ case DEV_PM_QOS_MIN_FREQUENCY:
+ ret = blocking_notifier_chain_register(dev->power.qos->min_frequency.notifiers,
+ notifier);
+ break;
+ case DEV_PM_QOS_MAX_FREQUENCY:
+ ret = blocking_notifier_chain_register(dev->power.qos->max_frequency.notifiers,
+ notifier);
+ break;
+ default:
+ WARN_ON(1);
+ ret = -EINVAL;
+ }
+unlock:
mutex_unlock(&dev_pm_qos_mtx);
return ret;
}
@@ -520,20 +577,35 @@ int dev_pm_qos_remove_notifier(struct device *dev,
struct notifier_block *notifier,
enum dev_pm_qos_req_type type)
{
- int retval = 0;
-
- if (WARN_ON(type != DEV_PM_QOS_RESUME_LATENCY))
- return -EINVAL;
+ int ret = 0;
mutex_lock(&dev_pm_qos_mtx);
/* Silently return if the constraints object is not present. */
- if (!IS_ERR_OR_NULL(dev->power.qos))
- retval = blocking_notifier_chain_unregister(dev->power.qos->resume_latency.notifiers,
- notifier);
+ if (IS_ERR_OR_NULL(dev->power.qos))
+ goto unlock;
+ switch (type) {
+ case DEV_PM_QOS_RESUME_LATENCY:
+ ret = blocking_notifier_chain_unregister(dev->power.qos->resume_latency.notifiers,
+ notifier);
+ break;
+ case DEV_PM_QOS_MIN_FREQUENCY:
+ ret = blocking_notifier_chain_unregister(dev->power.qos->min_frequency.notifiers,
+ notifier);
+ break;
+ case DEV_PM_QOS_MAX_FREQUENCY:
+ ret = blocking_notifier_chain_unregister(dev->power.qos->max_frequency.notifiers,
+ notifier);
+ break;
+ default:
+ WARN_ON(1);
+ ret = -EINVAL;
+ }
+
+unlock:
mutex_unlock(&dev_pm_qos_mtx);
- return retval;
+ return ret;
}
EXPORT_SYMBOL_GPL(dev_pm_qos_remove_notifier);
@@ -593,6 +665,9 @@ static void __dev_pm_qos_drop_user_request(struct device *dev,
req = dev->power.qos->flags_req;
dev->power.qos->flags_req = NULL;
break;
+ default:
+ WARN_ON(1);
+ return;
}
__dev_pm_qos_remove_request(req);
kfree(req);
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h
index 55814d48c39c..3f994283a5ae 100644
--- a/include/linux/pm_qos.h
+++ b/include/linux/pm_qos.h
@@ -40,6 +40,8 @@ enum pm_qos_flags_status {
#define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT PM_QOS_LATENCY_ANY
#define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS PM_QOS_LATENCY_ANY_NS
#define PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE 0
+#define PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE 0
+#define PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE (-1)
#define PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT (-1)
#define PM_QOS_FLAG_NO_POWER_OFF (1 << 0)
@@ -58,6 +60,8 @@ struct pm_qos_flags_request {
enum dev_pm_qos_req_type {
DEV_PM_QOS_RESUME_LATENCY = 1,
DEV_PM_QOS_LATENCY_TOLERANCE,
+ DEV_PM_QOS_MIN_FREQUENCY,
+ DEV_PM_QOS_MAX_FREQUENCY,
DEV_PM_QOS_FLAGS,
};
@@ -99,10 +103,14 @@ struct pm_qos_flags {
struct dev_pm_qos {
struct pm_qos_constraints resume_latency;
struct pm_qos_constraints latency_tolerance;
+ struct pm_qos_constraints min_frequency;
+ struct pm_qos_constraints max_frequency;
struct pm_qos_flags flags;
struct dev_pm_qos_request *resume_latency_req;
struct dev_pm_qos_request *latency_tolerance_req;
struct dev_pm_qos_request *flags_req;
+ struct dev_pm_qos_request *min_frequency_req;
+ struct dev_pm_qos_request *max_frequency_req;
};
/* Action requested to pm_qos_update_target */
@@ -185,6 +193,12 @@ static inline s32 dev_pm_qos_raw_read_value(struct device *dev,
case DEV_PM_QOS_RESUME_LATENCY:
return IS_ERR_OR_NULL(qos) ? PM_QOS_RESUME_LATENCY_NO_CONSTRAINT
: pm_qos_read_value(&qos->resume_latency);
+ case DEV_PM_QOS_MIN_FREQUENCY:
+ return IS_ERR_OR_NULL(qos) ? PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE
+ : pm_qos_read_value(&qos->min_frequency);
+ case DEV_PM_QOS_MAX_FREQUENCY:
+ return IS_ERR_OR_NULL(qos) ? PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE
+ : pm_qos_read_value(&qos->max_frequency);
default:
WARN_ON(1);
return 0;
@@ -256,6 +270,10 @@ static inline s32 dev_pm_qos_raw_read_value(struct device *dev,
switch type {
case DEV_PM_QOS_RESUME_LATENCY:
return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
+ case DEV_PM_QOS_MIN_FREQUENCY:
+ return PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE;
+ case DEV_PM_QOS_MAX_FREQUENCY:
+ return PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
default:
WARN_ON(1);
return 0;
--
2.21.0.rc0.269.g1a574e7a288b
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH V2 4/5] cpufreq: Register notifiers with the PM QoS framework
2019-02-21 11:29 [PATCH V2 0/5] cpufreq: Use QoS layer to manage freq-constraints Viresh Kumar
` (2 preceding siblings ...)
2019-02-21 11:29 ` [PATCH V2 3/5] PM / QoS: Add support for MIN/MAX frequency constraints Viresh Kumar
@ 2019-02-21 11:29 ` Viresh Kumar
2019-02-22 11:44 ` Qais Yousef
2019-02-21 11:29 ` [PATCH V2 5/5] cpufreq: Add QoS requests for userspace constraints Viresh Kumar
2019-02-21 11:30 ` [PATCH V2 0/5] cpufreq: Use QoS layer to manage freq-constraints Rafael J. Wysocki
5 siblings, 1 reply; 16+ messages in thread
From: Viresh Kumar @ 2019-02-21 11:29 UTC (permalink / raw)
To: Rafael Wysocki
Cc: Viresh Kumar, linux-pm, Vincent Guittot, mka, juri.lelli,
Qais.Yousef, linux-kernel
This registers the notifiers for min/max frequency constraints with the
PM QoS framework. The constraints are also taken into consideration in
cpufreq_set_policy().
This also relocates cpufreq_policy_put_kobj() as it is required to be
called from cpufreq_policy_alloc() now.
No constraints are added until now though.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
drivers/cpufreq/cpufreq.c | 135 +++++++++++++++++++++++++++++++-------
include/linux/cpufreq.h | 4 ++
2 files changed, 116 insertions(+), 23 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 0e626b00053b..d615bf35ac00 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -26,6 +26,7 @@
#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/pm_qos.h>
#include <linux/slab.h>
#include <linux/suspend.h>
#include <linux/syscore_ops.h>
@@ -1082,11 +1083,77 @@ static void handle_update(struct work_struct *work)
cpufreq_update_policy(cpu);
}
+static void cpufreq_update_freq_work(struct work_struct *work)
+{
+ struct cpufreq_policy *policy =
+ container_of(work, struct cpufreq_policy, req_work);
+ struct cpufreq_policy new_policy = *policy;
+
+ /* We should read constraint values from QoS layer */
+ new_policy.min = 0;
+ new_policy.max = UINT_MAX;
+
+ down_write(&policy->rwsem);
+
+ if (!policy_is_inactive(policy))
+ cpufreq_set_policy(policy, &new_policy);
+
+ up_write(&policy->rwsem);
+}
+
+static int cpufreq_update_freq(struct cpufreq_policy *policy)
+{
+ schedule_work(&policy->req_work);
+ return 0;
+}
+
+static int cpufreq_notifier_min(struct notifier_block *nb, unsigned long freq,
+ void *data)
+{
+ struct cpufreq_policy *policy = container_of(nb, struct cpufreq_policy, nb_min);
+
+ return cpufreq_update_freq(policy);
+}
+
+static int cpufreq_notifier_max(struct notifier_block *nb, unsigned long freq,
+ void *data)
+{
+ struct cpufreq_policy *policy = container_of(nb, struct cpufreq_policy, nb_max);
+
+ return cpufreq_update_freq(policy);
+}
+
+static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy)
+{
+ struct kobject *kobj;
+ struct completion *cmp;
+
+ down_write(&policy->rwsem);
+ cpufreq_stats_free_table(policy);
+ kobj = &policy->kobj;
+ cmp = &policy->kobj_unregister;
+ up_write(&policy->rwsem);
+ kobject_put(kobj);
+
+ /*
+ * We need to make sure that the underlying kobj is
+ * actually not referenced anymore by anybody before we
+ * proceed with unloading.
+ */
+ pr_debug("waiting for dropping of refcount\n");
+ wait_for_completion(cmp);
+ pr_debug("wait complete\n");
+}
+
static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
{
struct cpufreq_policy *policy;
+ struct device *dev = get_cpu_device(cpu);
int ret;
+ if (!dev)
+ return NULL;
+
policy = kzalloc(sizeof(*policy), GFP_KERNEL);
if (!policy)
return NULL;
@@ -1103,20 +1170,45 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
cpufreq_global_kobject, "policy%u", cpu);
if (ret) {
- pr_err("%s: failed to init policy->kobj: %d\n", __func__, ret);
+ dev_err(dev, "%s: failed to init policy->kobj: %d\n", __func__, ret);
goto err_free_real_cpus;
}
+ policy->nb_min.notifier_call = cpufreq_notifier_min;
+ policy->nb_max.notifier_call = cpufreq_notifier_max;
+
+ ret = dev_pm_qos_add_notifier(dev, &policy->nb_min,
+ DEV_PM_QOS_MIN_FREQUENCY);
+ if (ret) {
+ dev_err(dev, "Failed to register MIN QoS notifier: %d (%*pbl)\n",
+ ret, cpumask_pr_args(policy->cpus));
+ goto err_kobj_remove;
+ }
+
+ ret = dev_pm_qos_add_notifier(dev, &policy->nb_max,
+ DEV_PM_QOS_MAX_FREQUENCY);
+ if (ret) {
+ dev_err(dev, "Failed to register MAX QoS notifier: %d (%*pbl)\n",
+ ret, cpumask_pr_args(policy->cpus));
+ goto err_min_qos_notifier;
+ }
+
INIT_LIST_HEAD(&policy->policy_list);
init_rwsem(&policy->rwsem);
spin_lock_init(&policy->transition_lock);
init_waitqueue_head(&policy->transition_wait);
init_completion(&policy->kobj_unregister);
INIT_WORK(&policy->update, handle_update);
+ INIT_WORK(&policy->req_work, cpufreq_update_freq_work);
policy->cpu = cpu;
return policy;
+err_min_qos_notifier:
+ dev_pm_qos_remove_notifier(dev, &policy->nb_min,
+ DEV_PM_QOS_MIN_FREQUENCY);
+err_kobj_remove:
+ cpufreq_policy_put_kobj(policy);
err_free_real_cpus:
free_cpumask_var(policy->real_cpus);
err_free_rcpumask:
@@ -1129,30 +1221,9 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
return NULL;
}
-static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy)
-{
- struct kobject *kobj;
- struct completion *cmp;
-
- down_write(&policy->rwsem);
- cpufreq_stats_free_table(policy);
- kobj = &policy->kobj;
- cmp = &policy->kobj_unregister;
- up_write(&policy->rwsem);
- kobject_put(kobj);
-
- /*
- * We need to make sure that the underlying kobj is
- * actually not referenced anymore by anybody before we
- * proceed with unloading.
- */
- pr_debug("waiting for dropping of refcount\n");
- wait_for_completion(cmp);
- pr_debug("wait complete\n");
-}
-
static void cpufreq_policy_free(struct cpufreq_policy *policy)
{
+ struct device *dev = get_cpu_device(policy->cpu);
unsigned long flags;
int cpu;
@@ -1164,6 +1235,10 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
per_cpu(cpufreq_cpu_data, cpu) = NULL;
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+ dev_pm_qos_remove_notifier(dev, &policy->nb_max,
+ DEV_PM_QOS_MAX_FREQUENCY);
+ dev_pm_qos_remove_notifier(dev, &policy->nb_min,
+ DEV_PM_QOS_MIN_FREQUENCY);
cpufreq_policy_put_kobj(policy);
free_cpumask_var(policy->real_cpus);
free_cpumask_var(policy->related_cpus);
@@ -2239,6 +2314,8 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
struct cpufreq_policy *new_policy)
{
struct cpufreq_governor *old_gov;
+ struct device *cpu_dev = get_cpu_device(policy->cpu);
+ unsigned long min, max;
int ret;
pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
@@ -2253,11 +2330,23 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
if (new_policy->min > new_policy->max)
return -EINVAL;
+ min = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MIN_FREQUENCY);
+ max = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MAX_FREQUENCY);
+
+ if (min > new_policy->min)
+ new_policy->min = min;
+ if (max < new_policy->max)
+ new_policy->max = max;
+
/* verify the cpu speed can be set within this limit */
ret = cpufreq_driver->verify(new_policy);
if (ret)
return ret;
+ /*
+ * The notifier-chain shall be removed once all the users of
+ * CPUFREQ_ADJUST are moved to use the QoS framework.
+ */
/* adjust if necessary - all reasons */
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_ADJUST, new_policy);
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index b160e98076e3..f8f48d8a9b52 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -90,6 +90,7 @@ struct cpufreq_policy {
struct work_struct update; /* if update_policy() needs to be
* called, but you're in IRQ context */
+ struct work_struct req_work;
struct cpufreq_user_policy user_policy;
struct cpufreq_frequency_table *freq_table;
@@ -154,6 +155,9 @@ struct cpufreq_policy {
/* Pointer to the cooling device if used for thermal mitigation */
struct thermal_cooling_device *cdev;
+
+ struct notifier_block nb_min;
+ struct notifier_block nb_max;
};
/* Only for ACPI */
--
2.21.0.rc0.269.g1a574e7a288b
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH V2 4/5] cpufreq: Register notifiers with the PM QoS framework
2019-02-21 11:29 ` [PATCH V2 4/5] cpufreq: Register notifiers with the PM QoS framework Viresh Kumar
@ 2019-02-22 11:44 ` Qais Yousef
2019-02-25 4:31 ` Viresh Kumar
0 siblings, 1 reply; 16+ messages in thread
From: Qais Yousef @ 2019-02-22 11:44 UTC (permalink / raw)
To: Viresh Kumar
Cc: Rafael Wysocki, linux-pm, Vincent Guittot, mka, juri.lelli, linux-kernel
Hi Verish
On 02/21/19 16:59, Viresh Kumar wrote:
[...]
> @@ -2239,6 +2314,8 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
> struct cpufreq_policy *new_policy)
> {
> struct cpufreq_governor *old_gov;
> + struct device *cpu_dev = get_cpu_device(policy->cpu);
> + unsigned long min, max;
> int ret;
>
> pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
> @@ -2253,11 +2330,23 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
> if (new_policy->min > new_policy->max)
> return -EINVAL;
>
> + min = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MIN_FREQUENCY);
> + max = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MAX_FREQUENCY);
> +
> + if (min > new_policy->min)
> + new_policy->min = min;
> + if (max < new_policy->max)
> + new_policy->max = max;
> +
Assuming for example min and max range from 1-10, and thermal throttles max to
5 using pm_qos to deal with temporary thermal pressure. But shortly after
a driver thinks that max shouldn't be greater than 7 for one reason or another.
What will happen after thermal pressure removes its constraint? Will we still
remember the driver's request and apply it so max is set to 7 instead of 10?
Thanks
--
Qais Yousef
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH V2 4/5] cpufreq: Register notifiers with the PM QoS framework
2019-02-22 11:44 ` Qais Yousef
@ 2019-02-25 4:31 ` Viresh Kumar
2019-02-25 8:58 ` Qais Yousef
0 siblings, 1 reply; 16+ messages in thread
From: Viresh Kumar @ 2019-02-25 4:31 UTC (permalink / raw)
To: Qais Yousef
Cc: Rafael Wysocki, linux-pm, Vincent Guittot, mka, juri.lelli, linux-kernel
On 22-02-19, 11:44, Qais Yousef wrote:
> Hi Verish
>
> On 02/21/19 16:59, Viresh Kumar wrote:
>
> [...]
>
> > @@ -2239,6 +2314,8 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
> > struct cpufreq_policy *new_policy)
> > {
> > struct cpufreq_governor *old_gov;
> > + struct device *cpu_dev = get_cpu_device(policy->cpu);
> > + unsigned long min, max;
> > int ret;
> >
> > pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
> > @@ -2253,11 +2330,23 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
> > if (new_policy->min > new_policy->max)
> > return -EINVAL;
> >
> > + min = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MIN_FREQUENCY);
> > + max = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MAX_FREQUENCY);
> > +
> > + if (min > new_policy->min)
> > + new_policy->min = min;
> > + if (max < new_policy->max)
> > + new_policy->max = max;
> > +
>
> Assuming for example min and max range from 1-10, and thermal throttles max to
> 5 using pm_qos to deal with temporary thermal pressure. But shortly after
> a driver thinks that max shouldn't be greater than 7 for one reason or another.
>
> What will happen after thermal pressure removes its constraint? Will we still
> remember the driver's request and apply it so max is set to 7 instead of 10?
Once everything comes via PM QoS, it will remember all the presently available
requests and choose a target min/max frequency based on that.
But even with this patchset, with half stuff done with PM QoS and half done with
cpufreq notifiers, it should still work that way only.
--
viresh
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH V2 4/5] cpufreq: Register notifiers with the PM QoS framework
2019-02-25 4:31 ` Viresh Kumar
@ 2019-02-25 8:58 ` Qais Yousef
2019-02-25 9:09 ` Viresh Kumar
0 siblings, 1 reply; 16+ messages in thread
From: Qais Yousef @ 2019-02-25 8:58 UTC (permalink / raw)
To: Viresh Kumar
Cc: Rafael Wysocki, linux-pm, Vincent Guittot, mka, juri.lelli, linux-kernel
On 02/25/19 10:01, Viresh Kumar wrote:
> On 22-02-19, 11:44, Qais Yousef wrote:
> > Hi Verish
> >
> > On 02/21/19 16:59, Viresh Kumar wrote:
> >
> > [...]
> >
> > > @@ -2239,6 +2314,8 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
> > > struct cpufreq_policy *new_policy)
> > > {
> > > struct cpufreq_governor *old_gov;
> > > + struct device *cpu_dev = get_cpu_device(policy->cpu);
> > > + unsigned long min, max;
> > > int ret;
> > >
> > > pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
> > > @@ -2253,11 +2330,23 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
> > > if (new_policy->min > new_policy->max)
> > > return -EINVAL;
> > >
> > > + min = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MIN_FREQUENCY);
> > > + max = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MAX_FREQUENCY);
> > > +
> > > + if (min > new_policy->min)
> > > + new_policy->min = min;
> > > + if (max < new_policy->max)
> > > + new_policy->max = max;
> > > +
> >
> > Assuming for example min and max range from 1-10, and thermal throttles max to
> > 5 using pm_qos to deal with temporary thermal pressure. But shortly after
> > a driver thinks that max shouldn't be greater than 7 for one reason or another.
> >
> > What will happen after thermal pressure removes its constraint? Will we still
> > remember the driver's request and apply it so max is set to 7 instead of 10?
>
> Once everything comes via PM QoS, it will remember all the presently available
> requests and choose a target min/max frequency based on that.
OK I can see the logic now in kernel/power/qos.c now. Sorry I missed it and it
was easier to ask :-)
>
> But even with this patchset, with half stuff done with PM QoS and half done with
> cpufreq notifiers, it should still work that way only.
And this is why we need to check here if the PM QoS value doesn't conflict with
the current min/max, right? Until the current notifier code is removed they
could trip over each others.
It would be nice to add a comment here about PM QoS managing and remembering
values and that we need to be careful that both mechanisms don't trip over
each others until this transient period is over.
I have a nit too. It would be nice to explicitly state this is
CPU_{MIN,MAX}_FREQUENCY. I can see someone else adding {MIN,MAX}_FREQUENCY for
something elsee (memory maybe?)
Although I looked at the previous series briefly, but this one looks more
compact and easier to follow, so +1 for that.
--
Qais Yousef
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH V2 4/5] cpufreq: Register notifiers with the PM QoS framework
2019-02-25 8:58 ` Qais Yousef
@ 2019-02-25 9:09 ` Viresh Kumar
2019-02-25 12:14 ` Qais Yousef
0 siblings, 1 reply; 16+ messages in thread
From: Viresh Kumar @ 2019-02-25 9:09 UTC (permalink / raw)
To: Qais Yousef
Cc: Rafael Wysocki, linux-pm, Vincent Guittot, mka, juri.lelli, linux-kernel
On 25-02-19, 08:58, Qais Yousef wrote:
> On 02/25/19 10:01, Viresh Kumar wrote:
> > > > + min = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MIN_FREQUENCY);
> > > > + max = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MAX_FREQUENCY);
> > > > +
> > > > + if (min > new_policy->min)
> > > > + new_policy->min = min;
> > > > + if (max < new_policy->max)
> > > > + new_policy->max = max;
> And this is why we need to check here if the PM QoS value doesn't conflict with
> the current min/max, right? Until the current notifier code is removed they
> could trip over each others.
No. The above if/else block is already removed as part of patch 5/5. It was
required because of conflict between userspace specific min/max and qos min/max,
which are migrated to use qos by patc 5/5.
The cpufreq notifier mechanism already lets users play with min/max and that is
already safe from conflicts.
> It would be nice to add a comment here about PM QoS managing and remembering
> values
I am not sure if that would add any value. Some documentation update may be
useful for people looking for details though, that I shall do after all the
changes get in and things become a bit stable.
> and that we need to be careful that both mechanisms don't trip over
> each others until this transient period is over.
The second mechanism will die very very soon once this is merged, migrating them
shouldn't be a big challenge AFAICT. I didn't attempt that because I didn't
wanted to waste time updating things in case this version also doesn't make
sense to others.
> I have a nit too. It would be nice to explicitly state this is
> CPU_{MIN,MAX}_FREQUENCY. I can see someone else adding {MIN,MAX}_FREQUENCY for
> something elsee (memory maybe?)
This is not CPU specific, but any device. The same interface shall be used by
devfreq as well, who wanted to use freq-constraints initially.
> Although I looked at the previous series briefly, but this one looks more
> compact and easier to follow, so +1 for that.
Thanks for looking into this Qais.
--
viresh
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH V2 4/5] cpufreq: Register notifiers with the PM QoS framework
2019-02-25 9:09 ` Viresh Kumar
@ 2019-02-25 12:14 ` Qais Yousef
2019-02-26 2:30 ` Viresh Kumar
0 siblings, 1 reply; 16+ messages in thread
From: Qais Yousef @ 2019-02-25 12:14 UTC (permalink / raw)
To: Viresh Kumar
Cc: Rafael Wysocki, linux-pm, Vincent Guittot, mka, juri.lelli, linux-kernel
On 02/25/19 14:39, Viresh Kumar wrote:
> On 25-02-19, 08:58, Qais Yousef wrote:
> > On 02/25/19 10:01, Viresh Kumar wrote:
> > > > > + min = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MIN_FREQUENCY);
> > > > > + max = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MAX_FREQUENCY);
> > > > > +
> > > > > + if (min > new_policy->min)
> > > > > + new_policy->min = min;
> > > > > + if (max < new_policy->max)
> > > > > + new_policy->max = max;
>
> > And this is why we need to check here if the PM QoS value doesn't conflict with
> > the current min/max, right? Until the current notifier code is removed they
> > could trip over each others.
>
> No. The above if/else block is already removed as part of patch 5/5. It was
> required because of conflict between userspace specific min/max and qos min/max,
> which are migrated to use qos by patc 5/5.
>
> The cpufreq notifier mechanism already lets users play with min/max and that is
> already safe from conflicts.
>
>
> > It would be nice to add a comment here about PM QoS managing and remembering
> > values
>
> I am not sure if that would add any value. Some documentation update may be
> useful for people looking for details though, that I shall do after all the
> changes get in and things become a bit stable.
>
Up to you. But not everyone is familiar with the code and a one line comment
that points to where aggregation is happening would be helpful for someone
scanning this code IMHO.
> > and that we need to be careful that both mechanisms don't trip over
> > each others until this transient period is over.
>
> The second mechanism will die very very soon once this is merged, migrating them
> shouldn't be a big challenge AFAICT. I didn't attempt that because I didn't
> wanted to waste time updating things in case this version also doesn't make
> sense to others.
>
> > I have a nit too. It would be nice to explicitly state this is
> > CPU_{MIN,MAX}_FREQUENCY. I can see someone else adding {MIN,MAX}_FREQUENCY for
> > something elsee (memory maybe?)
>
> This is not CPU specific, but any device. The same interface shall be used by
> devfreq as well, who wanted to use freq-constraints initially.
>
I don't get that to be honest. I probably have to read more.
Is what you're saying that when applying a MIN_FREQUENCY constraint the same
value will be applied to both cpufreq and devfreq? Isn't this too coarse?
> > Although I looked at the previous series briefly, but this one looks more
> > compact and easier to follow, so +1 for that.
>
> Thanks for looking into this Qais.
>
> --
> viresh
Thanks
--
Qais Yousef
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH V2 4/5] cpufreq: Register notifiers with the PM QoS framework
2019-02-25 12:14 ` Qais Yousef
@ 2019-02-26 2:30 ` Viresh Kumar
2019-02-26 10:00 ` Qais Yousef
0 siblings, 1 reply; 16+ messages in thread
From: Viresh Kumar @ 2019-02-26 2:30 UTC (permalink / raw)
To: Qais Yousef
Cc: Rafael Wysocki, linux-pm, Vincent Guittot, mka, juri.lelli, linux-kernel
On 25-02-19, 12:14, Qais Yousef wrote:
> On 02/25/19 14:39, Viresh Kumar wrote:
> > On 25-02-19, 08:58, Qais Yousef wrote:
> > > On 02/25/19 10:01, Viresh Kumar wrote:
> > > > > > + min = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MIN_FREQUENCY);
> > > > > > + max = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MAX_FREQUENCY);
> > > > > > +
> > > > > > + if (min > new_policy->min)
> > > > > > + new_policy->min = min;
> > > > > > + if (max < new_policy->max)
> > > > > > + new_policy->max = max;
> >
> > > And this is why we need to check here if the PM QoS value doesn't conflict with
> > > the current min/max, right? Until the current notifier code is removed they
> > > could trip over each others.
> >
> > No. The above if/else block is already removed as part of patch 5/5. It was
> > required because of conflict between userspace specific min/max and qos min/max,
> > which are migrated to use qos by patc 5/5.
> >
> > The cpufreq notifier mechanism already lets users play with min/max and that is
> > already safe from conflicts.
> >
> >
> > > It would be nice to add a comment here about PM QoS managing and remembering
> > > values
> >
> > I am not sure if that would add any value. Some documentation update may be
> > useful for people looking for details though, that I shall do after all the
> > changes get in and things become a bit stable.
> >
>
> Up to you. But not everyone is familiar with the code and a one line comment
> that points to where aggregation is happening would be helpful for someone
> scanning this code IMHO.
Okay, will add something then.
> > > and that we need to be careful that both mechanisms don't trip over
> > > each others until this transient period is over.
> >
> > The second mechanism will die very very soon once this is merged, migrating them
> > shouldn't be a big challenge AFAICT. I didn't attempt that because I didn't
> > wanted to waste time updating things in case this version also doesn't make
> > sense to others.
> >
> > > I have a nit too. It would be nice to explicitly state this is
> > > CPU_{MIN,MAX}_FREQUENCY. I can see someone else adding {MIN,MAX}_FREQUENCY for
> > > something elsee (memory maybe?)
> >
> > This is not CPU specific, but any device. The same interface shall be used by
> > devfreq as well, who wanted to use freq-constraints initially.
> >
>
> I don't get that to be honest. I probably have to read more.
>
> Is what you're saying that when applying a MIN_FREQUENCY constraint the same
> value will be applied to both cpufreq and devfreq? Isn't this too coarse?
Oh no. A constraint with QoS is added like this:
dev_pm_qos_add_request(dev, req, DEV_PM_QOS_MIN_FREQUENCY, min);
Now dev here can be any device struct, CPU's or GPU's or anything else. All the
MIN freq requests are stored/processed per device and for a CPU in cpufreq all
we will see is MIN requests for the CPUs. And so the macro is required to be a
bit generic and shouldn't have CPU word within it.
Hope I was able to clarify your doubt a bit. Thanks.
--
viresh
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH V2 4/5] cpufreq: Register notifiers with the PM QoS framework
2019-02-26 2:30 ` Viresh Kumar
@ 2019-02-26 10:00 ` Qais Yousef
0 siblings, 0 replies; 16+ messages in thread
From: Qais Yousef @ 2019-02-26 10:00 UTC (permalink / raw)
To: Viresh Kumar
Cc: Rafael Wysocki, linux-pm, Vincent Guittot, mka, juri.lelli, linux-kernel
On 02/26/19 08:00, Viresh Kumar wrote:
> On 25-02-19, 12:14, Qais Yousef wrote:
> > On 02/25/19 14:39, Viresh Kumar wrote:
> > > On 25-02-19, 08:58, Qais Yousef wrote:
> > > > On 02/25/19 10:01, Viresh Kumar wrote:
> > > > > > > + min = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MIN_FREQUENCY);
> > > > > > > + max = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MAX_FREQUENCY);
> > > > > > > +
> > > > > > > + if (min > new_policy->min)
> > > > > > > + new_policy->min = min;
> > > > > > > + if (max < new_policy->max)
> > > > > > > + new_policy->max = max;
> > >
> > > > And this is why we need to check here if the PM QoS value doesn't conflict with
> > > > the current min/max, right? Until the current notifier code is removed they
> > > > could trip over each others.
> > >
> > > No. The above if/else block is already removed as part of patch 5/5. It was
> > > required because of conflict between userspace specific min/max and qos min/max,
> > > which are migrated to use qos by patc 5/5.
> > >
> > > The cpufreq notifier mechanism already lets users play with min/max and that is
> > > already safe from conflicts.
> > >
> > >
> > > > It would be nice to add a comment here about PM QoS managing and remembering
> > > > values
> > >
> > > I am not sure if that would add any value. Some documentation update may be
> > > useful for people looking for details though, that I shall do after all the
> > > changes get in and things become a bit stable.
> > >
> >
> > Up to you. But not everyone is familiar with the code and a one line comment
> > that points to where aggregation is happening would be helpful for someone
> > scanning this code IMHO.
>
> Okay, will add something then.
>
> > > > and that we need to be careful that both mechanisms don't trip over
> > > > each others until this transient period is over.
> > >
> > > The second mechanism will die very very soon once this is merged, migrating them
> > > shouldn't be a big challenge AFAICT. I didn't attempt that because I didn't
> > > wanted to waste time updating things in case this version also doesn't make
> > > sense to others.
> > >
> > > > I have a nit too. It would be nice to explicitly state this is
> > > > CPU_{MIN,MAX}_FREQUENCY. I can see someone else adding {MIN,MAX}_FREQUENCY for
> > > > something elsee (memory maybe?)
> > >
> > > This is not CPU specific, but any device. The same interface shall be used by
> > > devfreq as well, who wanted to use freq-constraints initially.
> > >
> >
> > I don't get that to be honest. I probably have to read more.
> >
> > Is what you're saying that when applying a MIN_FREQUENCY constraint the same
> > value will be applied to both cpufreq and devfreq? Isn't this too coarse?
>
> Oh no. A constraint with QoS is added like this:
>
> dev_pm_qos_add_request(dev, req, DEV_PM_QOS_MIN_FREQUENCY, min);
>
> Now dev here can be any device struct, CPU's or GPU's or anything else. All the
> MIN freq requests are stored/processed per device and for a CPU in cpufreq all
> we will see is MIN requests for the CPUs. And so the macro is required to be a
> bit generic and shouldn't have CPU word within it.
>
> Hope I was able to clarify your doubt a bit. Thanks.
Ah I see yes it all makes sense now.
Thanks!
--
Qais Yousef
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH V2 5/5] cpufreq: Add QoS requests for userspace constraints
2019-02-21 11:29 [PATCH V2 0/5] cpufreq: Use QoS layer to manage freq-constraints Viresh Kumar
` (3 preceding siblings ...)
2019-02-21 11:29 ` [PATCH V2 4/5] cpufreq: Register notifiers with the PM QoS framework Viresh Kumar
@ 2019-02-21 11:29 ` Viresh Kumar
2019-02-21 11:30 ` [PATCH V2 0/5] cpufreq: Use QoS layer to manage freq-constraints Rafael J. Wysocki
5 siblings, 0 replies; 16+ messages in thread
From: Viresh Kumar @ 2019-02-21 11:29 UTC (permalink / raw)
To: Rafael Wysocki
Cc: Viresh Kumar, linux-pm, Vincent Guittot, mka, juri.lelli,
Qais.Yousef, linux-kernel
This implements QoS requests to manage userspace configuration of min
and max frequency.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
drivers/cpufreq/cpufreq.c | 93 +++++++++++++++++++--------------------
include/linux/cpufreq.h | 8 +---
2 files changed, 48 insertions(+), 53 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index d615bf35ac00..403e4540aea7 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -686,23 +686,15 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
static ssize_t store_##file_name \
(struct cpufreq_policy *policy, const char *buf, size_t count) \
{ \
- int ret, temp; \
- struct cpufreq_policy new_policy; \
+ unsigned long val; \
+ int ret; \
\
- memcpy(&new_policy, policy, sizeof(*policy)); \
- new_policy.min = policy->user_policy.min; \
- new_policy.max = policy->user_policy.max; \
- \
- ret = sscanf(buf, "%u", &new_policy.object); \
+ ret = sscanf(buf, "%lu", &val); \
if (ret != 1) \
return -EINVAL; \
\
- temp = new_policy.object; \
- ret = cpufreq_set_policy(policy, &new_policy); \
- if (!ret) \
- policy->user_policy.object = temp; \
- \
- return ret ? ret : count; \
+ ret = dev_pm_qos_update_request(policy->object##_freq_req, val);\
+ return ret && ret != 1 ? ret : count; \
}
store_one(scaling_min_freq, min);
@@ -1089,10 +1081,6 @@ static void cpufreq_update_freq_work(struct work_struct *work)
container_of(work, struct cpufreq_policy, req_work);
struct cpufreq_policy new_policy = *policy;
- /* We should read constraint values from QoS layer */
- new_policy.min = 0;
- new_policy.max = UINT_MAX;
-
down_write(&policy->rwsem);
if (!policy_is_inactive(policy))
@@ -1193,6 +1181,12 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
goto err_min_qos_notifier;
}
+ policy->min_freq_req = kzalloc(2 * sizeof(*policy->min_freq_req),
+ GFP_KERNEL);
+ if (!policy->min_freq_req)
+ goto err_max_qos_notifier;
+
+ policy->max_freq_req = policy->min_freq_req + 1;
INIT_LIST_HEAD(&policy->policy_list);
init_rwsem(&policy->rwsem);
spin_lock_init(&policy->transition_lock);
@@ -1204,6 +1198,9 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
policy->cpu = cpu;
return policy;
+err_max_qos_notifier:
+ dev_pm_qos_remove_notifier(dev, &policy->nb_max,
+ DEV_PM_QOS_MAX_FREQUENCY);
err_min_qos_notifier:
dev_pm_qos_remove_notifier(dev, &policy->nb_min,
DEV_PM_QOS_MIN_FREQUENCY);
@@ -1239,6 +1236,10 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
DEV_PM_QOS_MAX_FREQUENCY);
dev_pm_qos_remove_notifier(dev, &policy->nb_min,
DEV_PM_QOS_MIN_FREQUENCY);
+ dev_pm_qos_remove_request(policy->max_freq_req);
+ dev_pm_qos_remove_request(policy->min_freq_req);
+ kfree(policy->min_freq_req);
+
cpufreq_policy_put_kobj(policy);
free_cpumask_var(policy->real_cpus);
free_cpumask_var(policy->related_cpus);
@@ -1316,16 +1317,30 @@ static int cpufreq_online(unsigned int cpu)
cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
if (new_policy) {
- policy->user_policy.min = policy->min;
- policy->user_policy.max = policy->max;
+ struct device *dev = get_cpu_device(cpu);
for_each_cpu(j, policy->related_cpus) {
per_cpu(cpufreq_cpu_data, j) = policy;
add_cpu_dev_symlink(policy, j);
}
- } else {
- policy->min = policy->user_policy.min;
- policy->max = policy->user_policy.max;
+
+ ret = dev_pm_qos_add_request(dev, policy->min_freq_req,
+ DEV_PM_QOS_MIN_FREQUENCY,
+ policy->min);
+ if (ret < 0) {
+ dev_err(dev, "Failed to add min-freq constraint (%d)\n",
+ ret);
+ goto out_destroy_policy;
+ }
+
+ ret = dev_pm_qos_add_request(dev, policy->max_freq_req,
+ DEV_PM_QOS_MAX_FREQUENCY,
+ policy->max);
+ if (ret < 0) {
+ dev_err(dev, "Failed to add max-freq constraint (%d)\n",
+ ret);
+ goto out_destroy_policy;
+ }
}
if (cpufreq_driver->get && !cpufreq_driver->setpolicy) {
@@ -2315,7 +2330,6 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
{
struct cpufreq_governor *old_gov;
struct device *cpu_dev = get_cpu_device(policy->cpu);
- unsigned long min, max;
int ret;
pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
@@ -2323,20 +2337,9 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
- /*
- * This check works well when we store new min/max freq attributes,
- * because new_policy is a copy of policy with one field updated.
- */
- if (new_policy->min > new_policy->max)
- return -EINVAL;
-
- min = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MIN_FREQUENCY);
- max = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MAX_FREQUENCY);
-
- if (min > new_policy->min)
- new_policy->min = min;
- if (max < new_policy->max)
- new_policy->max = max;
+ /* Start with min/max as seen by QoS framework */
+ new_policy->min = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MIN_FREQUENCY);
+ new_policy->max = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MAX_FREQUENCY);
/* verify the cpu speed can be set within this limit */
ret = cpufreq_driver->verify(new_policy);
@@ -2425,10 +2428,9 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
* @cpu: CPU to re-evaluate the policy for.
*
* Update the current frequency for the cpufreq policy of @cpu and use
- * cpufreq_set_policy() to re-apply the min and max limits saved in the
- * user_policy sub-structure of that policy, which triggers the evaluation
- * of policy notifiers and the cpufreq driver's ->verify() callback for the
- * policy in question, among other things.
+ * cpufreq_set_policy() to re-apply the min and max limits, which triggers the
+ * evaluation of policy notifiers and the cpufreq driver's ->verify() callback
+ * for the policy in question, among other things.
*/
void cpufreq_update_policy(unsigned int cpu)
{
@@ -2453,8 +2455,6 @@ void cpufreq_update_policy(unsigned int cpu)
pr_debug("updating policy for CPU %u\n", cpu);
memcpy(&new_policy, policy, sizeof(*policy));
- new_policy.min = policy->user_policy.min;
- new_policy.max = policy->user_policy.max;
cpufreq_set_policy(policy, &new_policy);
@@ -2485,10 +2485,9 @@ static int cpufreq_boost_set_sw(int state)
break;
}
- down_write(&policy->rwsem);
- policy->user_policy.max = policy->max;
- cpufreq_governor_limits(policy);
- up_write(&policy->rwsem);
+ ret = dev_pm_qos_update_request(policy->max_freq_req, policy->max);
+ if (ret)
+ break;
}
return ret;
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index f8f48d8a9b52..fc167a982c64 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -57,11 +57,6 @@ struct cpufreq_cpuinfo {
unsigned int transition_latency;
};
-struct cpufreq_user_policy {
- unsigned int min; /* in kHz */
- unsigned int max; /* in kHz */
-};
-
struct cpufreq_policy {
/* CPUs sharing clock, require sw coordination */
cpumask_var_t cpus; /* Online CPUs only */
@@ -92,7 +87,8 @@ struct cpufreq_policy {
* called, but you're in IRQ context */
struct work_struct req_work;
- struct cpufreq_user_policy user_policy;
+ struct dev_pm_qos_request *min_freq_req;
+ struct dev_pm_qos_request *max_freq_req;
struct cpufreq_frequency_table *freq_table;
enum cpufreq_table_sorting freq_table_sorted;
--
2.21.0.rc0.269.g1a574e7a288b
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH V2 0/5] cpufreq: Use QoS layer to manage freq-constraints
2019-02-21 11:29 [PATCH V2 0/5] cpufreq: Use QoS layer to manage freq-constraints Viresh Kumar
` (4 preceding siblings ...)
2019-02-21 11:29 ` [PATCH V2 5/5] cpufreq: Add QoS requests for userspace constraints Viresh Kumar
@ 2019-02-21 11:30 ` Rafael J. Wysocki
2019-04-08 10:46 ` Viresh Kumar
2019-05-20 6:16 ` Viresh Kumar
5 siblings, 2 replies; 16+ messages in thread
From: Rafael J. Wysocki @ 2019-02-21 11:30 UTC (permalink / raw)
To: Viresh Kumar
Cc: Daniel Lezcano, Kevin Hilman, Len Brown, Pavel Machek,
Ulf Hansson, linux-pm, Vincent Guittot, mka, juri.lelli,
Qais.Yousef, linux-kernel
On Thursday, February 21, 2019 12:29:26 PM CET Viresh Kumar wrote:
> Hello,
>
> This patchset attempts to manage CPU frequency constraints using the PM
> QoS framework. It only does the basic stuff right now and moves the
> userspace constraints to use the QoS infrastructure.
>
> Todo:
> - Migrate all users to the QoS framework and get rid of cpufreq specific
> notifiers.
> - Make PM QoS learn about the relation of CPUs in a policy, so a single
> list of constraints is managed for all of them instead of per-cpu
> constraints.
>
> V1->V2:
> - The previous version introduced a completely new framework, this one
> moves to PM QoS instead.
> - Lots of changes because of this.
Well, thanks for working on this, but I'm rather unlikely to look at it in
detail before 5.1-rc1 is released.
Cheers,
Rafael
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH V2 0/5] cpufreq: Use QoS layer to manage freq-constraints
2019-02-21 11:30 ` [PATCH V2 0/5] cpufreq: Use QoS layer to manage freq-constraints Rafael J. Wysocki
@ 2019-04-08 10:46 ` Viresh Kumar
2019-05-20 6:16 ` Viresh Kumar
1 sibling, 0 replies; 16+ messages in thread
From: Viresh Kumar @ 2019-04-08 10:46 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Daniel Lezcano, Kevin Hilman, Len Brown, Pavel Machek,
Ulf Hansson, linux-pm, Vincent Guittot, mka, juri.lelli,
Qais.Yousef, linux-kernel
On 21-02-19, 12:30, Rafael J. Wysocki wrote:
> On Thursday, February 21, 2019 12:29:26 PM CET Viresh Kumar wrote:
> > Hello,
> >
> > This patchset attempts to manage CPU frequency constraints using the PM
> > QoS framework. It only does the basic stuff right now and moves the
> > userspace constraints to use the QoS infrastructure.
> >
> > Todo:
> > - Migrate all users to the QoS framework and get rid of cpufreq specific
> > notifiers.
> > - Make PM QoS learn about the relation of CPUs in a policy, so a single
> > list of constraints is managed for all of them instead of per-cpu
> > constraints.
> >
> > V1->V2:
> > - The previous version introduced a completely new framework, this one
> > moves to PM QoS instead.
> > - Lots of changes because of this.
>
> Well, thanks for working on this, but I'm rather unlikely to look at it in
> detail before 5.1-rc1 is released.
Ping!
--
viresh
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V2 0/5] cpufreq: Use QoS layer to manage freq-constraints
2019-02-21 11:30 ` [PATCH V2 0/5] cpufreq: Use QoS layer to manage freq-constraints Rafael J. Wysocki
2019-04-08 10:46 ` Viresh Kumar
@ 2019-05-20 6:16 ` Viresh Kumar
1 sibling, 0 replies; 16+ messages in thread
From: Viresh Kumar @ 2019-05-20 6:16 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Daniel Lezcano, Kevin Hilman, Len Brown, Pavel Machek,
Ulf Hansson, linux-pm, Vincent Guittot, mka, juri.lelli,
Qais.Yousef, linux-kernel
On 21-02-19, 12:30, Rafael J. Wysocki wrote:
> On Thursday, February 21, 2019 12:29:26 PM CET Viresh Kumar wrote:
> > Hello,
> >
> > This patchset attempts to manage CPU frequency constraints using the PM
> > QoS framework. It only does the basic stuff right now and moves the
> > userspace constraints to use the QoS infrastructure.
> >
> > Todo:
> > - Migrate all users to the QoS framework and get rid of cpufreq specific
> > notifiers.
> > - Make PM QoS learn about the relation of CPUs in a policy, so a single
> > list of constraints is managed for all of them instead of per-cpu
> > constraints.
> >
> > V1->V2:
> > - The previous version introduced a completely new framework, this one
> > moves to PM QoS instead.
> > - Lots of changes because of this.
>
> Well, thanks for working on this, but I'm rather unlikely to look at it in
> detail before 5.1-rc1 is released.
Hi Rafael,
This series was posted almost 3 months back. Any comments on this would be very
helpful.
--
viresh
^ permalink raw reply [flat|nested] 16+ messages in thread