Skip to content

Commit 36a8015

Browse files
cdleonardrafaeljw
authored andcommitted
PM / QoS: Restore DEV_PM_QOS_MIN/MAX_FREQUENCY
Support for adding per-device frequency limits was removed in commit 2aac8bd ("PM: QoS: Drop frequency QoS types from device PM QoS") after cpufreq switched to use a new "freq_constraints" construct. Restore support for per-device freq limits but base this upon freq_constraints. This is primarily meant to be used by the devfreq subsystem. This removes the "static" marking on freq_qos_apply but does not export it for modules. Signed-off-by: Leonard Crestez <[email protected]> Reviewed-by: Matthias Kaehlcke <[email protected]> Tested-by: Matthias Kaehlcke <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 342035f commit 36a8015

File tree

3 files changed

+82
-7
lines changed

3 files changed

+82
-7
lines changed

drivers/base/power/qos.c

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,20 @@ s32 dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type)
115115

116116
spin_lock_irqsave(&dev->power.lock, flags);
117117

118-
if (type == DEV_PM_QOS_RESUME_LATENCY) {
118+
switch (type) {
119+
case DEV_PM_QOS_RESUME_LATENCY:
119120
ret = IS_ERR_OR_NULL(qos) ? PM_QOS_RESUME_LATENCY_NO_CONSTRAINT
120121
: pm_qos_read_value(&qos->resume_latency);
121-
} else {
122+
break;
123+
case DEV_PM_QOS_MIN_FREQUENCY:
124+
ret = IS_ERR_OR_NULL(qos) ? PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE
125+
: freq_qos_read_value(&qos->freq, FREQ_QOS_MIN);
126+
break;
127+
case DEV_PM_QOS_MAX_FREQUENCY:
128+
ret = IS_ERR_OR_NULL(qos) ? PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE
129+
: freq_qos_read_value(&qos->freq, FREQ_QOS_MAX);
130+
break;
131+
default:
122132
WARN_ON(1);
123133
ret = 0;
124134
}
@@ -159,6 +169,10 @@ static int apply_constraint(struct dev_pm_qos_request *req,
159169
req->dev->power.set_latency_tolerance(req->dev, value);
160170
}
161171
break;
172+
case DEV_PM_QOS_MIN_FREQUENCY:
173+
case DEV_PM_QOS_MAX_FREQUENCY:
174+
ret = freq_qos_apply(&req->data.freq, action, value);
175+
break;
162176
case DEV_PM_QOS_FLAGS:
163177
ret = pm_qos_update_flags(&qos->flags, &req->data.flr,
164178
action, value);
@@ -209,6 +223,8 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
209223
c->no_constraint_value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT;
210224
c->type = PM_QOS_MIN;
211225

226+
freq_constraints_init(&qos->freq);
227+
212228
INIT_LIST_HEAD(&qos->flags.list);
213229

214230
spin_lock_irq(&dev->power.lock);
@@ -269,6 +285,20 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
269285
memset(req, 0, sizeof(*req));
270286
}
271287

