Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/hch/vfs...
[pandora-kernel.git] / drivers / base / power / qos.c
1 /*
2  * Devices PM QoS constraints management
3  *
4  * Copyright (C) 2011 Texas Instruments, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  *
11  * This module exposes the interface to kernel space for specifying
12  * per-device PM QoS dependencies. It provides infrastructure for registration
13  * of:
14  *
15  * Dependents on a QoS value : register requests
16  * Watchers of QoS value : get notified when target QoS value changes
17  *
18  * This QoS design is best effort based. Dependents register their QoS needs.
19  * Watchers register to keep track of the current QoS needs of the system.
20  * Watchers can register different types of notification callbacks:
21  *  . a per-device notification callback using the dev_pm_qos_*_notifier API.
22  *    The notification chain data is stored in the per-device constraint
23  *    data struct.
24  *  . a system-wide notification callback using the dev_pm_qos_*_global_notifier
25  *    API. The notification chain data is stored in a static variable.
26  *
27  * Note about the per-device constraint data struct allocation:
28  * . The per-device constraints data struct ptr is tored into the device
29  *    dev_pm_info.
30  * . To minimize the data usage by the per-device constraints, the data struct
31  *   is only allocated at the first call to dev_pm_qos_add_request.
32  * . The data is later free'd when the device is removed from the system.
33  *  . A global mutex protects the constraints users from the data being
34  *     allocated and free'd.
35  */
36
37 #include <linux/pm_qos.h>
38 #include <linux/spinlock.h>
39 #include <linux/slab.h>
40 #include <linux/device.h>
41 #include <linux/mutex.h>
42
43
44 static DEFINE_MUTEX(dev_pm_qos_mtx);
45
46 static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
47
48 /**
49  * dev_pm_qos_read_value - Get PM QoS constraint for a given device.
50  * @dev: Device to get the PM QoS constraint value for.
51  */
52 s32 dev_pm_qos_read_value(struct device *dev)
53 {
54         struct pm_qos_constraints *c;
55         unsigned long flags;
56         s32 ret = 0;
57
58         spin_lock_irqsave(&dev->power.lock, flags);
59
60         c = dev->power.constraints;
61         if (c)
62                 ret = pm_qos_read_value(c);
63
64         spin_unlock_irqrestore(&dev->power.lock, flags);
65
66         return ret;
67 }
68
69 /*
70  * apply_constraint
71  * @req: constraint request to apply
72  * @action: action to perform add/update/remove, of type enum pm_qos_req_action
73  * @value: defines the qos request
74  *
75  * Internal function to update the constraints list using the PM QoS core
76  * code and if needed call the per-device and the global notification
77  * callbacks
78  */
79 static int apply_constraint(struct dev_pm_qos_request *req,
80                             enum pm_qos_req_action action, int value)
81 {
82         int ret, curr_value;
83
84         ret = pm_qos_update_target(req->dev->power.constraints,
85                                    &req->node, action, value);
86
87         if (ret) {
88                 /* Call the global callbacks if needed */
89                 curr_value = pm_qos_read_value(req->dev->power.constraints);
90                 blocking_notifier_call_chain(&dev_pm_notifiers,
91                                              (unsigned long)curr_value,
92                                              req);
93         }
94
95         return ret;
96 }
97
98 /*
99  * dev_pm_qos_constraints_allocate
100  * @dev: device to allocate data for
101  *
102  * Called at the first call to add_request, for constraint data allocation
103  * Must be called with the dev_pm_qos_mtx mutex held
104  */
105 static int dev_pm_qos_constraints_allocate(struct device *dev)
106 {
107         struct pm_qos_constraints *c;
108         struct blocking_notifier_head *n;
109
110         c = kzalloc(sizeof(*c), GFP_KERNEL);
111         if (!c)
112                 return -ENOMEM;
113
114         n = kzalloc(sizeof(*n), GFP_KERNEL);
115         if (!n) {
116                 kfree(c);
117                 return -ENOMEM;
118         }
119         BLOCKING_INIT_NOTIFIER_HEAD(n);
120
121         plist_head_init(&c->list);
122         c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
123         c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
124         c->type = PM_QOS_MIN;
125         c->notifiers = n;
126
127         spin_lock_irq(&dev->power.lock);
128         dev->power.constraints = c;
129         spin_unlock_irq(&dev->power.lock);
130
131         return 0;
132 }
133
134 /**
135  * dev_pm_qos_constraints_init - Initalize device's PM QoS constraints pointer.
136  * @dev: target device
137  *
138  * Called from the device PM subsystem during device insertion under
139  * device_pm_lock().
140  */
141 void dev_pm_qos_constraints_init(struct device *dev)
142 {
143         mutex_lock(&dev_pm_qos_mtx);
144         dev->power.constraints = NULL;
145         dev->power.power_state = PMSG_ON;
146         mutex_unlock(&dev_pm_qos_mtx);
147 }
148
149 /**
150  * dev_pm_qos_constraints_destroy
151  * @dev: target device
152  *
153  * Called from the device PM subsystem on device removal under device_pm_lock().
154  */
155 void dev_pm_qos_constraints_destroy(struct device *dev)
156 {
157         struct dev_pm_qos_request *req, *tmp;
158         struct pm_qos_constraints *c;
159
160         mutex_lock(&dev_pm_qos_mtx);
161
162         dev->power.power_state = PMSG_INVALID;
163         c = dev->power.constraints;
164         if (!c)
165                 goto out;
166
167         /* Flush the constraints list for the device */
168         plist_for_each_entry_safe(req, tmp, &c->list, node) {
169                 /*
170                  * Update constraints list and call the notification
171                  * callbacks if needed
172                  */
173                 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
174                 memset(req, 0, sizeof(*req));
175         }
176
177         spin_lock_irq(&dev->power.lock);
178         dev->power.constraints = NULL;
179         spin_unlock_irq(&dev->power.lock);
180
181         kfree(c->notifiers);
182         kfree(c);
183
184  out:
185         mutex_unlock(&dev_pm_qos_mtx);
186 }
187
188 /**
189  * dev_pm_qos_add_request - inserts new qos request into the list
190  * @dev: target device for the constraint
191  * @req: pointer to a preallocated handle
192  * @value: defines the qos request
193  *
194  * This function inserts a new entry in the device constraints list of
195  * requested qos performance characteristics. It recomputes the aggregate
196  * QoS expectations of parameters and initializes the dev_pm_qos_request
197  * handle.  Caller needs to save this handle for later use in updates and
198  * removal.
199  *
200  * Returns 1 if the aggregated constraint value has changed,
201  * 0 if the aggregated constraint value has not changed,
202  * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory
203  * to allocate for data structures, -ENODEV if the device has just been removed
204  * from the system.
205  */
206 int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
207                            s32 value)
208 {
209         int ret = 0;
210
211         if (!dev || !req) /*guard against callers passing in null */
212                 return -EINVAL;
213
214         if (dev_pm_qos_request_active(req)) {
215                 WARN(1, KERN_ERR "dev_pm_qos_add_request() called for already "
216                         "added request\n");
217                 return -EINVAL;
218         }
219
220         req->dev = dev;
221
222         mutex_lock(&dev_pm_qos_mtx);
223
224         if (!dev->power.constraints) {
225                 if (dev->power.power_state.event == PM_EVENT_INVALID) {
226                         /* The device has been removed from the system. */
227                         req->dev = NULL;
228                         ret = -ENODEV;
229                         goto out;
230                 } else {
231                         /*
232                          * Allocate the constraints data on the first call to
233                          * add_request, i.e. only if the data is not already
234                          * allocated and if the device has not been removed.
235                          */
236                         ret = dev_pm_qos_constraints_allocate(dev);
237                 }
238         }
239
240         if (!ret)
241                 ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
242
243  out:
244         mutex_unlock(&dev_pm_qos_mtx);
245
246         return ret;
247 }
248 EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
249
250 /**
251  * dev_pm_qos_update_request - modifies an existing qos request
252  * @req : handle to list element holding a dev_pm_qos request to use
253  * @new_value: defines the qos request
254  *
255  * Updates an existing dev PM qos request along with updating the
256  * target value.
257  *
258  * Attempts are made to make this code callable on hot code paths.
259  *
260  * Returns 1 if the aggregated constraint value has changed,
261  * 0 if the aggregated constraint value has not changed,
262  * -EINVAL in case of wrong parameters, -ENODEV if the device has been
263  * removed from the system
264  */
265 int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
266                               s32 new_value)
267 {
268         int ret = 0;
269
270         if (!req) /*guard against callers passing in null */
271                 return -EINVAL;
272
273         if (!dev_pm_qos_request_active(req)) {
274                 WARN(1, KERN_ERR "dev_pm_qos_update_request() called for "
275                         "unknown object\n");
276                 return -EINVAL;
277         }
278
279         mutex_lock(&dev_pm_qos_mtx);
280
281         if (req->dev->power.constraints) {
282                 if (new_value != req->node.prio)
283                         ret = apply_constraint(req, PM_QOS_UPDATE_REQ,
284                                                new_value);
285         } else {
286                 /* Return if the device has been removed */
287                 ret = -ENODEV;
288         }
289
290         mutex_unlock(&dev_pm_qos_mtx);
291         return ret;
292 }
293 EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
294
295 /**
296  * dev_pm_qos_remove_request - modifies an existing qos request
297  * @req: handle to request list element
298  *
299  * Will remove pm qos request from the list of constraints and
300  * recompute the current target value. Call this on slow code paths.
301  *
302  * Returns 1 if the aggregated constraint value has changed,
303  * 0 if the aggregated constraint value has not changed,
304  * -EINVAL in case of wrong parameters, -ENODEV if the device has been
305  * removed from the system
306  */
307 int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
308 {
309         int ret = 0;
310
311         if (!req) /*guard against callers passing in null */
312                 return -EINVAL;
313
314         if (!dev_pm_qos_request_active(req)) {
315                 WARN(1, KERN_ERR "dev_pm_qos_remove_request() called for "
316                         "unknown object\n");
317                 return -EINVAL;
318         }
319
320         mutex_lock(&dev_pm_qos_mtx);
321
322         if (req->dev->power.constraints) {
323                 ret = apply_constraint(req, PM_QOS_REMOVE_REQ,
324                                        PM_QOS_DEFAULT_VALUE);
325                 memset(req, 0, sizeof(*req));
326         } else {
327                 /* Return if the device has been removed */
328                 ret = -ENODEV;
329         }
330
331         mutex_unlock(&dev_pm_qos_mtx);
332         return ret;
333 }
334 EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request);
335
336 /**
337  * dev_pm_qos_add_notifier - sets notification entry for changes to target value
338  * of per-device PM QoS constraints
339  *
340  * @dev: target device for the constraint
341  * @notifier: notifier block managed by caller.
342  *
343  * Will register the notifier into a notification chain that gets called
344  * upon changes to the target value for the device.
345  */
346 int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
347 {
348         int retval = 0;
349
350         mutex_lock(&dev_pm_qos_mtx);
351
352         /* Silently return if the constraints object is not present. */
353         if (dev->power.constraints)
354                 retval = blocking_notifier_chain_register(
355                                 dev->power.constraints->notifiers,
356                                 notifier);
357
358         mutex_unlock(&dev_pm_qos_mtx);
359         return retval;
360 }
361 EXPORT_SYMBOL_GPL(dev_pm_qos_add_notifier);
362
363 /**
364  * dev_pm_qos_remove_notifier - deletes notification for changes to target value
365  * of per-device PM QoS constraints
366  *
367  * @dev: target device for the constraint
368  * @notifier: notifier block to be removed.
369  *
370  * Will remove the notifier from the notification chain that gets called
371  * upon changes to the target value.
372  */
373 int dev_pm_qos_remove_notifier(struct device *dev,
374                                struct notifier_block *notifier)
375 {
376         int retval = 0;
377
378         mutex_lock(&dev_pm_qos_mtx);
379
380         /* Silently return if the constraints object is not present. */
381         if (dev->power.constraints)
382                 retval = blocking_notifier_chain_unregister(
383                                 dev->power.constraints->notifiers,
384                                 notifier);
385
386         mutex_unlock(&dev_pm_qos_mtx);
387         return retval;
388 }
389 EXPORT_SYMBOL_GPL(dev_pm_qos_remove_notifier);
390
391 /**
392  * dev_pm_qos_add_global_notifier - sets notification entry for changes to
393  * target value of the PM QoS constraints for any device
394  *
395  * @notifier: notifier block managed by caller.
396  *
397  * Will register the notifier into a notification chain that gets called
398  * upon changes to the target value for any device.
399  */
400 int dev_pm_qos_add_global_notifier(struct notifier_block *notifier)
401 {
402         return blocking_notifier_chain_register(&dev_pm_notifiers, notifier);
403 }
404 EXPORT_SYMBOL_GPL(dev_pm_qos_add_global_notifier);
405
406 /**
407  * dev_pm_qos_remove_global_notifier - deletes notification for changes to
408  * target value of PM QoS constraints for any device
409  *
410  * @notifier: notifier block to be removed.
411  *
412  * Will remove the notifier from the notification chain that gets called
413  * upon changes to the target value for any device.
414  */
415 int dev_pm_qos_remove_global_notifier(struct notifier_block *notifier)
416 {
417         return blocking_notifier_chain_unregister(&dev_pm_notifiers, notifier);
418 }
419 EXPORT_SYMBOL_GPL(dev_pm_qos_remove_global_notifier);