aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/pm_qos_params.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/pm_qos_params.c')
-rw-r--r--kernel/pm_qos_params.c67
1 files changed, 40 insertions, 27 deletions
diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
index db8e51d7f392..996a4dec5f96 100644
--- a/kernel/pm_qos_params.c
+++ b/kernel/pm_qos_params.c
@@ -30,7 +30,6 @@
30/*#define DEBUG*/ 30/*#define DEBUG*/
31 31
32#include <linux/pm_qos_params.h> 32#include <linux/pm_qos_params.h>
33#include <linux/plist.h>
34#include <linux/sched.h> 33#include <linux/sched.h>
35#include <linux/spinlock.h> 34#include <linux/spinlock.h>
36#include <linux/slab.h> 35#include <linux/slab.h>
@@ -49,11 +48,6 @@
49 * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock 48 * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
50 * held, taken with _irqsave. One lock to rule them all 49 * held, taken with _irqsave. One lock to rule them all
51 */ 50 */
52struct pm_qos_request_list {
53 struct plist_node list;
54 int pm_qos_class;
55};
56
57enum pm_qos_type { 51enum pm_qos_type {
58 PM_QOS_MAX, /* return the largest value */ 52 PM_QOS_MAX, /* return the largest value */
59 PM_QOS_MIN /* return the smallest value */ 53 PM_QOS_MIN /* return the smallest value */
@@ -210,6 +204,12 @@ int pm_qos_request(int pm_qos_class)
210} 204}
211EXPORT_SYMBOL_GPL(pm_qos_request); 205EXPORT_SYMBOL_GPL(pm_qos_request);
212 206
207int pm_qos_request_active(struct pm_qos_request_list *req)
208{
209 return req->pm_qos_class != 0;
210}
211EXPORT_SYMBOL_GPL(pm_qos_request_active);
212
213/** 213/**
214 * pm_qos_add_request - inserts new qos request into the list 214 * pm_qos_add_request - inserts new qos request into the list
215 * @pm_qos_class: identifies which list of qos request to us 215 * @pm_qos_class: identifies which list of qos request to us
@@ -221,25 +221,23 @@ EXPORT_SYMBOL_GPL(pm_qos_request);
221 * element as a handle for use in updating and removal. Call needs to save 221 * element as a handle for use in updating and removal. Call needs to save
222 * this handle for later use. 222 * this handle for later use.
223 */ 223 */
224struct pm_qos_request_list *pm_qos_add_request(int pm_qos_class, s32 value) 224void pm_qos_add_request(struct pm_qos_request_list *dep,
225 int pm_qos_class, s32 value)
225{ 226{
226 struct pm_qos_request_list *dep; 227 struct pm_qos_object *o = pm_qos_array[pm_qos_class];
227 228 int new_value;
228 dep = kzalloc(sizeof(struct pm_qos_request_list), GFP_KERNEL);
229 if (dep) {
230 struct pm_qos_object *o = pm_qos_array[pm_qos_class];
231 int new_value;
232
233 if (value == PM_QOS_DEFAULT_VALUE)
234 new_value = o->default_value;
235 else
236 new_value = value;
237 plist_node_init(&dep->list, new_value);
238 dep->pm_qos_class = pm_qos_class;
239 update_target(o, &dep->list, 0, PM_QOS_DEFAULT_VALUE);
240 }
241 229
242 return dep; 230 if (pm_qos_request_active(dep)) {
231 WARN(1, KERN_ERR "pm_qos_add_request() called for already added request\n");
232 return;
233 }
234 if (value == PM_QOS_DEFAULT_VALUE)
235 new_value = o->default_value;
236 else
237 new_value = value;
238 plist_node_init(&dep->list, new_value);
239 dep->pm_qos_class = pm_qos_class;
240 update_target(o, &dep->list, 0, PM_QOS_DEFAULT_VALUE);
243} 241}
244EXPORT_SYMBOL_GPL(pm_qos_add_request); 242EXPORT_SYMBOL_GPL(pm_qos_add_request);
245 243
@@ -262,6 +260,11 @@ void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
262 if (!pm_qos_req) /*guard against callers passing in null */ 260 if (!pm_qos_req) /*guard against callers passing in null */
263 return; 261 return;
264 262
263 if (!pm_qos_request_active(pm_qos_req)) {
264 WARN(1, KERN_ERR "pm_qos_update_request() called for unknown object\n");
265 return;
266 }
267
265 o = pm_qos_array[pm_qos_req->pm_qos_class]; 268 o = pm_qos_array[pm_qos_req->pm_qos_class];
266 269
267 if (new_value == PM_QOS_DEFAULT_VALUE) 270 if (new_value == PM_QOS_DEFAULT_VALUE)
@@ -290,9 +293,14 @@ void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req)
290 return; 293 return;
291 /* silent return to keep pcm code cleaner */ 294 /* silent return to keep pcm code cleaner */
292 295
296 if (!pm_qos_request_active(pm_qos_req)) {
297 WARN(1, KERN_ERR "pm_qos_remove_request() called for unknown object\n");
298 return;
299 }
300
293 o = pm_qos_array[pm_qos_req->pm_qos_class]; 301 o = pm_qos_array[pm_qos_req->pm_qos_class];
294 update_target(o, &pm_qos_req->list, 1, PM_QOS_DEFAULT_VALUE); 302 update_target(o, &pm_qos_req->list, 1, PM_QOS_DEFAULT_VALUE);
295 kfree(pm_qos_req); 303 memset(pm_qos_req, 0, sizeof(*pm_qos_req));
296} 304}
297EXPORT_SYMBOL_GPL(pm_qos_remove_request); 305EXPORT_SYMBOL_GPL(pm_qos_remove_request);
298 306
@@ -340,8 +348,12 @@ static int pm_qos_power_open(struct inode *inode, struct file *filp)
340 348
341 pm_qos_class = find_pm_qos_object_by_minor(iminor(inode)); 349 pm_qos_class = find_pm_qos_object_by_minor(iminor(inode));
342 if (pm_qos_class >= 0) { 350 if (pm_qos_class >= 0) {
343 filp->private_data = (void *) pm_qos_add_request(pm_qos_class, 351 struct pm_qos_request_list *req = kzalloc(GFP_KERNEL, sizeof(*req));
344 PM_QOS_DEFAULT_VALUE); 352 if (!req)
353 return -ENOMEM;
354
355 pm_qos_add_request(req, pm_qos_class, PM_QOS_DEFAULT_VALUE);
356 filp->private_data = req;
345 357
346 if (filp->private_data) 358 if (filp->private_data)
347 return 0; 359 return 0;
@@ -353,8 +365,9 @@ static int pm_qos_power_release(struct inode *inode, struct file *filp)
353{ 365{
354 struct pm_qos_request_list *req; 366 struct pm_qos_request_list *req;
355 367
356 req = (struct pm_qos_request_list *)filp->private_data; 368 req = filp->private_data;
357 pm_qos_remove_request(req); 369 pm_qos_remove_request(req);
370 kfree(req);
358 371
359 return 0; 372 return 0;
360} 373}