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
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
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
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
);
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;
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
)
71 spin_lock_irqsave(&dev
->power
.lock
, flags
);
72 ret
= __dev_pm_qos_read_value(dev
);
73 spin_unlock_irqrestore(&dev
->power
.lock
, flags
);
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
88 static int apply_constraint(struct dev_pm_qos_request
*req
,
89 enum pm_qos_req_action action
, int value
)
93 ret
= pm_qos_update_target(req
->dev
->power
.constraints
,
94 &req
->node
, action
, value
);
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
,
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
);
123 n
= kzalloc(sizeof(*n
), GFP_KERNEL
);
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
;
136 spin_lock_irq(&dev
->power
.lock
);
137 dev
->power
.constraints
= c
;
138 spin_unlock_irq(&dev
->power
.lock
);
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
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
;
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
);
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
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
215 int dev_pm_qos_add_request(struct device
*dev
, struct dev_pm_qos_request
*req
,
220 if (!dev
|| !req
) /*guard against callers passing in null */
223 if (WARN(dev_pm_qos_request_active(req
),
224 "%s() called for already added request\n", __func__
))
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. */
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
);
248 ret
= apply_constraint(req
, PM_QOS_ADD_REQ
, value
);
251 mutex_unlock(&dev_pm_qos_mtx
);
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
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
,
277 if (!req
) /*guard against callers passing in null */
280 if (WARN(!dev_pm_qos_request_active(req
),
281 "%s() called for unknown object\n", __func__
))
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
,
291 /* Return if the device has been removed */
295 mutex_unlock(&dev_pm_qos_mtx
);
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
)
316 if (!req
) /*guard against callers passing in null */
319 if (WARN(!dev_pm_qos_request_active(req
),
320 "%s() called for unknown object\n", __func__
))
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
));
330 /* Return if the device has been removed */
334 mutex_unlock(&dev_pm_qos_mtx
);
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
)
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
,
361 mutex_unlock(&dev_pm_qos_mtx
);
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
)
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
,
389 mutex_unlock(&dev_pm_qos_mtx
);
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
;
436 while (ancestor
&& !ancestor
->power
.ignore_children
)
437 ancestor
= ancestor
->parent
;
440 error
= dev_pm_qos_add_request(ancestor
, req
, value
);
447 EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request
);