288+
c = &qos->freq.min_freq;
289+
plist_for_each_entry_safe(req, tmp, &c->list, data.freq.pnode) {
290+
apply_constraint(req, PM_QOS_REMOVE_REQ,
291+
PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE);
292+
memset(req, 0, sizeof(*req));
293+
}
294+
295+
c = &qos->freq.max_freq;
296+
plist_for_each_entry_safe(req, tmp, &c->list, data.freq.pnode) {
297+
apply_constraint(req, PM_QOS_REMOVE_REQ,
298+
PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
299+
memset(req, 0, sizeof(*req));
300+
}
301+
272302
f = &qos->flags;
273303
list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) {
274304
apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
@@ -314,11 +344,22 @@ static int __dev_pm_qos_add_request(struct device *dev,
314344
ret = dev_pm_qos_constraints_allocate(dev);
315345

316346
trace_dev_pm_qos_add_request(dev_name(dev), type, value);
317-
if (!ret) {
318-
req->dev = dev;
319-
req->type = type;
347+
if (ret)
348+
return ret;
349+
350+
req->dev = dev;
351+
req->type = type;
352+
if (req->type == DEV_PM_QOS_MIN_FREQUENCY)
353+
ret = freq_qos_add_request(&dev->power.qos->freq,
354+
&req->data.freq,
355+
FREQ_QOS_MIN, value);
356+
else if (req->type == DEV_PM_QOS_MAX_FREQUENCY)
357+
ret = freq_qos_add_request(&dev->power.qos->freq,
358+
&req->data.freq,
359+
FREQ_QOS_MAX, value);
360+
else
320361
ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
321-
}
362+
322363
return ret;
323364
}
324365

@@ -382,6 +423,10 @@ static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req,
382423
case DEV_PM_QOS_LATENCY_TOLERANCE:
383424
curr_value = req->data.pnode.prio;
384425
break;
426+
case DEV_PM_QOS_MIN_FREQUENCY:
427+
case DEV_PM_QOS_MAX_FREQUENCY:
428+
curr_value = req->data.freq.pnode.prio;
429+
break;
385430
case DEV_PM_QOS_FLAGS:
386431
curr_value = req->data.flr.flags;
387432
break;
@@ -507,6 +552,14 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier,
507552
ret = blocking_notifier_chain_register(dev->power.qos->resume_latency.notifiers,
508553
notifier);
509554
break;
555+
case DEV_PM_QOS_MIN_FREQUENCY:
556+
ret = freq_qos_add_notifier(&dev->power.qos->freq,
557+
FREQ_QOS_MIN, notifier);
558+
break;
559+
case DEV_PM_QOS_MAX_FREQUENCY:
560+
ret = freq_qos_add_notifier(&dev->power.qos->freq,
561+
FREQ_QOS_MAX, notifier);
562+
break;
510563
default:
511564
WARN_ON(1);
512565
ret = -EINVAL;
@@ -546,6 +599,14 @@ int dev_pm_qos_remove_notifier(struct device *dev,
546599
ret = blocking_notifier_chain_unregister(dev->power.qos->resume_latency.notifiers,
547600
notifier);
548601
break;
602+
case DEV_PM_QOS_MIN_FREQUENCY:
603+
ret = freq_qos_remove_notifier(&dev->power.qos->freq,
604+
FREQ_QOS_MIN, notifier);
605+
break;
606+
case DEV_PM_QOS_MAX_FREQUENCY:
607+
ret = freq_qos_remove_notifier(&dev->power.qos->freq,
608+
FREQ_QOS_MAX, notifier);
609+
break;
549610
default:
550611
WARN_ON(1);
551612
ret = -EINVAL;

include/linux/pm_qos.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ enum pm_qos_flags_status {
3434
#define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT PM_QOS_LATENCY_ANY
3535
#define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS PM_QOS_LATENCY_ANY_NS
3636
#define PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE 0
37+
#define PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE 0
38+
#define PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE FREQ_QOS_MAX_DEFAULT_VALUE
3739
#define PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT (-1)
3840

3941
#define PM_QOS_FLAG_NO_POWER_OFF (1 << 0)
@@ -101,6 +103,8 @@ struct freq_qos_request {
101103
enum dev_pm_qos_req_type {
102104
DEV_PM_QOS_RESUME_LATENCY = 1,
103105
DEV_PM_QOS_LATENCY_TOLERANCE,
106+
DEV_PM_QOS_MIN_FREQUENCY,
107+
DEV_PM_QOS_MAX_FREQUENCY,
104108
DEV_PM_QOS_FLAGS,
105109
};
106110

@@ -109,13 +113,15 @@ struct dev_pm_qos_request {
109113
union {
110114
struct plist_node pnode;
111115
struct pm_qos_flags_request flr;
116+
struct freq_qos_request freq;
112117
} data;
113118
struct device *dev;
114119
};
115120

116121
struct dev_pm_qos {
117122
struct pm_qos_constraints resume_latency;
118123
struct pm_qos_constraints latency_tolerance;
124+
struct freq_constraints freq;
119125
struct pm_qos_flags flags;
120126
struct dev_pm_qos_request *resume_latency_req;
121127
struct dev_pm_qos_request *latency_tolerance_req;
@@ -214,6 +220,10 @@ static inline s32 dev_pm_qos_read_value(struct device *dev,
214220
switch (type) {
215221
case DEV_PM_QOS_RESUME_LATENCY:
216222
return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
223+
case DEV_PM_QOS_MIN_FREQUENCY:
224+
return PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE;
225+
case DEV_PM_QOS_MAX_FREQUENCY:
226+
return PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
217227
default:
218228
WARN_ON(1);
219229
return 0;
@@ -293,6 +303,8 @@ int freq_qos_add_request(struct freq_constraints *qos,
293303
enum freq_qos_req_type type, s32 value);
294304
int freq_qos_update_request(struct freq_qos_request *req, s32 new_value);
295305
int freq_qos_remove_request(struct freq_qos_request *req);
306+
int freq_qos_apply(struct freq_qos_request *req,
307+
enum pm_qos_req_action action, s32 value);
296308

297309
int freq_qos_add_notifier(struct freq_constraints *qos,
298310
enum freq_qos_req_type type,

kernel/power/qos.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -714,8 +714,10 @@ s32 freq_qos_read_value(struct freq_constraints *qos,
714714
* @req: Constraint request to apply.
715715
* @action: Action to perform (add/update/remove).
716716
* @value: Value to assign to the QoS request.
717+
*
718+
* This is only meant to be called from inside pm_qos, not drivers.
717719
*/
718-
static int freq_qos_apply(struct freq_qos_request *req,
720+
int freq_qos_apply(struct freq_qos_request *req,
719721
enum pm_qos_req_action action, s32 value)
720722
{
721723
int ret;

0 commit comments

Comments
 (0)