aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/power/pm_qos_interface.txt2
-rw-r--r--drivers/base/power/qos.c124
-rw-r--r--drivers/mtd/nand/sh_flctl.c4
-rw-r--r--include/linux/pm_qos.h26
4 files changed, 127 insertions, 29 deletions
diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt
index 17e130a80347..79a2a58425ee 100644
--- a/Documentation/power/pm_qos_interface.txt
+++ b/Documentation/power/pm_qos_interface.txt
@@ -99,7 +99,7 @@ reading the aggregated value does not require any locking mechanism.
99 99
100From kernel mode the use of this interface is the following: 100From kernel mode the use of this interface is the following:
101 101
102int dev_pm_qos_add_request(device, handle, value): 102int dev_pm_qos_add_request(device, handle, type, value):
103Will insert an element into the list for that identified device with the 103Will insert an element into the list for that identified device with the
104target value. Upon change to this list the new target is recomputed and any 104target value. Upon change to this list the new target is recomputed and any
105registered notifiers are called only if the target value is now different. 105registered notifiers are called only if the target value is now different.
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c
index 96d27b821bb8..3c66f75d14b0 100644
--- a/drivers/base/power/qos.c
+++ b/drivers/base/power/qos.c
@@ -48,6 +48,50 @@ static DEFINE_MUTEX(dev_pm_qos_mtx);
48static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers); 48static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
49 49
50/** 50/**
51 * __dev_pm_qos_flags - Check PM QoS flags for a given device.
52 * @dev: Device to check the PM QoS flags for.
53 * @mask: Flags to check against.
54 *
55 * This routine must be called with dev->power.lock held.
56 */
57enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask)
58{
59 struct dev_pm_qos *qos = dev->power.qos;
60 struct pm_qos_flags *pqf;
61 s32 val;
62
63 if (!qos)
64 return PM_QOS_FLAGS_UNDEFINED;
65
66 pqf = &qos->flags;
67 if (list_empty(&pqf->list))
68 return PM_QOS_FLAGS_UNDEFINED;
69
70 val = pqf->effective_flags & mask;
71 if (val)
72 return (val == mask) ? PM_QOS_FLAGS_ALL : PM_QOS_FLAGS_SOME;
73
74 return PM_QOS_FLAGS_NONE;
75}
76
77/**
78 * dev_pm_qos_flags - Check PM QoS flags for a given device (locked).
79 * @dev: Device to check the PM QoS flags for.
80 * @mask: Flags to check against.
81 */
82enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask)
83{
84 unsigned long irqflags;
85 enum pm_qos_flags_status ret;
86
87 spin_lock_irqsave(&dev->power.lock, irqflags);
88 ret = __dev_pm_qos_flags(dev, mask);
89 spin_unlock_irqrestore(&dev->power.lock, irqflags);
90
91 return ret;
92}
93
94/**
51 * __dev_pm_qos_read_value - Get PM QoS constraint for a given device. 95 * __dev_pm_qos_read_value - Get PM QoS constraint for a given device.
52 * @dev: Device to get the PM QoS constraint value for. 96 * @dev: Device to get the PM QoS constraint value for.
53 * 97 *
@@ -74,30 +118,39 @@ s32 dev_pm_qos_read_value(struct device *dev)
74 return ret; 118 return ret;
75} 119}
76 120
77/* 121/**
78 * apply_constraint 122 * apply_constraint - Add/modify/remove device PM QoS request.
79 * @req: constraint request to apply 123 * @req: Constraint request to apply
80 * @action: action to perform add/update/remove, of type enum pm_qos_req_action 124 * @action: Action to perform (add/update/remove).
81 * @value: defines the qos request 125 * @value: Value to assign to the QoS request.
82 * 126 *
83 * Internal function to update the constraints list using the PM QoS core 127 * Internal function to update the constraints list using the PM QoS core
84 * code and if needed call the per-device and the global notification 128 * code and if needed call the per-device and the global notification
85 * callbacks 129 * callbacks
86 */ 130 */
87static int apply_constraint(struct dev_pm_qos_request *req, 131static int apply_constraint(struct dev_pm_qos_request *req,
88 enum pm_qos_req_action action, int value) 132 enum pm_qos_req_action action, s32 value)
89{ 133{
90 int ret, curr_value; 134 struct dev_pm_qos *qos = req->dev->power.qos;
91 135 int ret;
92 ret = pm_qos_update_target(&req->dev->power.qos->latency,
93 &req->data.pnode, action, value);
94 136
95 if (ret) { 137 switch(req->type) {
96 /* Call the global callbacks if needed */ 138 case DEV_PM_QOS_LATENCY:
97 curr_value = pm_qos_read_value(&req->dev->power.qos->latency); 139 ret = pm_qos_update_target(&qos->latency, &req->data.pnode,
98 blocking_notifier_call_chain(&dev_pm_notifiers, 140 action, value);
99 (unsigned long)curr_value, 141 if (ret) {
100 req); 142 value = pm_qos_read_value(&qos->latency);
143 blocking_notifier_call_chain(&dev_pm_notifiers,
144 (unsigned long)value,
145 req);
146 }
147 break;
148 case DEV_PM_QOS_FLAGS:
149 ret = pm_qos_update_flags(&qos->flags, &req->data.flr,
150 action, value);
151 break;
152 default:
153 ret = -EINVAL;
101 } 154 }
102 155
103 return ret; 156 return ret;
@@ -134,6 +187,8 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
134 c->type = PM_QOS_MIN; 187 c->type = PM_QOS_MIN;
135 c->notifiers = n; 188 c->notifiers = n;
136 189
190 INIT_LIST_HEAD(&qos->flags.list);
191
137 spin_lock_irq(&dev->power.lock); 192 spin_lock_irq(&dev->power.lock);
138 dev->power.qos = qos; 193 dev->power.qos = qos;
139 spin_unlock_irq(&dev->power.lock); 194 spin_unlock_irq(&dev->power.lock);
@@ -207,6 +262,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
207 * dev_pm_qos_add_request - inserts new qos request into the list 262 * dev_pm_qos_add_request - inserts new qos request into the list
208 * @dev: target device for the constraint 263 * @dev: target device for the constraint
209 * @req: pointer to a preallocated handle 264 * @req: pointer to a preallocated handle
265 * @type: type of the request
210 * @value: defines the qos request 266 * @value: defines the qos request
211 * 267 *
212 * This function inserts a new entry in the device constraints list of 268 * This function inserts a new entry in the device constraints list of
@@ -222,7 +278,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
222 * from the system. 278 * from the system.
223 */ 279 */
224int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, 280int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
225 s32 value) 281 enum dev_pm_qos_req_type type, s32 value)
226{ 282{
227 int ret = 0; 283 int ret = 0;
228 284
@@ -253,8 +309,10 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
253 } 309 }
254 } 310 }
255 311
256 if (!ret) 312 if (!ret) {
313 req->type = type;
257 ret = apply_constraint(req, PM_QOS_ADD_REQ, value); 314 ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
315 }
258 316
259 out: 317 out:
260 mutex_unlock(&dev_pm_qos_mtx); 318 mutex_unlock(&dev_pm_qos_mtx);
@@ -281,6 +339,7 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
281int dev_pm_qos_update_request(struct dev_pm_qos_request *req, 339int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
282 s32 new_value) 340 s32 new_value)
283{ 341{
342 s32 curr_value;
284 int ret = 0; 343 int ret = 0;
285 344
286 if (!req) /*guard against callers passing in null */ 345 if (!req) /*guard against callers passing in null */
@@ -292,15 +351,27 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
292 351
293 mutex_lock(&dev_pm_qos_mtx); 352 mutex_lock(&dev_pm_qos_mtx);
294 353
295 if (req->dev->power.qos) { 354 if (!req->dev->power.qos) {
296 if (new_value != req->data.pnode.prio)
297 ret = apply_constraint(req, PM_QOS_UPDATE_REQ,
298 new_value);
299 } else {
300 /* Return if the device has been removed */
301 ret = -ENODEV; 355 ret = -ENODEV;
356 goto out;
302 } 357 }
303 358
359 switch(req->type) {
360 case DEV_PM_QOS_LATENCY:
361 curr_value = req->data.pnode.prio;
362 break;
363 case DEV_PM_QOS_FLAGS:
364 curr_value = req->data.flr.flags;
365 break;
366 default:
367 ret = -EINVAL;
368 goto out;
369 }
370
371 if (curr_value != new_value)
372 ret = apply_constraint(req, PM_QOS_UPDATE_REQ, new_value);
373
374 out:
304 mutex_unlock(&dev_pm_qos_mtx); 375 mutex_unlock(&dev_pm_qos_mtx);
305 return ret; 376 return ret;
306} 377}
@@ -451,7 +522,8 @@ int dev_pm_qos_add_ancestor_request(struct device *dev,
451 ancestor = ancestor->parent; 522 ancestor = ancestor->parent;
452 523
453 if (ancestor) 524 if (ancestor)
454 error = dev_pm_qos_add_request(ancestor, req, value); 525 error = dev_pm_qos_add_request(ancestor, req,
526 DEV_PM_QOS_LATENCY, value);
455 527
456 if (error) 528 if (error)
457 req->dev = NULL; 529 req->dev = NULL;
@@ -487,7 +559,7 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
487 if (!req) 559 if (!req)
488 return -ENOMEM; 560 return -ENOMEM;
489 561
490 ret = dev_pm_qos_add_request(dev, req, value); 562 ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY, value);
491 if (ret < 0) 563 if (ret < 0)
492 return ret; 564 return ret;
493 565
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index 4fbfe96e37a1..f48ac5d80bbf 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -727,7 +727,9 @@ static void flctl_select_chip(struct mtd_info *mtd, int chipnr)
727 727
728 if (!flctl->qos_request) { 728 if (!flctl->qos_request) {
729 ret = dev_pm_qos_add_request(&flctl->pdev->dev, 729 ret = dev_pm_qos_add_request(&flctl->pdev->dev,
730 &flctl->pm_qos, 100); 730 &flctl->pm_qos,
731 DEV_PM_QOS_LATENCY,
732 100);
731 if (ret < 0) 733 if (ret < 0)
732 dev_err(&flctl->pdev->dev, 734 dev_err(&flctl->pdev->dev,
733 "PM QoS request failed: %d\n", ret); 735 "PM QoS request failed: %d\n", ret);
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h
index 3b9d14964d2b..3af7d8573c23 100644
--- a/include/linux/pm_qos.h
+++ b/include/linux/pm_qos.h
@@ -20,6 +20,13 @@ enum {
20 PM_QOS_NUM_CLASSES, 20 PM_QOS_NUM_CLASSES,
21}; 21};
22 22
23enum pm_qos_flags_status {
24 PM_QOS_FLAGS_UNDEFINED = -1,
25 PM_QOS_FLAGS_NONE,
26 PM_QOS_FLAGS_SOME,
27 PM_QOS_FLAGS_ALL,
28};
29
23#define PM_QOS_DEFAULT_VALUE -1 30#define PM_QOS_DEFAULT_VALUE -1
24 31
25#define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) 32#define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC)
@@ -38,9 +45,16 @@ struct pm_qos_flags_request {
38 s32 flags; /* Do not change to 64 bit */ 45 s32 flags; /* Do not change to 64 bit */
39}; 46};
40 47
48enum dev_pm_qos_req_type {
49 DEV_PM_QOS_LATENCY = 1,
50 DEV_PM_QOS_FLAGS,
51};
52
41struct dev_pm_qos_request { 53struct dev_pm_qos_request {
54 enum dev_pm_qos_req_type type;
42 union { 55 union {
43 struct plist_node pnode; 56 struct plist_node pnode;
57 struct pm_qos_flags_request flr;
44 } data; 58 } data;
45 struct device *dev; 59 struct device *dev;
46}; 60};
@@ -71,6 +85,7 @@ struct pm_qos_flags {
71 85
72struct dev_pm_qos { 86struct dev_pm_qos {
73 struct pm_qos_constraints latency; 87 struct pm_qos_constraints latency;
88 struct pm_qos_flags flags;
74}; 89};
75 90
76/* Action requested to pm_qos_update_target */ 91/* Action requested to pm_qos_update_target */
@@ -105,10 +120,12 @@ int pm_qos_request_active(struct pm_qos_request *req);
105s32 pm_qos_read_value(struct pm_qos_constraints *c); 120s32 pm_qos_read_value(struct pm_qos_constraints *c);
106 121
107#ifdef CONFIG_PM 122#ifdef CONFIG_PM
123enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask);
124enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask);
108s32 __dev_pm_qos_read_value(struct device *dev); 125s32 __dev_pm_qos_read_value(struct device *dev);
109s32 dev_pm_qos_read_value(struct device *dev); 126s32 dev_pm_qos_read_value(struct device *dev);
110int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, 127int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
111 s32 value); 128 enum dev_pm_qos_req_type type, s32 value);
112int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value); 129int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value);
113int dev_pm_qos_remove_request(struct dev_pm_qos_request *req); 130int dev_pm_qos_remove_request(struct dev_pm_qos_request *req);
114int dev_pm_qos_add_notifier(struct device *dev, 131int dev_pm_qos_add_notifier(struct device *dev,
@@ -122,12 +139,19 @@ void dev_pm_qos_constraints_destroy(struct device *dev);
122int dev_pm_qos_add_ancestor_request(struct device *dev, 139int dev_pm_qos_add_ancestor_request(struct device *dev,
123 struct dev_pm_qos_request *req, s32 value); 140 struct dev_pm_qos_request *req, s32 value);
124#else 141#else
142static inline enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev,
143 s32 mask)
144 { return PM_QOS_FLAGS_UNDEFINED; }
145static inline enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev,
146 s32 mask)
147 { return PM_QOS_FLAGS_UNDEFINED; }
125static inline s32 __dev_pm_qos_read_value(struct device *dev) 148static inline s32 __dev_pm_qos_read_value(struct device *dev)
126 { return 0; } 149 { return 0; }
127static inline s32 dev_pm_qos_read_value(struct device *dev) 150static inline s32 dev_pm_qos_read_value(struct device *dev)
128 { return 0; } 151 { return 0; }
129static inline int dev_pm_qos_add_request(struct device *dev, 152static inline int dev_pm_qos_add_request(struct device *dev,
130 struct dev_pm_qos_request *req, 153 struct dev_pm_qos_request *req,
154 enum dev_pm_qos_req_type type,
131 s32 value) 155 s32 value)
132 { return 0; } 156 { return 0; }
133static inline int dev_pm_qos_update_request(struct dev_pm_qos_request *req, 157static inline int dev_pm_qos_update_request(struct dev_pm_qos_request *req,