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.c48
1 files changed, 23 insertions, 25 deletions
diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
index 0afe32be4c85..dfdec524d1b7 100644
--- a/kernel/pm_qos_params.c
+++ b/kernel/pm_qos_params.c
@@ -24,11 +24,12 @@
24 * requirement that the application has is cleaned up when closes the file 24 * requirement that the application has is cleaned up when closes the file
25 * pointer or exits the pm_qos_object will get an opportunity to clean up. 25 * pointer or exits the pm_qos_object will get an opportunity to clean up.
26 * 26 *
27 * mark gross mgross@linux.intel.com 27 * Mark Gross <mgross@linux.intel.com>
28 */ 28 */
29 29
30#include <linux/pm_qos_params.h> 30#include <linux/pm_qos_params.h>
31#include <linux/sched.h> 31#include <linux/sched.h>
32#include <linux/smp_lock.h>
32#include <linux/spinlock.h> 33#include <linux/spinlock.h>
33#include <linux/slab.h> 34#include <linux/slab.h>
34#include <linux/time.h> 35#include <linux/time.h>
@@ -42,7 +43,7 @@
42#include <linux/uaccess.h> 43#include <linux/uaccess.h>
43 44
44/* 45/*
45 * locking rule: all changes to target_value or requirements or notifiers lists 46 * locking rule: all changes to requirements or notifiers lists
46 * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock 47 * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
47 * held, taken with _irqsave. One lock to rule them all 48 * held, taken with _irqsave. One lock to rule them all
48 */ 49 */
@@ -65,7 +66,7 @@ struct pm_qos_object {
65 struct miscdevice pm_qos_power_miscdev; 66 struct miscdevice pm_qos_power_miscdev;
66 char *name; 67 char *name;
67 s32 default_value; 68 s32 default_value;
68 s32 target_value; 69 atomic_t target_value;
69 s32 (*comparitor)(s32, s32); 70 s32 (*comparitor)(s32, s32);
70}; 71};
71 72
@@ -76,7 +77,7 @@ static struct pm_qos_object cpu_dma_pm_qos = {
76 .notifiers = &cpu_dma_lat_notifier, 77 .notifiers = &cpu_dma_lat_notifier,
77 .name = "cpu_dma_latency", 78 .name = "cpu_dma_latency",
78 .default_value = 2000 * USEC_PER_SEC, 79 .default_value = 2000 * USEC_PER_SEC,
79 .target_value = 2000 * USEC_PER_SEC, 80 .target_value = ATOMIC_INIT(2000 * USEC_PER_SEC),
80 .comparitor = min_compare 81 .comparitor = min_compare
81}; 82};
82 83
@@ -86,7 +87,7 @@ static struct pm_qos_object network_lat_pm_qos = {
86 .notifiers = &network_lat_notifier, 87 .notifiers = &network_lat_notifier,
87 .name = "network_latency", 88 .name = "network_latency",
88 .default_value = 2000 * USEC_PER_SEC, 89 .default_value = 2000 * USEC_PER_SEC,
89 .target_value = 2000 * USEC_PER_SEC, 90 .target_value = ATOMIC_INIT(2000 * USEC_PER_SEC),
90 .comparitor = min_compare 91 .comparitor = min_compare
91}; 92};
92 93
@@ -98,7 +99,7 @@ static struct pm_qos_object network_throughput_pm_qos = {
98 .notifiers = &network_throughput_notifier, 99 .notifiers = &network_throughput_notifier,
99 .name = "network_throughput", 100 .name = "network_throughput",
100 .default_value = 0, 101 .default_value = 0,
101 .target_value = 0, 102 .target_value = ATOMIC_INIT(0),
102 .comparitor = max_compare 103 .comparitor = max_compare
103}; 104};
104 105
@@ -149,11 +150,11 @@ static void update_target(int target)
149 extreme_value = pm_qos_array[target]->comparitor( 150 extreme_value = pm_qos_array[target]->comparitor(
150 extreme_value, node->value); 151 extreme_value, node->value);
151 } 152 }
152 if (pm_qos_array[target]->target_value != extreme_value) { 153 if (atomic_read(&pm_qos_array[target]->target_value) != extreme_value) {
153 call_notifier = 1; 154 call_notifier = 1;
154 pm_qos_array[target]->target_value = extreme_value; 155 atomic_set(&pm_qos_array[target]->target_value, extreme_value);
155 pr_debug(KERN_ERR "new target for qos %d is %d\n", target, 156 pr_debug(KERN_ERR "new target for qos %d is %d\n", target,
156 pm_qos_array[target]->target_value); 157 atomic_read(&pm_qos_array[target]->target_value));
157 } 158 }
158 spin_unlock_irqrestore(&pm_qos_lock, flags); 159 spin_unlock_irqrestore(&pm_qos_lock, flags);
159 160
@@ -192,14 +193,7 @@ static int find_pm_qos_object_by_minor(int minor)
192 */ 193 */
193int pm_qos_requirement(int pm_qos_class) 194int pm_qos_requirement(int pm_qos_class)
194{ 195{
195 int ret_val; 196 return atomic_read(&pm_qos_array[pm_qos_class]->target_value);
196 unsigned long flags;
197
198 spin_lock_irqsave(&pm_qos_lock, flags);
199 ret_val = pm_qos_array[pm_qos_class]->target_value;
200 spin_unlock_irqrestore(&pm_qos_lock, flags);
201
202 return ret_val;
203} 197}
204EXPORT_SYMBOL_GPL(pm_qos_requirement); 198EXPORT_SYMBOL_GPL(pm_qos_requirement);
205 199
@@ -210,8 +204,8 @@ EXPORT_SYMBOL_GPL(pm_qos_requirement);
210 * @value: defines the qos request 204 * @value: defines the qos request
211 * 205 *
212 * This function inserts a new entry in the pm_qos_class list of requested qos 206 * This function inserts a new entry in the pm_qos_class list of requested qos
213 * performance charactoistics. It recomputes the agregate QoS expectations for 207 * performance characteristics. It recomputes the aggregate QoS expectations
214 * the pm_qos_class of parrameters. 208 * for the pm_qos_class of parameters.
215 */ 209 */
216int pm_qos_add_requirement(int pm_qos_class, char *name, s32 value) 210int pm_qos_add_requirement(int pm_qos_class, char *name, s32 value)
217{ 211{
@@ -249,10 +243,10 @@ EXPORT_SYMBOL_GPL(pm_qos_add_requirement);
249 * @name: identifies the request 243 * @name: identifies the request
250 * @value: defines the qos request 244 * @value: defines the qos request
251 * 245 *
252 * Updates an existing qos requierement for the pm_qos_class of parameters along 246 * Updates an existing qos requirement for the pm_qos_class of parameters along
253 * with updating the target pm_qos_class value. 247 * with updating the target pm_qos_class value.
254 * 248 *
255 * If the named request isn't in the lest then no change is made. 249 * If the named request isn't in the list then no change is made.
256 */ 250 */
257int pm_qos_update_requirement(int pm_qos_class, char *name, s32 new_value) 251int pm_qos_update_requirement(int pm_qos_class, char *name, s32 new_value)
258{ 252{
@@ -286,7 +280,7 @@ EXPORT_SYMBOL_GPL(pm_qos_update_requirement);
286 * @pm_qos_class: identifies which list of qos request to us 280 * @pm_qos_class: identifies which list of qos request to us
287 * @name: identifies the request 281 * @name: identifies the request
288 * 282 *
289 * Will remove named qos request from pm_qos_class list of parrameters and 283 * Will remove named qos request from pm_qos_class list of parameters and
290 * recompute the current target value for the pm_qos_class. 284 * recompute the current target value for the pm_qos_class.
291 */ 285 */
292void pm_qos_remove_requirement(int pm_qos_class, char *name) 286void pm_qos_remove_requirement(int pm_qos_class, char *name)
@@ -318,7 +312,7 @@ EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
318 * @notifier: notifier block managed by caller. 312 * @notifier: notifier block managed by caller.
319 * 313 *
320 * will register the notifier into a notification chain that gets called 314 * will register the notifier into a notification chain that gets called
321 * uppon changes to the pm_qos_class target value. 315 * upon changes to the pm_qos_class target value.
322 */ 316 */
323 int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier) 317 int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
324{ 318{
@@ -337,7 +331,7 @@ EXPORT_SYMBOL_GPL(pm_qos_add_notifier);
337 * @notifier: notifier block to be removed. 331 * @notifier: notifier block to be removed.
338 * 332 *
339 * will remove the notifier from the notification chain that gets called 333 * will remove the notifier from the notification chain that gets called
340 * uppon changes to the pm_qos_class target value. 334 * upon changes to the pm_qos_class target value.
341 */ 335 */
342int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier) 336int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier)
343{ 337{
@@ -358,15 +352,19 @@ static int pm_qos_power_open(struct inode *inode, struct file *filp)
358 int ret; 352 int ret;
359 long pm_qos_class; 353 long pm_qos_class;
360 354
355 lock_kernel();
361 pm_qos_class = find_pm_qos_object_by_minor(iminor(inode)); 356 pm_qos_class = find_pm_qos_object_by_minor(iminor(inode));
362 if (pm_qos_class >= 0) { 357 if (pm_qos_class >= 0) {
363 filp->private_data = (void *)pm_qos_class; 358 filp->private_data = (void *)pm_qos_class;
364 sprintf(name, "process_%d", current->pid); 359 sprintf(name, "process_%d", current->pid);
365 ret = pm_qos_add_requirement(pm_qos_class, name, 360 ret = pm_qos_add_requirement(pm_qos_class, name,
366 PM_QOS_DEFAULT_VALUE); 361 PM_QOS_DEFAULT_VALUE);
367 if (ret >= 0) 362 if (ret >= 0) {
363 unlock_kernel();
368 return 0; 364 return 0;
365 }
369 } 366 }
367 unlock_kernel();
370 368
371 return -EPERM; 369 return -EPERM;
372} 370}