percpu, x86: don't use PMD_SIZE as embedded atom_size on 32bit
[zen-stable.git] / drivers / base / power / qos.c
blobc5d358837461bf4d65716dd7a41d14d7341891d5
1 /*
2 * Devices PM QoS constraints management
4 * Copyright (C) 2011 Texas Instruments, Inc.
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.
11 * This module exposes the interface to kernel space for specifying
12 * per-device PM QoS dependencies. It provides infrastructure for registration
13 * of:
15 * Dependents on a QoS value : register requests
16 * Watchers of QoS value : get notified when target QoS value changes
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.
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.
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 #include <linux/export.h>
45 static DEFINE_MUTEX(dev_pm_qos_mtx);
47 static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
49 /**
50 * __dev_pm_qos_read_value - Get PM QoS constraint for a given device.
51 * @dev: Device to get the PM QoS constraint value for.
53 * This routine must be called with dev->power.lock held.
55 s32 __dev_pm_qos_read_value(struct device *dev)
57 struct pm_qos_constraints *c = dev->power.constraints;
59 return c ? pm_qos_read_value(c) : 0;
62 /**
63 * dev_pm_qos_read_value - Get PM QoS constraint for a given device (locked).
64 * @dev: Device to get the PM QoS constraint value for.
66 s32 dev_pm_qos_read_value(struct device *dev)
68 unsigned long flags;
69 s32 ret;
71 spin_lock_irqsave(&dev->power.lock, flags);
72 ret = __dev_pm_qos_read_value(dev);
73 spin_unlock_irqrestore(&dev->power.lock, flags);
75 return ret;
79 * apply_constraint
80 * @req: constraint request to apply
81 * @action: action to perform add/update/remove, of type enum pm_qos_req_action
82 * @value: defines the qos request
84 * Internal function to update the constraints list using the PM QoS core
85 * code and if needed call the per-device and the global notification
86 * callbacks
88 static int apply_constraint(struct dev_pm_qos_request *req,
89 enum pm_qos_req_action action, int value)
91 int ret, curr_value;
93 ret = pm_qos_update_target(req->dev->power.constraints,
94 &req->node, action, value);
96 if (ret) {
97 /* Call the global callbacks if needed */
98 curr_value = pm_qos_read_value(req->dev->power.constraints);
99 blocking_notifier_call_chain(&dev_pm_notifiers,
100 (unsigned long)curr_value,
101 req);
104 return ret;
108 * dev_pm_qos_constraints_allocate
109 * @dev: device to allocate data for
111 * Called at the first call to add_request, for constraint data allocation
112 * Must be called with the dev_pm_qos_mtx mutex held
114 static int dev_pm_qos_constraints_allocate(struct device *dev)
116 struct pm_qos_constraints *c;
117 struct blocking_notifier_head *n;
119 c = kzalloc(sizeof(*c), GFP_KERNEL);
120 if (!c)
121 return -ENOMEM;
123 n = kzalloc(sizeof(*n), GFP_KERNEL);
124 if (!n) {
125 kfree(c);
126 return -ENOMEM;
128 BLOCKING_INIT_NOTIFIER_HEAD(n);
130 plist_head_init(&c->list);
131 c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
132 c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
133 c->type = PM_QOS_MIN;
134 c->notifiers = n;
136 spin_lock_irq(&dev->power.lock);
137 dev->power.constraints = c;
138 spin_unlock_irq(&dev->power.lock);
140 return 0;
144 * dev_pm_qos_constraints_init - Initalize device's PM QoS constraints pointer.
145 * @dev: target device
147 * Called from the device PM subsystem during device insertion under
148 * device_pm_lock().
150 void dev_pm_qos_constraints_init(struct device *dev)
152 mutex_lock(&dev_pm_qos_mtx);
153 dev->power.constraints = NULL;
154 dev->power.power_state = PMSG_ON;
155 mutex_unlock(&dev_pm_qos_mtx);
159 * dev_pm_qos_constraints_destroy
160 * @dev: target device
162 * Called from the device PM subsystem on device removal under device_pm_lock().
164 void dev_pm_qos_constraints_destroy(struct device *dev)
166 struct dev_pm_qos_request *req, *tmp;
167 struct pm_qos_constraints *c;
169 mutex_lock(&dev_pm_qos_mtx);
171 dev->power.power_state = PMSG_INVALID;
172 c = dev->power.constraints;
173 if (!c)
174 goto out;
176 /* Flush the constraints list for the device */
177 plist_for_each_entry_safe(req, tmp, &c->list, node) {
179 * Update constraints list and call the notification
180 * callbacks if needed
182 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
183 memset(req, 0, sizeof(*req));
186 spin_lock_irq(&dev->power.lock);
187 dev->power.constraints = NULL;
188 spin_unlock_irq(&dev->power.lock);
190 kfree(c->notifiers);
191 kfree(c);
193 out:
194 mutex_unlock(&dev_pm_qos_mtx);
198 * dev_pm_qos_add_request - inserts new qos request into the list
199 * @dev: target device for the constraint
200 * @req: pointer to a preallocated handle
201 * @value: defines the qos request
203 * This function inserts a new entry in the device constraints list of
204 * requested qos performance characteristics. It recomputes the aggregate
205 * QoS expectations of parameters and initializes the dev_pm_qos_request
206 * handle. Caller needs to save this handle for later use in updates and
207 * removal.
209 * Returns 1 if the aggregated constraint value has changed,
210 * 0 if the aggregated constraint value has not changed,
211 * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory
212 * to allocate for data structures, -ENODEV if the device has just been removed
213 * from the system.
215 int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
216 s32 value)
218 int ret = 0;
220 if (!dev || !req) /*guard against callers passing in null */
221 return -EINVAL;
223 if (WARN(dev_pm_qos_request_active(req),
224 "%s() called for already added request\n", __func__))
225 return -EINVAL;
227 req->dev = dev;
229 mutex_lock(&dev_pm_qos_mtx);
231 if (!dev->power.constraints) {
232 if (dev->power.power_state.event == PM_EVENT_INVALID) {
233 /* The device has been removed from the system. */
234 req->dev = NULL;
235 ret = -ENODEV;
236 goto out;
237 } else {
239 * Allocate the constraints data on the first call to
240 * add_request, i.e. only if the data is not already
241 * allocated and if the device has not been removed.
243 ret = dev_pm_qos_constraints_allocate(dev);
247 if (!ret)
248 ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
250 out:
251 mutex_unlock(&dev_pm_qos_mtx);
253 return ret;
255 EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
258 * dev_pm_qos_update_request - modifies an existing qos request
259 * @req : handle to list element holding a dev_pm_qos request to use
260 * @new_value: defines the qos request
262 * Updates an existing dev PM qos request along with updating the
263 * target value.
265 * Attempts are made to make this code callable on hot code paths.
267 * Returns 1 if the aggregated constraint value has changed,
268 * 0 if the aggregated constraint value has not changed,
269 * -EINVAL in case of wrong parameters, -ENODEV if the device has been
270 * removed from the system
272 int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
273 s32 new_value)
275 int ret = 0;
277 if (!req) /*guard against callers passing in null */
278 return -EINVAL;
280 if (WARN(!dev_pm_qos_request_active(req),
281 "%s() called for unknown object\n", __func__))
282 return -EINVAL;
284 mutex_lock(&dev_pm_qos_mtx);
286 if (req->dev->power.constraints) {
287 if (new_value != req->node.prio)
288 ret = apply_constraint(req, PM_QOS_UPDATE_REQ,
289 new_value);
290 } else {
291 /* Return if the device has been removed */
292 ret = -ENODEV;
295 mutex_unlock(&dev_pm_qos_mtx);
296 return ret;
298 EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
301 * dev_pm_qos_remove_request - modifies an existing qos request
302 * @req: handle to request list element
304 * Will remove pm qos request from the list of constraints and
305 * recompute the current target value. Call this on slow code paths.
307 * Returns 1 if the aggregated constraint value has changed,
308 * 0 if the aggregated constraint value has not changed,
309 * -EINVAL in case of wrong parameters, -ENODEV if the device has been
310 * removed from the system
312 int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
314 int ret = 0;
316 if (!req) /*guard against callers passing in null */
317 return -EINVAL;
319 if (WARN(!dev_pm_qos_request_active(req),
320 "%s() called for unknown object\n", __func__))
321 return -EINVAL;
323 mutex_lock(&dev_pm_qos_mtx);
325 if (req->dev->power.constraints) {
326 ret = apply_constraint(req, PM_QOS_REMOVE_REQ,
327 PM_QOS_DEFAULT_VALUE);
328 memset(req, 0, sizeof(*req));
329 } else {
330 /* Return if the device has been removed */
331 ret = -ENODEV;
334 mutex_unlock(&dev_pm_qos_mtx);
335 return ret;
337 EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request);
340 * dev_pm_qos_add_notifier - sets notification entry for changes to target value
341 * of per-device PM QoS constraints
343 * @dev: target device for the constraint
344 * @notifier: notifier block managed by caller.
346 * Will register the notifier into a notification chain that gets called
347 * upon changes to the target value for the device.
349 int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
351 int retval = 0;
353 mutex_lock(&dev_pm_qos_mtx);
355 /* Silently return if the constraints object is not present. */
356 if (dev->power.constraints)
357 retval = blocking_notifier_chain_register(
358 dev->power.constraints->notifiers,
359 notifier);
361 mutex_unlock(&dev_pm_qos_mtx);
362 return retval;
364 EXPORT_SYMBOL_GPL(dev_pm_qos_add_notifier);
367 * dev_pm_qos_remove_notifier - deletes notification for changes to target value
368 * of per-device PM QoS constraints
370 * @dev: target device for the constraint
371 * @notifier: notifier block to be removed.
373 * Will remove the notifier from the notification chain that gets called
374 * upon changes to the target value.
376 int dev_pm_qos_remove_notifier(struct device *dev,
377 struct notifier_block *notifier)
379 int retval = 0;
381 mutex_lock(&dev_pm_qos_mtx);
383 /* Silently return if the constraints object is not present. */
384 if (dev->power.constraints)
385 retval = blocking_notifier_chain_unregister(
386 dev->power.constraints->notifiers,
387 notifier);
389 mutex_unlock(&dev_pm_qos_mtx);
390 return retval;
392 EXPORT_SYMBOL_GPL(dev_pm_qos_remove_notifier);
395 * dev_pm_qos_add_global_notifier - sets notification entry for changes to
396 * target value of the PM QoS constraints for any device
398 * @notifier: notifier block managed by caller.
400 * Will register the notifier into a notification chain that gets called
401 * upon changes to the target value for any device.
403 int dev_pm_qos_add_global_notifier(struct notifier_block *notifier)
405 return blocking_notifier_chain_register(&dev_pm_notifiers, notifier);
407 EXPORT_SYMBOL_GPL(dev_pm_qos_add_global_notifier);
410 * dev_pm_qos_remove_global_notifier - deletes notification for changes to
411 * target value of PM QoS constraints for any device
413 * @notifier: notifier block to be removed.
415 * Will remove the notifier from the notification chain that gets called
416 * upon changes to the target value for any device.
418 int dev_pm_qos_remove_global_notifier(struct notifier_block *notifier)
420 return blocking_notifier_chain_unregister(&dev_pm_notifiers, notifier);
422 EXPORT_SYMBOL_GPL(dev_pm_qos_remove_global_notifier);
425 * dev_pm_qos_add_ancestor_request - Add PM QoS request for device's ancestor.
426 * @dev: Device whose ancestor to add the request for.
427 * @req: Pointer to the preallocated handle.
428 * @value: Constraint latency value.
430 int dev_pm_qos_add_ancestor_request(struct device *dev,
431 struct dev_pm_qos_request *req, s32 value)
433 struct device *ancestor = dev->parent;
434 int error = -ENODEV;
436 while (ancestor && !ancestor->power.ignore_children)
437 ancestor = ancestor->parent;
439 if (ancestor)
440 error = dev_pm_qos_add_request(ancestor, req, value);
442 if (error)
443 req->dev = NULL;
445 return error;
447 EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request);