summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2019-07-04 03:36:20 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-07-04 04:40:54 -0400
commit208637b37824c8956fe28d277835a403ee35fa84 (patch)
tree645fc6e0353a09e80ff50bdda11541a9f0e2f33c
parent2a79ea5ec53973c8711b54d33ace5c77659dc8f8 (diff)
PM / QoS: Add support for MIN/MAX frequency constraints
This patch introduces the min-frequency and max-frequency device constraints, which will be used by the cpufreq core to begin with. Reviewed-by: Matthias Kaehlcke <mka@chromium.org> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/base/power/qos.c111
-rw-r--r--include/linux/pm_qos.h12
2 files changed, 109 insertions, 14 deletions
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c
index 2461fed0efa0..6c90fd7e2ff8 100644
--- a/drivers/base/power/qos.c
+++ b/drivers/base/power/qos.c
@@ -120,6 +120,14 @@ s32 dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type)
120 ret = IS_ERR_OR_NULL(qos) ? PM_QOS_RESUME_LATENCY_NO_CONSTRAINT 120 ret = IS_ERR_OR_NULL(qos) ? PM_QOS_RESUME_LATENCY_NO_CONSTRAINT
121 : pm_qos_read_value(&qos->resume_latency); 121 : pm_qos_read_value(&qos->resume_latency);
122 break; 122 break;
123 case DEV_PM_QOS_MIN_FREQUENCY:
124 ret = IS_ERR_OR_NULL(qos) ? PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE
125 : pm_qos_read_value(&qos->min_frequency);
126 break;
127 case DEV_PM_QOS_MAX_FREQUENCY:
128 ret = IS_ERR_OR_NULL(qos) ? PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE
129 : pm_qos_read_value(&qos->max_frequency);
130 break;
123 default: 131 default:
124 WARN_ON(1); 132 WARN_ON(1);
125 ret = 0; 133 ret = 0;
@@ -161,6 +169,14 @@ static int apply_constraint(struct dev_pm_qos_request *req,
161 req->dev->power.set_latency_tolerance(req->dev, value); 169 req->dev->power.set_latency_tolerance(req->dev, value);
162 } 170 }
163 break; 171 break;
172 case DEV_PM_QOS_MIN_FREQUENCY:
173 ret = pm_qos_update_target(&qos->min_frequency,
174 &req->data.pnode, action, value);
175 break;
176 case DEV_PM_QOS_MAX_FREQUENCY:
177 ret = pm_qos_update_target(&qos->max_frequency,
178 &req->data.pnode, action, value);
179 break;
164 case DEV_PM_QOS_FLAGS: 180 case DEV_PM_QOS_FLAGS:
165 ret = pm_qos_update_flags(&qos->flags, &req->data.flr, 181 ret = pm_qos_update_flags(&qos->flags, &req->data.flr,
166 action, value); 182 action, value);
@@ -189,12 +205,11 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
189 if (!qos) 205 if (!qos)
190 return -ENOMEM; 206 return -ENOMEM;
191 207
192 n = kzalloc(sizeof(*n), GFP_KERNEL); 208 n = kzalloc(3 * sizeof(*n), GFP_KERNEL);
193 if (!n) { 209 if (!n) {
194 kfree(qos); 210 kfree(qos);
195 return -ENOMEM; 211 return -ENOMEM;
196 } 212 }
197 BLOCKING_INIT_NOTIFIER_HEAD(n);
198 213
199 c = &qos->resume_latency; 214 c = &qos->resume_latency;
200 plist_head_init(&c->list); 215 plist_head_init(&c->list);
@@ -203,6 +218,7 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
203 c->no_constraint_value = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; 218 c->no_constraint_value = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
204 c->type = PM_QOS_MIN; 219 c->type = PM_QOS_MIN;
205 c->notifiers = n; 220 c->notifiers = n;
221 BLOCKING_INIT_NOTIFIER_HEAD(n);
206 222
207 c = &qos->latency_tolerance; 223 c = &qos->latency_tolerance;
208 plist_head_init(&c->list); 224 plist_head_init(&c->list);
@@ -211,6 +227,24 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
211 c->no_constraint_value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT; 227 c->no_constraint_value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT;
212 c->type = PM_QOS_MIN; 228 c->type = PM_QOS_MIN;
213 229
230 c = &qos->min_frequency;
231 plist_head_init(&c->list);
232 c->target_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE;
233 c->default_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE;
234 c->no_constraint_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE;
235 c->type = PM_QOS_MAX;
236 c->notifiers = ++n;
237 BLOCKING_INIT_NOTIFIER_HEAD(n);
238
239 c = &qos->max_frequency;
240 plist_head_init(&c->list);
241 c->target_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
242 c->default_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
243 c->no_constraint_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
244 c->type = PM_QOS_MIN;
245 c->notifiers = ++n;
246 BLOCKING_INIT_NOTIFIER_HEAD(n);
247
214 INIT_LIST_HEAD(&qos->flags.list); 248 INIT_LIST_HEAD(&qos->flags.list);
215 249
216 spin_lock_irq(&dev->power.lock); 250 spin_lock_irq(&dev->power.lock);
@@ -264,11 +298,25 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
264 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); 298 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
265 memset(req, 0, sizeof(*req)); 299 memset(req, 0, sizeof(*req));
266 } 300 }
301
267 c = &qos->latency_tolerance; 302 c = &qos->latency_tolerance;
268 plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) { 303 plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
269 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); 304 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
270 memset(req, 0, sizeof(*req)); 305 memset(req, 0, sizeof(*req));
271 } 306 }
307
308 c = &qos->min_frequency;
309 plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
310 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE);
311 memset(req, 0, sizeof(*req));
312 }
313
314 c = &qos->max_frequency;
315 plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
316 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
317 memset(req, 0, sizeof(*req));
318 }
319
272 f = &qos->flags; 320 f = &qos->flags;
273 list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) { 321 list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) {
274 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); 322 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
@@ -380,6 +428,8 @@ static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req,
380 switch(req->type) { 428 switch(req->type) {
381 case DEV_PM_QOS_RESUME_LATENCY: 429 case DEV_PM_QOS_RESUME_LATENCY:
382 case DEV_PM_QOS_LATENCY_TOLERANCE: 430 case DEV_PM_QOS_LATENCY_TOLERANCE:
431 case DEV_PM_QOS_MIN_FREQUENCY:
432 case DEV_PM_QOS_MAX_FREQUENCY:
383 curr_value = req->data.pnode.prio; 433 curr_value = req->data.pnode.prio;
384 break; 434 break;
385 case DEV_PM_QOS_FLAGS: 435 case DEV_PM_QOS_FLAGS:
@@ -492,9 +542,6 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier,
492{ 542{
493 int ret = 0; 543 int ret = 0;
494 544
495 if (WARN_ON(type != DEV_PM_QOS_RESUME_LATENCY))
496 return -EINVAL;
497
498 mutex_lock(&dev_pm_qos_mtx); 545 mutex_lock(&dev_pm_qos_mtx);
499 546
500 if (IS_ERR(dev->power.qos)) 547 if (IS_ERR(dev->power.qos))
@@ -502,10 +549,28 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier,
502 else if (!dev->power.qos) 549 else if (!dev->power.qos)
503 ret = dev_pm_qos_constraints_allocate(dev); 550 ret = dev_pm_qos_constraints_allocate(dev);
504 551
505 if (!ret) 552 if (ret)
553 goto unlock;
554
555 switch (type) {
556 case DEV_PM_QOS_RESUME_LATENCY:
506 ret = blocking_notifier_chain_register(dev->power.qos->resume_latency.notifiers, 557 ret = blocking_notifier_chain_register(dev->power.qos->resume_latency.notifiers,
507 notifier); 558 notifier);
559 break;
560 case DEV_PM_QOS_MIN_FREQUENCY:
561 ret = blocking_notifier_chain_register(dev->power.qos->min_frequency.notifiers,
562 notifier);
563 break;
564 case DEV_PM_QOS_MAX_FREQUENCY:
565 ret = blocking_notifier_chain_register(dev->power.qos->max_frequency.notifiers,
566 notifier);
567 break;
568 default:
569 WARN_ON(1);
570 ret = -EINVAL;
571 }
508 572
573unlock:
509 mutex_unlock(&dev_pm_qos_mtx); 574 mutex_unlock(&dev_pm_qos_mtx);
510 return ret; 575 return ret;
511} 576}
@@ -526,20 +591,35 @@ int dev_pm_qos_remove_notifier(struct device *dev,
526 struct notifier_block *notifier, 591 struct notifier_block *notifier,
527 enum dev_pm_qos_req_type type) 592 enum dev_pm_qos_req_type type)
528{ 593{
529 int retval = 0; 594 int ret = 0;
530
531 if (WARN_ON(type != DEV_PM_QOS_RESUME_LATENCY))
532 return -EINVAL;
533 595
534 mutex_lock(&dev_pm_qos_mtx); 596 mutex_lock(&dev_pm_qos_mtx);
535 597
536 /* Silently return if the constraints object is not present. */ 598 /* Silently return if the constraints object is not present. */
537 if (!IS_ERR_OR_NULL(dev->power.qos)) 599 if (IS_ERR_OR_NULL(dev->power.qos))
538 retval = blocking_notifier_chain_unregister(dev->power.qos->resume_latency.notifiers, 600 goto unlock;
539 notifier); 601
602 switch (type) {
603 case DEV_PM_QOS_RESUME_LATENCY:
604 ret = blocking_notifier_chain_unregister(dev->power.qos->resume_latency.notifiers,
605 notifier);
606 break;
607 case DEV_PM_QOS_MIN_FREQUENCY:
608 ret = blocking_notifier_chain_unregister(dev->power.qos->min_frequency.notifiers,
609 notifier);
610 break;
611 case DEV_PM_QOS_MAX_FREQUENCY:
612 ret = blocking_notifier_chain_unregister(dev->power.qos->max_frequency.notifiers,
613 notifier);
614 break;
615 default:
616 WARN_ON(1);
617 ret = -EINVAL;
618 }
540 619
620unlock:
541 mutex_unlock(&dev_pm_qos_mtx); 621 mutex_unlock(&dev_pm_qos_mtx);
542 return retval; 622 return ret;
543} 623}
544EXPORT_SYMBOL_GPL(dev_pm_qos_remove_notifier); 624EXPORT_SYMBOL_GPL(dev_pm_qos_remove_notifier);
545 625
@@ -599,6 +679,9 @@ static void __dev_pm_qos_drop_user_request(struct device *dev,
599 req = dev->power.qos->flags_req; 679 req = dev->power.qos->flags_req;
600 dev->power.qos->flags_req = NULL; 680 dev->power.qos->flags_req = NULL;
601 break; 681 break;
682 default:
683 WARN_ON(1);
684 return;
602 } 685 }
603 __dev_pm_qos_remove_request(req); 686 __dev_pm_qos_remove_request(req);
604 kfree(req); 687 kfree(req);
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h
index 9a21b7ba72ae..2aebbc5b9950 100644
--- a/include/linux/pm_qos.h
+++ b/include/linux/pm_qos.h
@@ -40,6 +40,8 @@ enum pm_qos_flags_status {
40#define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT PM_QOS_LATENCY_ANY 40#define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT PM_QOS_LATENCY_ANY
41#define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS PM_QOS_LATENCY_ANY_NS 41#define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS PM_QOS_LATENCY_ANY_NS
42#define PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE 0 42#define PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE 0
43#define PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE 0
44#define PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE (-1)
43#define PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT (-1) 45#define PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT (-1)
44 46
45#define PM_QOS_FLAG_NO_POWER_OFF (1 << 0) 47#define PM_QOS_FLAG_NO_POWER_OFF (1 << 0)
@@ -58,6 +60,8 @@ struct pm_qos_flags_request {
58enum dev_pm_qos_req_type { 60enum dev_pm_qos_req_type {
59 DEV_PM_QOS_RESUME_LATENCY = 1, 61 DEV_PM_QOS_RESUME_LATENCY = 1,
60 DEV_PM_QOS_LATENCY_TOLERANCE, 62 DEV_PM_QOS_LATENCY_TOLERANCE,
63 DEV_PM_QOS_MIN_FREQUENCY,
64 DEV_PM_QOS_MAX_FREQUENCY,
61 DEV_PM_QOS_FLAGS, 65 DEV_PM_QOS_FLAGS,
62}; 66};
63 67
@@ -99,10 +103,14 @@ struct pm_qos_flags {
99struct dev_pm_qos { 103struct dev_pm_qos {
100 struct pm_qos_constraints resume_latency; 104 struct pm_qos_constraints resume_latency;
101 struct pm_qos_constraints latency_tolerance; 105 struct pm_qos_constraints latency_tolerance;
106 struct pm_qos_constraints min_frequency;
107 struct pm_qos_constraints max_frequency;
102 struct pm_qos_flags flags; 108 struct pm_qos_flags flags;
103 struct dev_pm_qos_request *resume_latency_req; 109 struct dev_pm_qos_request *resume_latency_req;
104 struct dev_pm_qos_request *latency_tolerance_req; 110 struct dev_pm_qos_request *latency_tolerance_req;
105 struct dev_pm_qos_request *flags_req; 111 struct dev_pm_qos_request *flags_req;
112 struct dev_pm_qos_request *min_frequency_req;
113 struct dev_pm_qos_request *max_frequency_req;
106}; 114};
107 115
108/* Action requested to pm_qos_update_target */ 116/* Action requested to pm_qos_update_target */
@@ -197,6 +205,10 @@ static inline s32 dev_pm_qos_read_value(struct device *dev,
197 switch (type) { 205 switch (type) {
198 case DEV_PM_QOS_RESUME_LATENCY: 206 case DEV_PM_QOS_RESUME_LATENCY:
199 return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; 207 return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
208 case DEV_PM_QOS_MIN_FREQUENCY:
209 return PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE;
210 case DEV_PM_QOS_MAX_FREQUENCY:
211 return PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
200 default: 212 default:
201 WARN_ON(1); 213 WARN_ON(1);
202 return 0; 214 return 0;