PM QoS: Add CPU frequency min/max as PM QoS params
[linux-2.6.git] / kernel / power / qos.c
1 /*
2  * This module exposes the interface to kernel space for specifying
3  * QoS dependencies.  It provides infrastructure for registration of:
4  *
5  * Dependents on a QoS value : register requests
6  * Watchers of QoS value : get notified when target QoS value changes
7  *
8  * This QoS design is best effort based.  Dependents register their QoS needs.
9  * Watchers register to keep track of the current QoS needs of the system.
10  *
11  * There are 3 basic classes of QoS parameter: latency, timeout, throughput
12  * each have defined units:
13  * latency: usec
14  * timeout: usec <-- currently not used.
15  * throughput: kbs (kilo byte / sec)
16  *
17  * There are lists of pm_qos_objects each one wrapping requests, notifiers
18  *
19  * User mode requests on a QOS parameter register themselves to the
20  * subsystem by opening the device node /dev/... and writing there request to
21  * the node.  As long as the process holds a file handle open to the node the
22  * client continues to be accounted for.  Upon file release the usermode
23  * request is removed and a new qos target is computed.  This way when the
24  * request 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.
26  *
27  * Mark Gross <mgross@linux.intel.com>
28  */
29
30 /*#define DEBUG*/
31
32 #include <linux/pm_qos.h>
33 #include <linux/sched.h>
34 #include <linux/spinlock.h>
35 #include <linux/slab.h>
36 #include <linux/time.h>
37 #include <linux/fs.h>
38 #include <linux/device.h>
39 #include <linux/miscdevice.h>
40 #include <linux/string.h>
41 #include <linux/platform_device.h>
42 #include <linux/init.h>
43 #include <linux/kernel.h>
44
45 #include <linux/uaccess.h>
46 #include <linux/export.h>
47
48 /*
49  * locking rule: all changes to constraints or notifiers lists
50  * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
51  * held, taken with _irqsave.  One lock to rule them all
52  */
53 struct pm_qos_object {
54         struct pm_qos_constraints *constraints;
55         struct miscdevice pm_qos_power_miscdev;
56         char *name;
57 };
58
59 static DEFINE_SPINLOCK(pm_qos_lock);
60
61 static struct pm_qos_object null_pm_qos;
62
63 static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier);
64 static struct pm_qos_constraints cpu_dma_constraints = {
65         .list = PLIST_HEAD_INIT(cpu_dma_constraints.list),
66         .target_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE,
67         .default_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE,
68         .type = PM_QOS_MIN,
69         .notifiers = &cpu_dma_lat_notifier,
70 };
71 static struct pm_qos_object cpu_dma_pm_qos = {
72         .constraints = &cpu_dma_constraints,
73         .name = "cpu_dma_latency",
74 };
75
76 static BLOCKING_NOTIFIER_HEAD(network_lat_notifier);
77 static struct pm_qos_constraints network_lat_constraints = {
78         .list = PLIST_HEAD_INIT(network_lat_constraints.list),
79         .target_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE,
80         .default_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE,
81         .type = PM_QOS_MIN,
82         .notifiers = &network_lat_notifier,
83 };
84 static struct pm_qos_object network_lat_pm_qos = {
85         .constraints = &network_lat_constraints,
86         .name = "network_latency",
87 };
88
89
90 static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier);
91 static struct pm_qos_constraints network_tput_constraints = {
92         .list = PLIST_HEAD_INIT(network_tput_constraints.list),
93         .target_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE,
94         .default_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE,
95         .type = PM_QOS_MAX,
96         .notifiers = &network_throughput_notifier,
97 };
98 static struct pm_qos_object network_throughput_pm_qos = {
99         .constraints = &network_tput_constraints,
100         .name = "network_throughput",
101 };
102
103 static BLOCKING_NOTIFIER_HEAD(max_online_cpus_notifier);
104 static struct pm_qos_constraints max_online_cpus_constraints = {
105         .list = PLIST_HEAD_INIT(max_online_cpus_constraints.list),
106         .target_value = PM_QOS_MAX_ONLINE_CPUS_DEFAULT_VALUE,
107         .default_value = PM_QOS_MAX_ONLINE_CPUS_DEFAULT_VALUE,
108         .type = PM_QOS_MIN,
109         .notifiers = &max_online_cpus_notifier,
110 };
111 static struct pm_qos_object max_online_cpus_pm_qos = {
112         .constraints = &max_online_cpus_constraints,
113         .name = "max_online_cpus",
114
115 };
116
117
118 static BLOCKING_NOTIFIER_HEAD(cpu_freq_min_notifier);
119 static struct pm_qos_constraints cpu_freq_min_constraints = {
120         .list = PLIST_HEAD_INIT(cpu_freq_min_constraints.list),
121         .target_value = PM_QOS_CPU_FREQ_MIN_DEFAULT_VALUE,
122         .default_value = PM_QOS_CPU_FREQ_MIN_DEFAULT_VALUE,
123         .type = PM_QOS_MAX,
124         .notifiers = &cpu_freq_min_notifier,
125 };
126 static struct pm_qos_object cpu_freq_min_pm_qos = {
127         .constraints = &cpu_freq_min_constraints,
128         .name = "cpu_freq_min",
129 };
130
131
132 static BLOCKING_NOTIFIER_HEAD(cpu_freq_max_notifier);
133 static struct pm_qos_constraints cpu_freq_max_constraints = {
134         .list = PLIST_HEAD_INIT(cpu_freq_max_constraints.list),
135         .target_value = PM_QOS_CPU_FREQ_MAX_DEFAULT_VALUE,
136         .default_value = PM_QOS_CPU_FREQ_MAX_DEFAULT_VALUE,
137         .type = PM_QOS_MIN,
138         .notifiers = &cpu_freq_max_notifier,
139 };
140 static struct pm_qos_object cpu_freq_max_pm_qos = {
141         .constraints = &cpu_freq_max_constraints,
142         .name = "cpu_freq_max",
143 };
144
145
146 static struct pm_qos_object *pm_qos_array[] = {
147         &null_pm_qos,
148         &cpu_dma_pm_qos,
149         &network_lat_pm_qos,
150         &network_throughput_pm_qos,
151         &max_online_cpus_pm_qos,
152         &cpu_freq_min_pm_qos,
153         &cpu_freq_max_pm_qos
154 };
155
156 static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
157                 size_t count, loff_t *f_pos);
158 static ssize_t pm_qos_power_read(struct file *filp, char __user *buf,
159                 size_t count, loff_t *f_pos);
160 static int pm_qos_power_open(struct inode *inode, struct file *filp);
161 static int pm_qos_power_release(struct inode *inode, struct file *filp);
162
163 static const struct file_operations pm_qos_power_fops = {
164         .write = pm_qos_power_write,
165         .read = pm_qos_power_read,
166         .open = pm_qos_power_open,
167         .release = pm_qos_power_release,
168         .llseek = noop_llseek,
169 };
170
171 /* unlocked internal variant */
172 static inline int pm_qos_get_value(struct pm_qos_constraints *c)
173 {
174         if (plist_head_empty(&c->list))
175                 return c->default_value;
176
177         switch (c->type) {
178         case PM_QOS_MIN:
179                 return plist_first(&c->list)->prio;
180
181         case PM_QOS_MAX:
182                 return plist_last(&c->list)->prio;
183
184         default:
185                 /* runtime check for not using enum */
186                 BUG();
187         }
188 }
189
190 s32 pm_qos_read_value(struct pm_qos_constraints *c)
191 {
192         return c->target_value;
193 }
194
195 static inline void pm_qos_set_value(struct pm_qos_constraints *c, s32 value)
196 {
197         c->target_value = value;
198 }
199
200 /**
201  * pm_qos_update_target - manages the constraints list and calls the notifiers
202  *  if needed
203  * @c: constraints data struct
204  * @node: request to add to the list, to update or to remove
205  * @action: action to take on the constraints list
206  * @value: value of the request to add or update
207  *
208  * This function returns 1 if the aggregated constraint value has changed, 0
209  *  otherwise.
210  */
211 int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node,
212                          enum pm_qos_req_action action, int value)
213 {
214         unsigned long flags;
215         int prev_value, curr_value, new_value;
216
217         spin_lock_irqsave(&pm_qos_lock, flags);
218         prev_value = pm_qos_get_value(c);
219         if (value == PM_QOS_DEFAULT_VALUE)
220                 new_value = c->default_value;
221         else
222                 new_value = value;
223
224         switch (action) {
225         case PM_QOS_REMOVE_REQ:
226                 plist_del(node, &c->list);
227                 break;
228         case PM_QOS_UPDATE_REQ:
229                 /*
230                  * to change the list, we atomically remove, reinit
231                  * with new value and add, then see if the extremal
232                  * changed
233                  */
234                 plist_del(node, &c->list);
235         case PM_QOS_ADD_REQ:
236                 plist_node_init(node, new_value);
237                 plist_add(node, &c->list);
238                 break;
239         default:
240                 /* no action */
241                 ;
242         }
243
244         curr_value = pm_qos_get_value(c);
245         pm_qos_set_value(c, curr_value);
246
247         spin_unlock_irqrestore(&pm_qos_lock, flags);
248
249         if (prev_value != curr_value) {
250                 blocking_notifier_call_chain(c->notifiers,
251                                              (unsigned long)curr_value,
252                                              NULL);
253                 return 1;
254         } else {
255                 return 0;
256         }
257 }
258
259 /**
260  * pm_qos_request - returns current system wide qos expectation
261  * @pm_qos_class: identification of which qos value is requested
262  *
263  * This function returns the current target value.
264  */
265 int pm_qos_request(int pm_qos_class)
266 {
267         return pm_qos_read_value(pm_qos_array[pm_qos_class]->constraints);
268 }
269 EXPORT_SYMBOL_GPL(pm_qos_request);
270
271 int pm_qos_request_active(struct pm_qos_request *req)
272 {
273         return req->pm_qos_class != 0;
274 }
275 EXPORT_SYMBOL_GPL(pm_qos_request_active);
276
277 /**
278  * pm_qos_add_request - inserts new qos request into the list
279  * @req: pointer to a preallocated handle
280  * @pm_qos_class: identifies which list of qos request to use
281  * @value: defines the qos request
282  *
283  * This function inserts a new entry in the pm_qos_class list of requested qos
284  * performance characteristics.  It recomputes the aggregate QoS expectations
285  * for the pm_qos_class of parameters and initializes the pm_qos_request
286  * handle.  Caller needs to save this handle for later use in updates and
287  * removal.
288  */
289
290 void pm_qos_add_request(struct pm_qos_request *req,
291                         int pm_qos_class, s32 value)
292 {
293         if (!req) /*guard against callers passing in null */
294                 return;
295
296         if (pm_qos_request_active(req)) {
297                 WARN(1, KERN_ERR "pm_qos_add_request() called for already added request\n");
298                 return;
299         }
300         req->pm_qos_class = pm_qos_class;
301         pm_qos_update_target(pm_qos_array[pm_qos_class]->constraints,
302                              &req->node, PM_QOS_ADD_REQ, value);
303 }
304 EXPORT_SYMBOL_GPL(pm_qos_add_request);
305
306 /**
307  * pm_qos_update_request - modifies an existing qos request
308  * @req : handle to list element holding a pm_qos request to use
309  * @value: defines the qos request
310  *
311  * Updates an existing qos request for the pm_qos_class of parameters along
312  * with updating the target pm_qos_class value.
313  *
314  * Attempts are made to make this code callable on hot code paths.
315  */
316 void pm_qos_update_request(struct pm_qos_request *req,
317                            s32 new_value)
318 {
319         if (!req) /*guard against callers passing in null */
320                 return;
321
322         if (!pm_qos_request_active(req)) {
323                 WARN(1, KERN_ERR "pm_qos_update_request() called for unknown object\n");
324                 return;
325         }
326
327         if (new_value != req->node.prio)
328                 pm_qos_update_target(
329                         pm_qos_array[req->pm_qos_class]->constraints,
330                         &req->node, PM_QOS_UPDATE_REQ, new_value);
331 }
332 EXPORT_SYMBOL_GPL(pm_qos_update_request);
333
334 /**
335  * pm_qos_remove_request - modifies an existing qos request
336  * @req: handle to request list element
337  *
338  * Will remove pm qos request from the list of constraints and
339  * recompute the current target value for the pm_qos_class.  Call this
340  * on slow code paths.
341  */
342 void pm_qos_remove_request(struct pm_qos_request *req)
343 {
344         if (!req) /*guard against callers passing in null */
345                 return;
346                 /* silent return to keep pcm code cleaner */
347
348         if (!pm_qos_request_active(req)) {
349                 WARN(1, KERN_ERR "pm_qos_remove_request() called for unknown object\n");
350                 return;
351         }
352
353         pm_qos_update_target(pm_qos_array[req->pm_qos_class]->constraints,
354                              &req->node, PM_QOS_REMOVE_REQ,
355                              PM_QOS_DEFAULT_VALUE);
356         memset(req, 0, sizeof(*req));
357 }
358 EXPORT_SYMBOL_GPL(pm_qos_remove_request);
359
360 /**
361  * pm_qos_add_notifier - sets notification entry for changes to target value
362  * @pm_qos_class: identifies which qos target changes should be notified.
363  * @notifier: notifier block managed by caller.
364  *
365  * will register the notifier into a notification chain that gets called
366  * upon changes to the pm_qos_class target value.
367  */
368 int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
369 {
370         int retval;
371
372         retval = blocking_notifier_chain_register(
373                         pm_qos_array[pm_qos_class]->constraints->notifiers,
374                         notifier);
375
376         return retval;
377 }
378 EXPORT_SYMBOL_GPL(pm_qos_add_notifier);
379
380 /**
381  * pm_qos_remove_notifier - deletes notification entry from chain.
382  * @pm_qos_class: identifies which qos target changes are notified.
383  * @notifier: notifier block to be removed.
384  *
385  * will remove the notifier from the notification chain that gets called
386  * upon changes to the pm_qos_class target value.
387  */
388 int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier)
389 {
390         int retval;
391
392         retval = blocking_notifier_chain_unregister(
393                         pm_qos_array[pm_qos_class]->constraints->notifiers,
394                         notifier);
395
396         return retval;
397 }
398 EXPORT_SYMBOL_GPL(pm_qos_remove_notifier);
399
400 /* User space interface to PM QoS classes via misc devices */
401 static int register_pm_qos_misc(struct pm_qos_object *qos)
402 {
403         qos->pm_qos_power_miscdev.minor = MISC_DYNAMIC_MINOR;
404         qos->pm_qos_power_miscdev.name = qos->name;
405         qos->pm_qos_power_miscdev.fops = &pm_qos_power_fops;
406
407         return misc_register(&qos->pm_qos_power_miscdev);
408 }
409
410 static int find_pm_qos_object_by_minor(int minor)
411 {
412         int pm_qos_class;
413
414         for (pm_qos_class = 0;
415                 pm_qos_class < PM_QOS_NUM_CLASSES; pm_qos_class++) {
416                 if (minor ==
417                         pm_qos_array[pm_qos_class]->pm_qos_power_miscdev.minor)
418                         return pm_qos_class;
419         }
420         return -1;
421 }
422
423 static int pm_qos_power_open(struct inode *inode, struct file *filp)
424 {
425         long pm_qos_class;
426
427         pm_qos_class = find_pm_qos_object_by_minor(iminor(inode));
428         if (pm_qos_class >= 0) {
429                 struct pm_qos_request *req = kzalloc(sizeof(*req), GFP_KERNEL);
430                 if (!req)
431                         return -ENOMEM;
432
433                 pm_qos_add_request(req, pm_qos_class, PM_QOS_DEFAULT_VALUE);
434                 filp->private_data = req;
435
436                 return 0;
437         }
438         return -EPERM;
439 }
440
441 static int pm_qos_power_release(struct inode *inode, struct file *filp)
442 {
443         struct pm_qos_request *req;
444
445         req = filp->private_data;
446         pm_qos_remove_request(req);
447         kfree(req);
448
449         return 0;
450 }
451
452
453 static ssize_t pm_qos_power_read(struct file *filp, char __user *buf,
454                 size_t count, loff_t *f_pos)
455 {
456         s32 value;
457         unsigned long flags;
458         struct pm_qos_request *req = filp->private_data;
459
460         if (!req)
461                 return -EINVAL;
462         if (!pm_qos_request_active(req))
463                 return -EINVAL;
464
465         spin_lock_irqsave(&pm_qos_lock, flags);
466         value = pm_qos_get_value(pm_qos_array[req->pm_qos_class]->constraints);
467         spin_unlock_irqrestore(&pm_qos_lock, flags);
468
469         return simple_read_from_buffer(buf, count, f_pos, &value, sizeof(s32));
470 }
471
472 static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
473                 size_t count, loff_t *f_pos)
474 {
475         s32 value;
476         struct pm_qos_request *req;
477
478         if (count == sizeof(s32)) {
479                 if (copy_from_user(&value, buf, sizeof(s32)))
480                         return -EFAULT;
481         } else if (count <= 11) { /* ASCII perhaps? */
482                 char ascii_value[11];
483                 unsigned long int ulval;
484                 int ret;
485
486                 if (copy_from_user(ascii_value, buf, count))
487                         return -EFAULT;
488
489                 if (count > 10) {
490                         if (ascii_value[10] == '\n')
491                                 ascii_value[10] = '\0';
492                         else
493                                 return -EINVAL;
494                 } else {
495                         ascii_value[count] = '\0';
496                 }
497                 ret = strict_strtoul(ascii_value, 16, &ulval);
498                 if (ret) {
499                         pr_debug("%s, 0x%lx, 0x%x\n", ascii_value, ulval, ret);
500                         return -EINVAL;
501                 }
502                 value = (s32)lower_32_bits(ulval);
503         } else {
504                 return -EINVAL;
505         }
506
507         req = filp->private_data;
508         pm_qos_update_request(req, value);
509
510         return count;
511 }
512
513
514 static int __init pm_qos_power_init(void)
515 {
516         int ret = 0;
517         int i;
518
519         BUILD_BUG_ON(ARRAY_SIZE(pm_qos_array) != PM_QOS_NUM_CLASSES);
520
521         for (i = 1; i < PM_QOS_NUM_CLASSES; i++) {
522                 ret = register_pm_qos_misc(pm_qos_array[i]);
523                 if (ret < 0) {
524                         printk(KERN_ERR "pm_qos_param: %s setup failed\n",
525                                pm_qos_array[i]->name);
526                         return ret;
527                 }
528         }
529
530         return ret;
531 }
532
533 late_initcall(pm_qos_power_init);