diff options
author | James Bottomley <James.Bottomley@suse.de> | 2010-07-05 16:53:06 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2010-07-18 20:00:34 -0400 |
commit | 82f682514a5df89ffb3890627eebf0897b7a84ec (patch) | |
tree | 27a3dba7a179102ac5bfdd5935679bd2abd3f70f /kernel | |
parent | 5f279845f9d684661563894d44729a0c706375b4 (diff) |
pm_qos: Get rid of the allocation in pm_qos_add_request()
All current users of pm_qos_add_request() have the ability to supply
the memory required by the pm_qos routines, so make them do this and
eliminate the kmalloc() with pm_qos_add_request(). This has the
double benefit of making the call never fail and allowing it to be
called from atomic context.
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Signed-off-by: mark gross <markgross@thegnar.org>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/pm_qos_params.c | 67 |
1 files changed, 40 insertions, 27 deletions
diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c index db8e51d7f39..996a4dec5f9 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 | */ |
52 | struct pm_qos_request_list { | ||
53 | struct plist_node list; | ||
54 | int pm_qos_class; | ||
55 | }; | ||
56 | |||
57 | enum pm_qos_type { | 51 | enum 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 | } |
211 | EXPORT_SYMBOL_GPL(pm_qos_request); | 205 | EXPORT_SYMBOL_GPL(pm_qos_request); |
212 | 206 | ||
207 | int pm_qos_request_active(struct pm_qos_request_list *req) | ||
208 | { | ||
209 | return req->pm_qos_class != 0; | ||
210 | } | ||
211 | EXPORT_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 | */ |
224 | struct pm_qos_request_list *pm_qos_add_request(int pm_qos_class, s32 value) | 224 | void 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 | } |
244 | EXPORT_SYMBOL_GPL(pm_qos_add_request); | 242 | EXPORT_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 | } |
297 | EXPORT_SYMBOL_GPL(pm_qos_remove_request); | 305 | EXPORT_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 | } |