aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/power
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-29 15:40:32 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-29 15:40:32 -0500
commitc8b6817103b23ed42114516fea901c2f61271506 (patch)
treef3a54c55a37cfa02496de62c0f0b89f2a52dc219 /drivers/base/power
parent9489e9dcae718d5fde988e4a684a0f55b5f94d17 (diff)
parent35546bd477146b75ae2a9ff2cb9bfcdb0f701015 (diff)
Merge branch 'pm-qos'
* pm-qos: PM / QoS: Handle device PM QoS flags while removing constraints PM / QoS: Resume device before exposing/hiding PM QoS flags PM / QoS: Document request manipulation requirement for flags PM / QoS: Fix a free error in the dev_pm_qos_constraints_destroy() PM / QoS: Fix the return value of dev_pm_qos_update_request() PM / ACPI: Take device PM QoS flags into account PM / Domains: Check device PM QoS flags in pm_genpd_poweroff() PM / QoS: Make it possible to expose PM QoS device flags to user space PM / QoS: Introduce PM QoS device flags support PM / QoS: Prepare struct dev_pm_qos_request for more request types PM / QoS: Introduce request and constraint data types for PM QoS flags PM / QoS: Prepare device structure for adding more constraint types
Diffstat (limited to 'drivers/base/power')
-rw-r--r--drivers/base/power/domain.c11
-rw-r--r--drivers/base/power/power.h6
-rw-r--r--drivers/base/power/qos.c321
-rw-r--r--drivers/base/power/sysfs.c94
4 files changed, 355 insertions, 77 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 96b71b6536d6..acc3a8ded29d 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -470,10 +470,19 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
470 return -EBUSY; 470 return -EBUSY;
471 471
472 not_suspended = 0; 472 not_suspended = 0;
473 list_for_each_entry(pdd, &genpd->dev_list, list_node) 473 list_for_each_entry(pdd, &genpd->dev_list, list_node) {
474 enum pm_qos_flags_status stat;
475
476 stat = dev_pm_qos_flags(pdd->dev,
477 PM_QOS_FLAG_NO_POWER_OFF
478 | PM_QOS_FLAG_REMOTE_WAKEUP);
479 if (stat > PM_QOS_FLAGS_NONE)
480 return -EBUSY;
481
474 if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev) 482 if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev)
475 || pdd->dev->power.irq_safe)) 483 || pdd->dev->power.irq_safe))
476 not_suspended++; 484 not_suspended++;
485 }
477 486
478 if (not_suspended > genpd->in_progress) 487 if (not_suspended > genpd->in_progress)
479 return -EBUSY; 488 return -EBUSY;
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 0dbfdf4419af..b16686a0a5a2 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -93,8 +93,10 @@ extern void dpm_sysfs_remove(struct device *dev);
93extern void rpm_sysfs_remove(struct device *dev); 93extern void rpm_sysfs_remove(struct device *dev);
94extern int wakeup_sysfs_add(struct device *dev); 94extern int wakeup_sysfs_add(struct device *dev);
95extern void wakeup_sysfs_remove(struct device *dev); 95extern void wakeup_sysfs_remove(struct device *dev);
96extern int pm_qos_sysfs_add(struct device *dev); 96extern int pm_qos_sysfs_add_latency(struct device *dev);
97extern void pm_qos_sysfs_remove(struct device *dev); 97extern void pm_qos_sysfs_remove_latency(struct device *dev);
98extern int pm_qos_sysfs_add_flags(struct device *dev);
99extern void pm_qos_sysfs_remove_flags(struct device *dev);
98 100
99#else /* CONFIG_PM */ 101#else /* CONFIG_PM */
100 102
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c
index fbbd4ed2edf2..ff46387f5308 100644
--- a/drivers/base/power/qos.c
+++ b/drivers/base/power/qos.c
@@ -40,6 +40,7 @@
40#include <linux/device.h> 40#include <linux/device.h>
41#include <linux/mutex.h> 41#include <linux/mutex.h>
42#include <linux/export.h> 42#include <linux/export.h>
43#include <linux/pm_runtime.h>
43 44
44#include "power.h" 45#include "power.h"
45 46
@@ -48,6 +49,50 @@ static DEFINE_MUTEX(dev_pm_qos_mtx);
48static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers); 49static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
49 50
50/** 51/**
52 * __dev_pm_qos_flags - Check PM QoS flags for a given device.
53 * @dev: Device to check the PM QoS flags for.
54 * @mask: Flags to check against.
55 *
56 * This routine must be called with dev->power.lock held.
57 */
58enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask)
59{
60 struct dev_pm_qos *qos = dev->power.qos;
61 struct pm_qos_flags *pqf;
62 s32 val;
63
64 if (!qos)
65 return PM_QOS_FLAGS_UNDEFINED;
66
67 pqf = &qos->flags;
68 if (list_empty(&pqf->list))
69 return PM_QOS_FLAGS_UNDEFINED;
70
71 val = pqf->effective_flags & mask;
72 if (val)
73 return (val == mask) ? PM_QOS_FLAGS_ALL : PM_QOS_FLAGS_SOME;
74
75 return PM_QOS_FLAGS_NONE;
76}
77
78/**
79 * dev_pm_qos_flags - Check PM QoS flags for a given device (locked).
80 * @dev: Device to check the PM QoS flags for.
81 * @mask: Flags to check against.
82 */
83enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask)
84{
85 unsigned long irqflags;
86 enum pm_qos_flags_status ret;
87
88 spin_lock_irqsave(&dev->power.lock, irqflags);
89 ret = __dev_pm_qos_flags(dev, mask);
90 spin_unlock_irqrestore(&dev->power.lock, irqflags);
91
92 return ret;
93}
94
95/**
51 * __dev_pm_qos_read_value - Get PM QoS constraint for a given device. 96 * __dev_pm_qos_read_value - Get PM QoS constraint for a given device.
52 * @dev: Device to get the PM QoS constraint value for. 97 * @dev: Device to get the PM QoS constraint value for.
53 * 98 *
@@ -55,9 +100,7 @@ static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
55 */ 100 */
56s32 __dev_pm_qos_read_value(struct device *dev) 101s32 __dev_pm_qos_read_value(struct device *dev)
57{ 102{
58 struct pm_qos_constraints *c = dev->power.constraints; 103 return dev->power.qos ? pm_qos_read_value(&dev->power.qos->latency) : 0;
59
60 return c ? pm_qos_read_value(c) : 0;
61} 104}
62 105
63/** 106/**
@@ -76,30 +119,39 @@ s32 dev_pm_qos_read_value(struct device *dev)
76 return ret; 119 return ret;
77} 120}
78 121
79/* 122/**
80 * apply_constraint 123 * apply_constraint - Add/modify/remove device PM QoS request.
81 * @req: constraint request to apply 124 * @req: Constraint request to apply
82 * @action: action to perform add/update/remove, of type enum pm_qos_req_action 125 * @action: Action to perform (add/update/remove).
83 * @value: defines the qos request 126 * @value: Value to assign to the QoS request.
84 * 127 *
85 * Internal function to update the constraints list using the PM QoS core 128 * Internal function to update the constraints list using the PM QoS core
86 * code and if needed call the per-device and the global notification 129 * code and if needed call the per-device and the global notification
87 * callbacks 130 * callbacks
88 */ 131 */
89static int apply_constraint(struct dev_pm_qos_request *req, 132static int apply_constraint(struct dev_pm_qos_request *req,
90 enum pm_qos_req_action action, int value) 133 enum pm_qos_req_action action, s32 value)
91{ 134{
92 int ret, curr_value; 135 struct dev_pm_qos *qos = req->dev->power.qos;
93 136 int ret;
94 ret = pm_qos_update_target(req->dev->power.constraints,
95 &req->node, action, value);
96 137
97 if (ret) { 138 switch(req->type) {
98 /* Call the global callbacks if needed */ 139 case DEV_PM_QOS_LATENCY:
99 curr_value = pm_qos_read_value(req->dev->power.constraints); 140 ret = pm_qos_update_target(&qos->latency, &req->data.pnode,
100 blocking_notifier_call_chain(&dev_pm_notifiers, 141 action, value);
101 (unsigned long)curr_value, 142 if (ret) {
102 req); 143 value = pm_qos_read_value(&qos->latency);
144 blocking_notifier_call_chain(&dev_pm_notifiers,
145 (unsigned long)value,
146 req);
147 }
148 break;
149 case DEV_PM_QOS_FLAGS:
150 ret = pm_qos_update_flags(&qos->flags, &req->data.flr,
151 action, value);
152 break;
153 default:
154 ret = -EINVAL;
103 } 155 }
104 156
105 return ret; 157 return ret;
@@ -114,28 +166,32 @@ static int apply_constraint(struct dev_pm_qos_request *req,
114 */ 166 */
115static int dev_pm_qos_constraints_allocate(struct device *dev) 167static int dev_pm_qos_constraints_allocate(struct device *dev)
116{ 168{
169 struct dev_pm_qos *qos;
117 struct pm_qos_constraints *c; 170 struct pm_qos_constraints *c;
118 struct blocking_notifier_head *n; 171 struct blocking_notifier_head *n;
119 172
120 c = kzalloc(sizeof(*c), GFP_KERNEL); 173 qos = kzalloc(sizeof(*qos), GFP_KERNEL);
121 if (!c) 174 if (!qos)
122 return -ENOMEM; 175 return -ENOMEM;
123 176
124 n = kzalloc(sizeof(*n), GFP_KERNEL); 177 n = kzalloc(sizeof(*n), GFP_KERNEL);
125 if (!n) { 178 if (!n) {
126 kfree(c); 179 kfree(qos);
127 return -ENOMEM; 180 return -ENOMEM;
128 } 181 }
129 BLOCKING_INIT_NOTIFIER_HEAD(n); 182 BLOCKING_INIT_NOTIFIER_HEAD(n);
130 183
184 c = &qos->latency;
131 plist_head_init(&c->list); 185 plist_head_init(&c->list);
132 c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE; 186 c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
133 c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE; 187 c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
134 c->type = PM_QOS_MIN; 188 c->type = PM_QOS_MIN;
135 c->notifiers = n; 189 c->notifiers = n;
136 190
191 INIT_LIST_HEAD(&qos->flags.list);
192
137 spin_lock_irq(&dev->power.lock); 193 spin_lock_irq(&dev->power.lock);
138 dev->power.constraints = c; 194 dev->power.qos = qos;
139 spin_unlock_irq(&dev->power.lock); 195 spin_unlock_irq(&dev->power.lock);
140 196
141 return 0; 197 return 0;
@@ -151,7 +207,7 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
151void dev_pm_qos_constraints_init(struct device *dev) 207void dev_pm_qos_constraints_init(struct device *dev)
152{ 208{
153 mutex_lock(&dev_pm_qos_mtx); 209 mutex_lock(&dev_pm_qos_mtx);
154 dev->power.constraints = NULL; 210 dev->power.qos = NULL;
155 dev->power.power_state = PMSG_ON; 211 dev->power.power_state = PMSG_ON;
156 mutex_unlock(&dev_pm_qos_mtx); 212 mutex_unlock(&dev_pm_qos_mtx);
157} 213}
@@ -164,24 +220,28 @@ void dev_pm_qos_constraints_init(struct device *dev)
164 */ 220 */
165void dev_pm_qos_constraints_destroy(struct device *dev) 221void dev_pm_qos_constraints_destroy(struct device *dev)
166{ 222{
223 struct dev_pm_qos *qos;
167 struct dev_pm_qos_request *req, *tmp; 224 struct dev_pm_qos_request *req, *tmp;
168 struct pm_qos_constraints *c; 225 struct pm_qos_constraints *c;
226 struct pm_qos_flags *f;
169 227
170 /* 228 /*
171 * If the device's PM QoS resume latency limit has been exposed to user 229 * If the device's PM QoS resume latency limit or PM QoS flags have been
172 * space, it has to be hidden at this point. 230 * exposed to user space, they have to be hidden at this point.
173 */ 231 */
174 dev_pm_qos_hide_latency_limit(dev); 232 dev_pm_qos_hide_latency_limit(dev);
233 dev_pm_qos_hide_flags(dev);
175 234
176 mutex_lock(&dev_pm_qos_mtx); 235 mutex_lock(&dev_pm_qos_mtx);
177 236
178 dev->power.power_state = PMSG_INVALID; 237 dev->power.power_state = PMSG_INVALID;
179 c = dev->power.constraints; 238 qos = dev->power.qos;
180 if (!c) 239 if (!qos)
181 goto out; 240 goto out;
182 241
183 /* Flush the constraints list for the device */ 242 /* Flush the constraints lists for the device. */
184 plist_for_each_entry_safe(req, tmp, &c->list, node) { 243 c = &qos->latency;
244 plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
185 /* 245 /*
186 * Update constraints list and call the notification 246 * Update constraints list and call the notification
187 * callbacks if needed 247 * callbacks if needed
@@ -189,13 +249,18 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
189 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); 249 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
190 memset(req, 0, sizeof(*req)); 250 memset(req, 0, sizeof(*req));
191 } 251 }
252 f = &qos->flags;
253 list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) {
254 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
255 memset(req, 0, sizeof(*req));
256 }
192 257
193 spin_lock_irq(&dev->power.lock); 258 spin_lock_irq(&dev->power.lock);
194 dev->power.constraints = NULL; 259 dev->power.qos = NULL;
195 spin_unlock_irq(&dev->power.lock); 260 spin_unlock_irq(&dev->power.lock);
196 261
197 kfree(c->notifiers); 262 kfree(c->notifiers);
198 kfree(c); 263 kfree(qos);
199 264
200 out: 265 out:
201 mutex_unlock(&dev_pm_qos_mtx); 266 mutex_unlock(&dev_pm_qos_mtx);
@@ -205,6 +270,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
205 * dev_pm_qos_add_request - inserts new qos request into the list 270 * dev_pm_qos_add_request - inserts new qos request into the list
206 * @dev: target device for the constraint 271 * @dev: target device for the constraint
207 * @req: pointer to a preallocated handle 272 * @req: pointer to a preallocated handle
273 * @type: type of the request
208 * @value: defines the qos request 274 * @value: defines the qos request
209 * 275 *
210 * This function inserts a new entry in the device constraints list of 276 * This function inserts a new entry in the device constraints list of
@@ -218,9 +284,12 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
218 * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory 284 * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory
219 * to allocate for data structures, -ENODEV if the device has just been removed 285 * to allocate for data structures, -ENODEV if the device has just been removed
220 * from the system. 286 * from the system.
287 *
288 * Callers should ensure that the target device is not RPM_SUSPENDED before
289 * using this function for requests of type DEV_PM_QOS_FLAGS.
221 */ 290 */
222int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, 291int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
223 s32 value) 292 enum dev_pm_qos_req_type type, s32 value)
224{ 293{
225 int ret = 0; 294 int ret = 0;
226 295
@@ -235,7 +304,7 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
235 304
236 mutex_lock(&dev_pm_qos_mtx); 305 mutex_lock(&dev_pm_qos_mtx);
237 306
238 if (!dev->power.constraints) { 307 if (!dev->power.qos) {
239 if (dev->power.power_state.event == PM_EVENT_INVALID) { 308 if (dev->power.power_state.event == PM_EVENT_INVALID) {
240 /* The device has been removed from the system. */ 309 /* The device has been removed from the system. */
241 req->dev = NULL; 310 req->dev = NULL;
@@ -251,8 +320,10 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
251 } 320 }
252 } 321 }
253 322
254 if (!ret) 323 if (!ret) {
324 req->type = type;
255 ret = apply_constraint(req, PM_QOS_ADD_REQ, value); 325 ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
326 }
256 327
257 out: 328 out:
258 mutex_unlock(&dev_pm_qos_mtx); 329 mutex_unlock(&dev_pm_qos_mtx);
@@ -262,6 +333,37 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
262EXPORT_SYMBOL_GPL(dev_pm_qos_add_request); 333EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
263 334
264/** 335/**
336 * __dev_pm_qos_update_request - Modify an existing device PM QoS request.
337 * @req : PM QoS request to modify.
338 * @new_value: New value to request.
339 */
340static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req,
341 s32 new_value)
342{
343 s32 curr_value;
344 int ret = 0;
345
346 if (!req->dev->power.qos)
347 return -ENODEV;
348
349 switch(req->type) {
350 case DEV_PM_QOS_LATENCY:
351 curr_value = req->data.pnode.prio;
352 break;
353 case DEV_PM_QOS_FLAGS:
354 curr_value = req->data.flr.flags;
355 break;
356 default:
357 return -EINVAL;
358 }
359
360 if (curr_value != new_value)
361 ret = apply_constraint(req, PM_QOS_UPDATE_REQ, new_value);
362
363 return ret;
364}
365
366/**
265 * dev_pm_qos_update_request - modifies an existing qos request 367 * dev_pm_qos_update_request - modifies an existing qos request
266 * @req : handle to list element holding a dev_pm_qos request to use 368 * @req : handle to list element holding a dev_pm_qos request to use
267 * @new_value: defines the qos request 369 * @new_value: defines the qos request
@@ -275,11 +377,13 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
275 * 0 if the aggregated constraint value has not changed, 377 * 0 if the aggregated constraint value has not changed,
276 * -EINVAL in case of wrong parameters, -ENODEV if the device has been 378 * -EINVAL in case of wrong parameters, -ENODEV if the device has been
277 * removed from the system 379 * removed from the system
380 *
381 * Callers should ensure that the target device is not RPM_SUSPENDED before
382 * using this function for requests of type DEV_PM_QOS_FLAGS.
278 */ 383 */
279int dev_pm_qos_update_request(struct dev_pm_qos_request *req, 384int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value)
280 s32 new_value)
281{ 385{
282 int ret = 0; 386 int ret;
283 387
284 if (!req) /*guard against callers passing in null */ 388 if (!req) /*guard against callers passing in null */
285 return -EINVAL; 389 return -EINVAL;
@@ -289,17 +393,9 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
289 return -EINVAL; 393 return -EINVAL;
290 394
291 mutex_lock(&dev_pm_qos_mtx); 395 mutex_lock(&dev_pm_qos_mtx);
292 396 ret = __dev_pm_qos_update_request(req, new_value);
293 if (req->dev->power.constraints) {
294 if (new_value != req->node.prio)
295 ret = apply_constraint(req, PM_QOS_UPDATE_REQ,
296 new_value);
297 } else {
298 /* Return if the device has been removed */
299 ret = -ENODEV;
300 }
301
302 mutex_unlock(&dev_pm_qos_mtx); 397 mutex_unlock(&dev_pm_qos_mtx);
398
303 return ret; 399 return ret;
304} 400}
305EXPORT_SYMBOL_GPL(dev_pm_qos_update_request); 401EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
@@ -315,6 +411,9 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
315 * 0 if the aggregated constraint value has not changed, 411 * 0 if the aggregated constraint value has not changed,
316 * -EINVAL in case of wrong parameters, -ENODEV if the device has been 412 * -EINVAL in case of wrong parameters, -ENODEV if the device has been
317 * removed from the system 413 * removed from the system
414 *
415 * Callers should ensure that the target device is not RPM_SUSPENDED before
416 * using this function for requests of type DEV_PM_QOS_FLAGS.
318 */ 417 */
319int dev_pm_qos_remove_request(struct dev_pm_qos_request *req) 418int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
320{ 419{
@@ -329,7 +428,7 @@ int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
329 428
330 mutex_lock(&dev_pm_qos_mtx); 429 mutex_lock(&dev_pm_qos_mtx);
331 430
332 if (req->dev->power.constraints) { 431 if (req->dev->power.qos) {
333 ret = apply_constraint(req, PM_QOS_REMOVE_REQ, 432 ret = apply_constraint(req, PM_QOS_REMOVE_REQ,
334 PM_QOS_DEFAULT_VALUE); 433 PM_QOS_DEFAULT_VALUE);
335 memset(req, 0, sizeof(*req)); 434 memset(req, 0, sizeof(*req));
@@ -362,13 +461,13 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
362 461
363 mutex_lock(&dev_pm_qos_mtx); 462 mutex_lock(&dev_pm_qos_mtx);
364 463
365 if (!dev->power.constraints) 464 if (!dev->power.qos)
366 ret = dev->power.power_state.event != PM_EVENT_INVALID ? 465 ret = dev->power.power_state.event != PM_EVENT_INVALID ?
367 dev_pm_qos_constraints_allocate(dev) : -ENODEV; 466 dev_pm_qos_constraints_allocate(dev) : -ENODEV;
368 467
369 if (!ret) 468 if (!ret)
370 ret = blocking_notifier_chain_register( 469 ret = blocking_notifier_chain_register(
371 dev->power.constraints->notifiers, notifier); 470 dev->power.qos->latency.notifiers, notifier);
372 471
373 mutex_unlock(&dev_pm_qos_mtx); 472 mutex_unlock(&dev_pm_qos_mtx);
374 return ret; 473 return ret;
@@ -393,9 +492,9 @@ int dev_pm_qos_remove_notifier(struct device *dev,
393 mutex_lock(&dev_pm_qos_mtx); 492 mutex_lock(&dev_pm_qos_mtx);
394 493
395 /* Silently return if the constraints object is not present. */ 494 /* Silently return if the constraints object is not present. */
396 if (dev->power.constraints) 495 if (dev->power.qos)
397 retval = blocking_notifier_chain_unregister( 496 retval = blocking_notifier_chain_unregister(
398 dev->power.constraints->notifiers, 497 dev->power.qos->latency.notifiers,
399 notifier); 498 notifier);
400 499
401 mutex_unlock(&dev_pm_qos_mtx); 500 mutex_unlock(&dev_pm_qos_mtx);
@@ -449,7 +548,8 @@ int dev_pm_qos_add_ancestor_request(struct device *dev,
449 ancestor = ancestor->parent; 548 ancestor = ancestor->parent;
450 549
451 if (ancestor) 550 if (ancestor)
452 error = dev_pm_qos_add_request(ancestor, req, value); 551 error = dev_pm_qos_add_request(ancestor, req,
552 DEV_PM_QOS_LATENCY, value);
453 553
454 if (error < 0) 554 if (error < 0)
455 req->dev = NULL; 555 req->dev = NULL;
@@ -459,10 +559,19 @@ int dev_pm_qos_add_ancestor_request(struct device *dev,
459EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request); 559EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request);
460 560
461#ifdef CONFIG_PM_RUNTIME 561#ifdef CONFIG_PM_RUNTIME
462static void __dev_pm_qos_drop_user_request(struct device *dev) 562static void __dev_pm_qos_drop_user_request(struct device *dev,
563 enum dev_pm_qos_req_type type)
463{ 564{
464 dev_pm_qos_remove_request(dev->power.pq_req); 565 switch(type) {
465 dev->power.pq_req = NULL; 566 case DEV_PM_QOS_LATENCY:
567 dev_pm_qos_remove_request(dev->power.qos->latency_req);
568 dev->power.qos->latency_req = NULL;
569 break;
570 case DEV_PM_QOS_FLAGS:
571 dev_pm_qos_remove_request(dev->power.qos->flags_req);
572 dev->power.qos->flags_req = NULL;
573 break;
574 }
466} 575}
467 576
468/** 577/**
@@ -478,21 +587,21 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
478 if (!device_is_registered(dev) || value < 0) 587 if (!device_is_registered(dev) || value < 0)
479 return -EINVAL; 588 return -EINVAL;
480 589
481 if (dev->power.pq_req) 590 if (dev->power.qos && dev->power.qos->latency_req)
482 return -EEXIST; 591 return -EEXIST;
483 592
484 req = kzalloc(sizeof(*req), GFP_KERNEL); 593 req = kzalloc(sizeof(*req), GFP_KERNEL);
485 if (!req) 594 if (!req)
486 return -ENOMEM; 595 return -ENOMEM;
487 596
488 ret = dev_pm_qos_add_request(dev, req, value); 597 ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY, value);
489 if (ret < 0) 598 if (ret < 0)
490 return ret; 599 return ret;
491 600
492 dev->power.pq_req = req; 601 dev->power.qos->latency_req = req;
493 ret = pm_qos_sysfs_add(dev); 602 ret = pm_qos_sysfs_add_latency(dev);
494 if (ret) 603 if (ret)
495 __dev_pm_qos_drop_user_request(dev); 604 __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
496 605
497 return ret; 606 return ret;
498} 607}
@@ -504,10 +613,92 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit);
504 */ 613 */
505void dev_pm_qos_hide_latency_limit(struct device *dev) 614void dev_pm_qos_hide_latency_limit(struct device *dev)
506{ 615{
507 if (dev->power.pq_req) { 616 if (dev->power.qos && dev->power.qos->latency_req) {
508 pm_qos_sysfs_remove(dev); 617 pm_qos_sysfs_remove_latency(dev);
509 __dev_pm_qos_drop_user_request(dev); 618 __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
510 } 619 }
511} 620}
512EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit); 621EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit);
622
623/**
624 * dev_pm_qos_expose_flags - Expose PM QoS flags of a device to user space.
625 * @dev: Device whose PM QoS flags are to be exposed to user space.
626 * @val: Initial values of the flags.
627 */
628int dev_pm_qos_expose_flags(struct device *dev, s32 val)
629{
630 struct dev_pm_qos_request *req;
631 int ret;
632
633 if (!device_is_registered(dev))
634 return -EINVAL;
635
636 if (dev->power.qos && dev->power.qos->flags_req)
637 return -EEXIST;
638
639 req = kzalloc(sizeof(*req), GFP_KERNEL);
640 if (!req)
641 return -ENOMEM;
642
643 pm_runtime_get_sync(dev);
644 ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_FLAGS, val);
645 if (ret < 0)
646 goto fail;
647
648 dev->power.qos->flags_req = req;
649 ret = pm_qos_sysfs_add_flags(dev);
650 if (ret)
651 __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
652
653fail:
654 pm_runtime_put(dev);
655 return ret;
656}
657EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags);
658
659/**
660 * dev_pm_qos_hide_flags - Hide PM QoS flags of a device from user space.
661 * @dev: Device whose PM QoS flags are to be hidden from user space.
662 */
663void dev_pm_qos_hide_flags(struct device *dev)
664{
665 if (dev->power.qos && dev->power.qos->flags_req) {
666 pm_qos_sysfs_remove_flags(dev);
667 pm_runtime_get_sync(dev);
668 __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
669 pm_runtime_put(dev);
670 }
671}
672EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags);
673
674/**
675 * dev_pm_qos_update_flags - Update PM QoS flags request owned by user space.
676 * @dev: Device to update the PM QoS flags request for.
677 * @mask: Flags to set/clear.
678 * @set: Whether to set or clear the flags (true means set).
679 */
680int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set)
681{
682 s32 value;
683 int ret;
684
685 if (!dev->power.qos || !dev->power.qos->flags_req)
686 return -EINVAL;
687
688 pm_runtime_get_sync(dev);
689 mutex_lock(&dev_pm_qos_mtx);
690
691 value = dev_pm_qos_requested_flags(dev);
692 if (set)
693 value |= mask;
694 else
695 value &= ~mask;
696
697 ret = __dev_pm_qos_update_request(dev->power.qos->flags_req, value);
698
699 mutex_unlock(&dev_pm_qos_mtx);
700 pm_runtime_put(dev);
701
702 return ret;
703}
513#endif /* CONFIG_PM_RUNTIME */ 704#endif /* CONFIG_PM_RUNTIME */
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index b91dc6f1e914..50d16e3cb0a9 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -221,7 +221,7 @@ static DEVICE_ATTR(autosuspend_delay_ms, 0644, autosuspend_delay_ms_show,
221static ssize_t pm_qos_latency_show(struct device *dev, 221static ssize_t pm_qos_latency_show(struct device *dev,
222 struct device_attribute *attr, char *buf) 222 struct device_attribute *attr, char *buf)
223{ 223{
224 return sprintf(buf, "%d\n", dev->power.pq_req->node.prio); 224 return sprintf(buf, "%d\n", dev_pm_qos_requested_latency(dev));
225} 225}
226 226
227static ssize_t pm_qos_latency_store(struct device *dev, 227static ssize_t pm_qos_latency_store(struct device *dev,
@@ -237,12 +237,66 @@ static ssize_t pm_qos_latency_store(struct device *dev,
237 if (value < 0) 237 if (value < 0)
238 return -EINVAL; 238 return -EINVAL;
239 239
240 ret = dev_pm_qos_update_request(dev->power.pq_req, value); 240 ret = dev_pm_qos_update_request(dev->power.qos->latency_req, value);
241 return ret < 0 ? ret : n; 241 return ret < 0 ? ret : n;
242} 242}
243 243
244static DEVICE_ATTR(pm_qos_resume_latency_us, 0644, 244static DEVICE_ATTR(pm_qos_resume_latency_us, 0644,
245 pm_qos_latency_show, pm_qos_latency_store); 245 pm_qos_latency_show, pm_qos_latency_store);
246
247static ssize_t pm_qos_no_power_off_show(struct device *dev,
248 struct device_attribute *attr,
249 char *buf)
250{
251 return sprintf(buf, "%d\n", !!(dev_pm_qos_requested_flags(dev)
252 & PM_QOS_FLAG_NO_POWER_OFF));
253}
254
255static ssize_t pm_qos_no_power_off_store(struct device *dev,
256 struct device_attribute *attr,
257 const char *buf, size_t n)
258{
259 int ret;
260
261 if (kstrtoint(buf, 0, &ret))
262 return -EINVAL;
263
264 if (ret != 0 && ret != 1)
265 return -EINVAL;
266
267 ret = dev_pm_qos_update_flags(dev, PM_QOS_FLAG_NO_POWER_OFF, ret);
268 return ret < 0 ? ret : n;
269}
270
271static DEVICE_ATTR(pm_qos_no_power_off, 0644,
272 pm_qos_no_power_off_show, pm_qos_no_power_off_store);
273
274static ssize_t pm_qos_remote_wakeup_show(struct device *dev,
275 struct device_attribute *attr,
276 char *buf)
277{
278 return sprintf(buf, "%d\n", !!(dev_pm_qos_requested_flags(dev)
279 & PM_QOS_FLAG_REMOTE_WAKEUP));
280}
281
282static ssize_t pm_qos_remote_wakeup_store(struct device *dev,
283 struct device_attribute *attr,
284 const char *buf, size_t n)
285{
286 int ret;
287
288 if (kstrtoint(buf, 0, &ret))
289 return -EINVAL;
290
291 if (ret != 0 && ret != 1)
292 return -EINVAL;
293
294 ret = dev_pm_qos_update_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP, ret);
295 return ret < 0 ? ret : n;
296}
297
298static DEVICE_ATTR(pm_qos_remote_wakeup, 0644,
299 pm_qos_remote_wakeup_show, pm_qos_remote_wakeup_store);
246#endif /* CONFIG_PM_RUNTIME */ 300#endif /* CONFIG_PM_RUNTIME */
247 301
248#ifdef CONFIG_PM_SLEEP 302#ifdef CONFIG_PM_SLEEP
@@ -564,15 +618,27 @@ static struct attribute_group pm_runtime_attr_group = {
564 .attrs = runtime_attrs, 618 .attrs = runtime_attrs,
565}; 619};
566 620
567static struct attribute *pm_qos_attrs[] = { 621static struct attribute *pm_qos_latency_attrs[] = {
568#ifdef CONFIG_PM_RUNTIME 622#ifdef CONFIG_PM_RUNTIME
569 &dev_attr_pm_qos_resume_latency_us.attr, 623 &dev_attr_pm_qos_resume_latency_us.attr,
570#endif /* CONFIG_PM_RUNTIME */ 624#endif /* CONFIG_PM_RUNTIME */
571 NULL, 625 NULL,
572}; 626};
573static struct attribute_group pm_qos_attr_group = { 627static struct attribute_group pm_qos_latency_attr_group = {
574 .name = power_group_name, 628 .name = power_group_name,
575 .attrs = pm_qos_attrs, 629 .attrs = pm_qos_latency_attrs,
630};
631
632static struct attribute *pm_qos_flags_attrs[] = {
633#ifdef CONFIG_PM_RUNTIME
634 &dev_attr_pm_qos_no_power_off.attr,
635 &dev_attr_pm_qos_remote_wakeup.attr,
636#endif /* CONFIG_PM_RUNTIME */
637 NULL,
638};
639static struct attribute_group pm_qos_flags_attr_group = {
640 .name = power_group_name,
641 .attrs = pm_qos_flags_attrs,
576}; 642};
577 643
578int dpm_sysfs_add(struct device *dev) 644int dpm_sysfs_add(struct device *dev)
@@ -615,14 +681,24 @@ void wakeup_sysfs_remove(struct device *dev)
615 sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); 681 sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
616} 682}
617 683
618int pm_qos_sysfs_add(struct device *dev) 684int pm_qos_sysfs_add_latency(struct device *dev)
685{
686 return sysfs_merge_group(&dev->kobj, &pm_qos_latency_attr_group);
687}
688
689void pm_qos_sysfs_remove_latency(struct device *dev)
690{
691 sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_attr_group);
692}
693
694int pm_qos_sysfs_add_flags(struct device *dev)
619{ 695{
620 return sysfs_merge_group(&dev->kobj, &pm_qos_attr_group); 696 return sysfs_merge_group(&dev->kobj, &pm_qos_flags_attr_group);
621} 697}
622 698
623void pm_qos_sysfs_remove(struct device *dev) 699void pm_qos_sysfs_remove_flags(struct device *dev)
624{ 700{
625 sysfs_unmerge_group(&dev->kobj, &pm_qos_attr_group); 701 sysfs_unmerge_group(&dev->kobj, &pm_qos_flags_attr_group);
626} 702}
627 703
628void rpm_sysfs_remove(struct device *dev) 704void rpm_sysfs_remove(struct device *dev)