blob: c754e55f9dcbafb6bb403a761512ccb03fb2278d [file] [log] [blame]
Jean Pihet91ff4cb2011-08-25 15:35:41 +02001/*
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.
Jean Pihetb66213c2011-08-25 15:35:47 +020020 * 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.
Jean Pihet91ff4cb2011-08-25 15:35:41 +020026 *
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.
Jean Pihet91ff4cb2011-08-25 15:35:41 +020033 * . 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>
Paul Gortmaker1b6bc322011-05-27 07:12:15 -040042#include <linux/export.h>
Rafael J. Wysockie39473d2012-10-24 02:08:18 +020043#include <linux/pm_runtime.h>
Rafael J. Wysocki37530f22013-03-04 14:22:57 +010044#include <linux/err.h>
Sahara96d9d0b2013-06-21 11:12:30 +090045#include <trace/events/power.h>
Jean Pihet91ff4cb2011-08-25 15:35:41 +020046
Rafael J. Wysocki85dc0b82012-03-13 01:01:39 +010047#include "power.h"
Jean Pihet91ff4cb2011-08-25 15:35:41 +020048
49static DEFINE_MUTEX(dev_pm_qos_mtx);
Rafael J. Wysocki0f703062013-04-02 01:25:24 +020050static DEFINE_MUTEX(dev_pm_qos_sysfs_mtx);
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +020051
Jean Pihetb66213c2011-08-25 15:35:47 +020052static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
53
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +020054/**
Rafael J. Wysockiae0fb4b2012-10-23 01:09:12 +020055 * __dev_pm_qos_flags - Check PM QoS flags for a given device.
56 * @dev: Device to check the PM QoS flags for.
57 * @mask: Flags to check against.
58 *
59 * This routine must be called with dev->power.lock held.
60 */
61enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask)
62{
63 struct dev_pm_qos *qos = dev->power.qos;
64 struct pm_qos_flags *pqf;
65 s32 val;
66
Rafael J. Wysocki37530f22013-03-04 14:22:57 +010067 if (IS_ERR_OR_NULL(qos))
Rafael J. Wysockiae0fb4b2012-10-23 01:09:12 +020068 return PM_QOS_FLAGS_UNDEFINED;
69
70 pqf = &qos->flags;
71 if (list_empty(&pqf->list))
72 return PM_QOS_FLAGS_UNDEFINED;
73
74 val = pqf->effective_flags & mask;
75 if (val)
76 return (val == mask) ? PM_QOS_FLAGS_ALL : PM_QOS_FLAGS_SOME;
77
78 return PM_QOS_FLAGS_NONE;
79}
80
81/**
82 * dev_pm_qos_flags - Check PM QoS flags for a given device (locked).
83 * @dev: Device to check the PM QoS flags for.
84 * @mask: Flags to check against.
85 */
86enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask)
87{
88 unsigned long irqflags;
89 enum pm_qos_flags_status ret;
90
91 spin_lock_irqsave(&dev->power.lock, irqflags);
92 ret = __dev_pm_qos_flags(dev, mask);
93 spin_unlock_irqrestore(&dev->power.lock, irqflags);
94
95 return ret;
96}
Lan Tianyu6802771b2013-01-23 04:26:28 +080097EXPORT_SYMBOL_GPL(dev_pm_qos_flags);
Rafael J. Wysockiae0fb4b2012-10-23 01:09:12 +020098
99/**
Rafael J. Wysocki00dc9ad2011-12-01 00:01:31 +0100100 * __dev_pm_qos_read_value - Get PM QoS constraint for a given device.
101 * @dev: Device to get the PM QoS constraint value for.
102 *
103 * This routine must be called with dev->power.lock held.
104 */
105s32 __dev_pm_qos_read_value(struct device *dev)
106{
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100107 return IS_ERR_OR_NULL(dev->power.qos) ?
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100108 0 : pm_qos_read_value(&dev->power.qos->resume_latency);
Rafael J. Wysocki00dc9ad2011-12-01 00:01:31 +0100109}
110
111/**
112 * dev_pm_qos_read_value - Get PM QoS constraint for a given device (locked).
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200113 * @dev: Device to get the PM QoS constraint value for.
114 */
115s32 dev_pm_qos_read_value(struct device *dev)
116{
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200117 unsigned long flags;
Rafael J. Wysocki00dc9ad2011-12-01 00:01:31 +0100118 s32 ret;
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200119
120 spin_lock_irqsave(&dev->power.lock, flags);
Rafael J. Wysocki00dc9ad2011-12-01 00:01:31 +0100121 ret = __dev_pm_qos_read_value(dev);
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200122 spin_unlock_irqrestore(&dev->power.lock, flags);
123
124 return ret;
125}
126
Rafael J. Wysockiae0fb4b2012-10-23 01:09:12 +0200127/**
128 * apply_constraint - Add/modify/remove device PM QoS request.
129 * @req: Constraint request to apply
130 * @action: Action to perform (add/update/remove).
131 * @value: Value to assign to the QoS request.
Jean Pihetb66213c2011-08-25 15:35:47 +0200132 *
133 * Internal function to update the constraints list using the PM QoS core
134 * code and if needed call the per-device and the global notification
135 * callbacks
136 */
137static int apply_constraint(struct dev_pm_qos_request *req,
Rafael J. Wysockiae0fb4b2012-10-23 01:09:12 +0200138 enum pm_qos_req_action action, s32 value)
Jean Pihetb66213c2011-08-25 15:35:47 +0200139{
Rafael J. Wysockiae0fb4b2012-10-23 01:09:12 +0200140 struct dev_pm_qos *qos = req->dev->power.qos;
141 int ret;
Jean Pihetb66213c2011-08-25 15:35:47 +0200142
Rafael J. Wysockiae0fb4b2012-10-23 01:09:12 +0200143 switch(req->type) {
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100144 case DEV_PM_QOS_RESUME_LATENCY:
145 ret = pm_qos_update_target(&qos->resume_latency,
146 &req->data.pnode, action, value);
Rafael J. Wysockiae0fb4b2012-10-23 01:09:12 +0200147 if (ret) {
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100148 value = pm_qos_read_value(&qos->resume_latency);
Rafael J. Wysockiae0fb4b2012-10-23 01:09:12 +0200149 blocking_notifier_call_chain(&dev_pm_notifiers,
150 (unsigned long)value,
151 req);
152 }
153 break;
154 case DEV_PM_QOS_FLAGS:
155 ret = pm_qos_update_flags(&qos->flags, &req->data.flr,
156 action, value);
157 break;
158 default:
159 ret = -EINVAL;
Jean Pihetb66213c2011-08-25 15:35:47 +0200160 }
161
162 return ret;
163}
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200164
165/*
166 * dev_pm_qos_constraints_allocate
167 * @dev: device to allocate data for
168 *
169 * Called at the first call to add_request, for constraint data allocation
170 * Must be called with the dev_pm_qos_mtx mutex held
171 */
172static int dev_pm_qos_constraints_allocate(struct device *dev)
173{
Rafael J. Wysocki5f986c52012-10-23 01:07:27 +0200174 struct dev_pm_qos *qos;
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200175 struct pm_qos_constraints *c;
176 struct blocking_notifier_head *n;
177
Rafael J. Wysocki5f986c52012-10-23 01:07:27 +0200178 qos = kzalloc(sizeof(*qos), GFP_KERNEL);
179 if (!qos)
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200180 return -ENOMEM;
181
182 n = kzalloc(sizeof(*n), GFP_KERNEL);
183 if (!n) {
Rafael J. Wysocki5f986c52012-10-23 01:07:27 +0200184 kfree(qos);
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200185 return -ENOMEM;
186 }
187 BLOCKING_INIT_NOTIFIER_HEAD(n);
188
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100189 c = &qos->resume_latency;
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200190 plist_head_init(&c->list);
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100191 c->target_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE;
192 c->default_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE;
Rafael J. Wysocki327adae2014-02-11 00:35:29 +0100193 c->no_constraint_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE;
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200194 c->type = PM_QOS_MIN;
195 c->notifiers = n;
196
Rafael J. Wysockiae0fb4b2012-10-23 01:09:12 +0200197 INIT_LIST_HEAD(&qos->flags.list);
198
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200199 spin_lock_irq(&dev->power.lock);
Rafael J. Wysocki5f986c52012-10-23 01:07:27 +0200200 dev->power.qos = qos;
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200201 spin_unlock_irq(&dev->power.lock);
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200202
203 return 0;
204}
205
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100206static void __dev_pm_qos_hide_latency_limit(struct device *dev);
207static void __dev_pm_qos_hide_flags(struct device *dev);
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200208
209/**
210 * dev_pm_qos_constraints_destroy
211 * @dev: target device
212 *
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200213 * Called from the device PM subsystem on device removal under device_pm_lock().
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200214 */
215void dev_pm_qos_constraints_destroy(struct device *dev)
216{
Rafael J. Wysocki5f986c52012-10-23 01:07:27 +0200217 struct dev_pm_qos *qos;
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200218 struct dev_pm_qos_request *req, *tmp;
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200219 struct pm_qos_constraints *c;
Rafael J. Wysocki35546bd2012-11-24 10:10:51 +0100220 struct pm_qos_flags *f;
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200221
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200222 mutex_lock(&dev_pm_qos_sysfs_mtx);
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100223
Rafael J. Wysocki85dc0b82012-03-13 01:01:39 +0100224 /*
Rafael J. Wysocki35546bd2012-11-24 10:10:51 +0100225 * If the device's PM QoS resume latency limit or PM QoS flags have been
226 * exposed to user space, they have to be hidden at this point.
Rafael J. Wysocki85dc0b82012-03-13 01:01:39 +0100227 */
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100228 pm_qos_sysfs_remove_resume_latency(dev);
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200229 pm_qos_sysfs_remove_flags(dev);
230
231 mutex_lock(&dev_pm_qos_mtx);
232
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100233 __dev_pm_qos_hide_latency_limit(dev);
234 __dev_pm_qos_hide_flags(dev);
Rafael J. Wysocki85dc0b82012-03-13 01:01:39 +0100235
Rafael J. Wysocki5f986c52012-10-23 01:07:27 +0200236 qos = dev->power.qos;
237 if (!qos)
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200238 goto out;
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200239
Rafael J. Wysocki35546bd2012-11-24 10:10:51 +0100240 /* Flush the constraints lists for the device. */
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100241 c = &qos->resume_latency;
Rafael J. Wysocki021c8702012-10-23 01:09:00 +0200242 plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200243 /*
244 * Update constraints list and call the notification
245 * callbacks if needed
246 */
247 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
248 memset(req, 0, sizeof(*req));
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200249 }
Rafael J. Wysocki35546bd2012-11-24 10:10:51 +0100250 f = &qos->flags;
251 list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) {
252 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
253 memset(req, 0, sizeof(*req));
254 }
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200255
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200256 spin_lock_irq(&dev->power.lock);
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100257 dev->power.qos = ERR_PTR(-ENODEV);
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200258 spin_unlock_irq(&dev->power.lock);
259
260 kfree(c->notifiers);
Lan,Tianyu9eaee2c2012-11-01 22:45:30 +0100261 kfree(qos);
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200262
263 out:
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200264 mutex_unlock(&dev_pm_qos_mtx);
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200265
266 mutex_unlock(&dev_pm_qos_sysfs_mtx);
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200267}
268
269/**
270 * dev_pm_qos_add_request - inserts new qos request into the list
271 * @dev: target device for the constraint
272 * @req: pointer to a preallocated handle
Rafael J. Wysockiae0fb4b2012-10-23 01:09:12 +0200273 * @type: type of the request
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200274 * @value: defines the qos request
275 *
276 * This function inserts a new entry in the device constraints list of
277 * requested qos performance characteristics. It recomputes the aggregate
278 * QoS expectations of parameters and initializes the dev_pm_qos_request
279 * handle. Caller needs to save this handle for later use in updates and
280 * removal.
281 *
282 * Returns 1 if the aggregated constraint value has changed,
283 * 0 if the aggregated constraint value has not changed,
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200284 * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory
285 * to allocate for data structures, -ENODEV if the device has just been removed
286 * from the system.
Rafael J. Wysocki436ede82012-11-02 13:10:09 +0100287 *
288 * Callers should ensure that the target device is not RPM_SUSPENDED before
289 * using this function for requests of type DEV_PM_QOS_FLAGS.
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200290 */
291int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
Rafael J. Wysockiae0fb4b2012-10-23 01:09:12 +0200292 enum dev_pm_qos_req_type type, s32 value)
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200293{
294 int ret = 0;
295
296 if (!dev || !req) /*guard against callers passing in null */
297 return -EINVAL;
298
Guennadi Liakhovetskiaf4c7202011-11-10 00:44:18 +0100299 if (WARN(dev_pm_qos_request_active(req),
300 "%s() called for already added request\n", __func__))
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200301 return -EINVAL;
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200302
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200303 mutex_lock(&dev_pm_qos_mtx);
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200304
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100305 if (IS_ERR(dev->power.qos))
306 ret = -ENODEV;
307 else if (!dev->power.qos)
308 ret = dev_pm_qos_constraints_allocate(dev);
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200309
Sahara96d9d0b2013-06-21 11:12:30 +0900310 trace_dev_pm_qos_add_request(dev_name(dev), type, value);
Rafael J. Wysockiae0fb4b2012-10-23 01:09:12 +0200311 if (!ret) {
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100312 req->dev = dev;
Rafael J. Wysockiae0fb4b2012-10-23 01:09:12 +0200313 req->type = type;
Jean Pihetb66213c2011-08-25 15:35:47 +0200314 ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
Rafael J. Wysockiae0fb4b2012-10-23 01:09:12 +0200315 }
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200316
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200317 mutex_unlock(&dev_pm_qos_mtx);
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200318
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200319 return ret;
320}
321EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
322
323/**
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200324 * __dev_pm_qos_update_request - Modify an existing device PM QoS request.
325 * @req : PM QoS request to modify.
326 * @new_value: New value to request.
327 */
328static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req,
329 s32 new_value)
330{
331 s32 curr_value;
332 int ret = 0;
333
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100334 if (!req) /*guard against callers passing in null */
335 return -EINVAL;
336
337 if (WARN(!dev_pm_qos_request_active(req),
338 "%s() called for unknown object\n", __func__))
339 return -EINVAL;
340
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100341 if (IS_ERR_OR_NULL(req->dev->power.qos))
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200342 return -ENODEV;
343
344 switch(req->type) {
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100345 case DEV_PM_QOS_RESUME_LATENCY:
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200346 curr_value = req->data.pnode.prio;
347 break;
348 case DEV_PM_QOS_FLAGS:
349 curr_value = req->data.flr.flags;
350 break;
351 default:
352 return -EINVAL;
353 }
354
Sahara96d9d0b2013-06-21 11:12:30 +0900355 trace_dev_pm_qos_update_request(dev_name(req->dev), req->type,
356 new_value);
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200357 if (curr_value != new_value)
358 ret = apply_constraint(req, PM_QOS_UPDATE_REQ, new_value);
359
360 return ret;
361}
362
363/**
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200364 * dev_pm_qos_update_request - modifies an existing qos request
365 * @req : handle to list element holding a dev_pm_qos request to use
366 * @new_value: defines the qos request
367 *
368 * Updates an existing dev PM qos request along with updating the
369 * target value.
370 *
371 * Attempts are made to make this code callable on hot code paths.
372 *
373 * Returns 1 if the aggregated constraint value has changed,
374 * 0 if the aggregated constraint value has not changed,
375 * -EINVAL in case of wrong parameters, -ENODEV if the device has been
376 * removed from the system
Rafael J. Wysocki436ede82012-11-02 13:10:09 +0100377 *
378 * Callers should ensure that the target device is not RPM_SUSPENDED before
379 * using this function for requests of type DEV_PM_QOS_FLAGS.
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200380 */
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200381int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value)
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200382{
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200383 int ret;
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200384
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100385 mutex_lock(&dev_pm_qos_mtx);
386 ret = __dev_pm_qos_update_request(req, new_value);
387 mutex_unlock(&dev_pm_qos_mtx);
388 return ret;
389}
390EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
391
392static int __dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
393{
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100394 int ret;
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100395
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200396 if (!req) /*guard against callers passing in null */
397 return -EINVAL;
398
Guennadi Liakhovetskiaf4c7202011-11-10 00:44:18 +0100399 if (WARN(!dev_pm_qos_request_active(req),
400 "%s() called for unknown object\n", __func__))
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200401 return -EINVAL;
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200402
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100403 if (IS_ERR_OR_NULL(req->dev->power.qos))
404 return -ENODEV;
405
Sahara96d9d0b2013-06-21 11:12:30 +0900406 trace_dev_pm_qos_remove_request(dev_name(req->dev), req->type,
407 PM_QOS_DEFAULT_VALUE);
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100408 ret = apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
409 memset(req, 0, sizeof(*req));
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200410 return ret;
411}
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200412
413/**
414 * dev_pm_qos_remove_request - modifies an existing qos request
415 * @req: handle to request list element
416 *
417 * Will remove pm qos request from the list of constraints and
418 * recompute the current target value. Call this on slow code paths.
419 *
420 * Returns 1 if the aggregated constraint value has changed,
421 * 0 if the aggregated constraint value has not changed,
422 * -EINVAL in case of wrong parameters, -ENODEV if the device has been
423 * removed from the system
Rafael J. Wysocki436ede82012-11-02 13:10:09 +0100424 *
425 * Callers should ensure that the target device is not RPM_SUSPENDED before
426 * using this function for requests of type DEV_PM_QOS_FLAGS.
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200427 */
428int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
429{
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100430 int ret;
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200431
432 mutex_lock(&dev_pm_qos_mtx);
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100433 ret = __dev_pm_qos_remove_request(req);
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200434 mutex_unlock(&dev_pm_qos_mtx);
435 return ret;
436}
437EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request);
438
439/**
440 * dev_pm_qos_add_notifier - sets notification entry for changes to target value
441 * of per-device PM QoS constraints
442 *
443 * @dev: target device for the constraint
444 * @notifier: notifier block managed by caller.
445 *
446 * Will register the notifier into a notification chain that gets called
447 * upon changes to the target value for the device.
Rafael J. Wysocki23e0fc52012-04-29 22:54:47 +0200448 *
449 * If the device's constraints object doesn't exist when this routine is called,
450 * it will be created (or error code will be returned if that fails).
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200451 */
452int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
453{
Rafael J. Wysocki23e0fc52012-04-29 22:54:47 +0200454 int ret = 0;
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200455
456 mutex_lock(&dev_pm_qos_mtx);
457
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100458 if (IS_ERR(dev->power.qos))
459 ret = -ENODEV;
460 else if (!dev->power.qos)
461 ret = dev_pm_qos_constraints_allocate(dev);
Rafael J. Wysocki23e0fc52012-04-29 22:54:47 +0200462
463 if (!ret)
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100464 ret = blocking_notifier_chain_register(dev->power.qos->resume_latency.notifiers,
465 notifier);
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200466
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200467 mutex_unlock(&dev_pm_qos_mtx);
Rafael J. Wysocki23e0fc52012-04-29 22:54:47 +0200468 return ret;
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200469}
470EXPORT_SYMBOL_GPL(dev_pm_qos_add_notifier);
471
472/**
473 * dev_pm_qos_remove_notifier - deletes notification for changes to target value
474 * of per-device PM QoS constraints
475 *
476 * @dev: target device for the constraint
477 * @notifier: notifier block to be removed.
478 *
479 * Will remove the notifier from the notification chain that gets called
480 * upon changes to the target value.
481 */
482int dev_pm_qos_remove_notifier(struct device *dev,
483 struct notifier_block *notifier)
484{
485 int retval = 0;
486
487 mutex_lock(&dev_pm_qos_mtx);
488
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200489 /* Silently return if the constraints object is not present. */
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100490 if (!IS_ERR_OR_NULL(dev->power.qos))
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100491 retval = blocking_notifier_chain_unregister(dev->power.qos->resume_latency.notifiers,
492 notifier);
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200493
Jean Pihet91ff4cb2011-08-25 15:35:41 +0200494 mutex_unlock(&dev_pm_qos_mtx);
495 return retval;
496}
497EXPORT_SYMBOL_GPL(dev_pm_qos_remove_notifier);
Jean Pihetb66213c2011-08-25 15:35:47 +0200498
499/**
500 * dev_pm_qos_add_global_notifier - sets notification entry for changes to
501 * target value of the PM QoS constraints for any device
502 *
503 * @notifier: notifier block managed by caller.
504 *
505 * Will register the notifier into a notification chain that gets called
506 * upon changes to the target value for any device.
507 */
508int dev_pm_qos_add_global_notifier(struct notifier_block *notifier)
509{
510 return blocking_notifier_chain_register(&dev_pm_notifiers, notifier);
511}
512EXPORT_SYMBOL_GPL(dev_pm_qos_add_global_notifier);
513
514/**
515 * dev_pm_qos_remove_global_notifier - deletes notification for changes to
516 * target value of PM QoS constraints for any device
517 *
518 * @notifier: notifier block to be removed.
519 *
520 * Will remove the notifier from the notification chain that gets called
521 * upon changes to the target value for any device.
522 */
523int dev_pm_qos_remove_global_notifier(struct notifier_block *notifier)
524{
525 return blocking_notifier_chain_unregister(&dev_pm_notifiers, notifier);
526}
527EXPORT_SYMBOL_GPL(dev_pm_qos_remove_global_notifier);
Rafael J. Wysocki40a5f8b2011-12-23 01:23:52 +0100528
529/**
530 * dev_pm_qos_add_ancestor_request - Add PM QoS request for device's ancestor.
531 * @dev: Device whose ancestor to add the request for.
532 * @req: Pointer to the preallocated handle.
533 * @value: Constraint latency value.
534 */
535int dev_pm_qos_add_ancestor_request(struct device *dev,
536 struct dev_pm_qos_request *req, s32 value)
537{
538 struct device *ancestor = dev->parent;
Rafael J. Wysocki4ce47802012-12-18 14:07:49 +0100539 int ret = -ENODEV;
Rafael J. Wysocki40a5f8b2011-12-23 01:23:52 +0100540
541 while (ancestor && !ancestor->power.ignore_children)
542 ancestor = ancestor->parent;
543
544 if (ancestor)
Rafael J. Wysocki4ce47802012-12-18 14:07:49 +0100545 ret = dev_pm_qos_add_request(ancestor, req,
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100546 DEV_PM_QOS_RESUME_LATENCY, value);
Rafael J. Wysocki40a5f8b2011-12-23 01:23:52 +0100547
Rafael J. Wysocki4ce47802012-12-18 14:07:49 +0100548 if (ret < 0)
Rafael J. Wysocki40a5f8b2011-12-23 01:23:52 +0100549 req->dev = NULL;
550
Rafael J. Wysocki4ce47802012-12-18 14:07:49 +0100551 return ret;
Rafael J. Wysocki40a5f8b2011-12-23 01:23:52 +0100552}
553EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request);
Rafael J. Wysocki85dc0b82012-03-13 01:01:39 +0100554
555#ifdef CONFIG_PM_RUNTIME
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200556static void __dev_pm_qos_drop_user_request(struct device *dev,
557 enum dev_pm_qos_req_type type)
Rafael J. Wysocki85dc0b82012-03-13 01:01:39 +0100558{
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100559 struct dev_pm_qos_request *req = NULL;
560
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200561 switch(type) {
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100562 case DEV_PM_QOS_RESUME_LATENCY:
563 req = dev->power.qos->resume_latency_req;
564 dev->power.qos->resume_latency_req = NULL;
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200565 break;
566 case DEV_PM_QOS_FLAGS:
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100567 req = dev->power.qos->flags_req;
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200568 dev->power.qos->flags_req = NULL;
569 break;
570 }
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100571 __dev_pm_qos_remove_request(req);
572 kfree(req);
Rafael J. Wysocki85dc0b82012-03-13 01:01:39 +0100573}
574
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200575static void dev_pm_qos_drop_user_request(struct device *dev,
576 enum dev_pm_qos_req_type type)
577{
578 mutex_lock(&dev_pm_qos_mtx);
579 __dev_pm_qos_drop_user_request(dev, type);
580 mutex_unlock(&dev_pm_qos_mtx);
581}
582
Rafael J. Wysocki85dc0b82012-03-13 01:01:39 +0100583/**
584 * dev_pm_qos_expose_latency_limit - Expose PM QoS latency limit to user space.
585 * @dev: Device whose PM QoS latency limit is to be exposed to user space.
586 * @value: Initial value of the latency limit.
587 */
588int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
589{
590 struct dev_pm_qos_request *req;
591 int ret;
592
593 if (!device_is_registered(dev) || value < 0)
594 return -EINVAL;
595
Rafael J. Wysocki85dc0b82012-03-13 01:01:39 +0100596 req = kzalloc(sizeof(*req), GFP_KERNEL);
597 if (!req)
598 return -ENOMEM;
599
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100600 ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_RESUME_LATENCY, value);
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100601 if (ret < 0) {
602 kfree(req);
Rafael J. Wysocki85dc0b82012-03-13 01:01:39 +0100603 return ret;
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100604 }
605
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200606 mutex_lock(&dev_pm_qos_sysfs_mtx);
607
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100608 mutex_lock(&dev_pm_qos_mtx);
609
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100610 if (IS_ERR_OR_NULL(dev->power.qos))
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100611 ret = -ENODEV;
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100612 else if (dev->power.qos->resume_latency_req)
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100613 ret = -EEXIST;
614
615 if (ret < 0) {
616 __dev_pm_qos_remove_request(req);
617 kfree(req);
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200618 mutex_unlock(&dev_pm_qos_mtx);
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100619 goto out;
620 }
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100621 dev->power.qos->resume_latency_req = req;
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200622
623 mutex_unlock(&dev_pm_qos_mtx);
624
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100625 ret = pm_qos_sysfs_add_resume_latency(dev);
Rafael J. Wysocki85dc0b82012-03-13 01:01:39 +0100626 if (ret)
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100627 dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_RESUME_LATENCY);
Rafael J. Wysocki85dc0b82012-03-13 01:01:39 +0100628
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100629 out:
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200630 mutex_unlock(&dev_pm_qos_sysfs_mtx);
Rafael J. Wysocki85dc0b82012-03-13 01:01:39 +0100631 return ret;
632}
633EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit);
634
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100635static void __dev_pm_qos_hide_latency_limit(struct device *dev)
636{
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100637 if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->resume_latency_req)
638 __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_RESUME_LATENCY);
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100639}
640
Rafael J. Wysocki85dc0b82012-03-13 01:01:39 +0100641/**
642 * dev_pm_qos_hide_latency_limit - Hide PM QoS latency limit from user space.
643 * @dev: Device whose PM QoS latency limit is to be hidden from user space.
644 */
645void dev_pm_qos_hide_latency_limit(struct device *dev)
646{
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200647 mutex_lock(&dev_pm_qos_sysfs_mtx);
648
Rafael J. Wysockib02f6692014-02-11 00:35:23 +0100649 pm_qos_sysfs_remove_resume_latency(dev);
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200650
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100651 mutex_lock(&dev_pm_qos_mtx);
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100652 __dev_pm_qos_hide_latency_limit(dev);
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100653 mutex_unlock(&dev_pm_qos_mtx);
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200654
655 mutex_unlock(&dev_pm_qos_sysfs_mtx);
Rafael J. Wysocki85dc0b82012-03-13 01:01:39 +0100656}
657EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit);
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200658
659/**
660 * dev_pm_qos_expose_flags - Expose PM QoS flags of a device to user space.
661 * @dev: Device whose PM QoS flags are to be exposed to user space.
662 * @val: Initial values of the flags.
663 */
664int dev_pm_qos_expose_flags(struct device *dev, s32 val)
665{
666 struct dev_pm_qos_request *req;
667 int ret;
668
669 if (!device_is_registered(dev))
670 return -EINVAL;
671
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200672 req = kzalloc(sizeof(*req), GFP_KERNEL);
673 if (!req)
674 return -ENOMEM;
675
676 ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_FLAGS, val);
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100677 if (ret < 0) {
678 kfree(req);
679 return ret;
680 }
681
682 pm_runtime_get_sync(dev);
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200683 mutex_lock(&dev_pm_qos_sysfs_mtx);
684
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100685 mutex_lock(&dev_pm_qos_mtx);
686
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100687 if (IS_ERR_OR_NULL(dev->power.qos))
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100688 ret = -ENODEV;
689 else if (dev->power.qos->flags_req)
690 ret = -EEXIST;
691
692 if (ret < 0) {
693 __dev_pm_qos_remove_request(req);
694 kfree(req);
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200695 mutex_unlock(&dev_pm_qos_mtx);
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100696 goto out;
697 }
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200698 dev->power.qos->flags_req = req;
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200699
700 mutex_unlock(&dev_pm_qos_mtx);
701
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200702 ret = pm_qos_sysfs_add_flags(dev);
703 if (ret)
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200704 dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200705
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100706 out:
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200707 mutex_unlock(&dev_pm_qos_sysfs_mtx);
Lan Tianyu7e4d6842012-11-08 11:14:08 +0800708 pm_runtime_put(dev);
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200709 return ret;
710}
711EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags);
712
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100713static void __dev_pm_qos_hide_flags(struct device *dev)
714{
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200715 if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->flags_req)
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100716 __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100717}
718
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200719/**
720 * dev_pm_qos_hide_flags - Hide PM QoS flags of a device from user space.
721 * @dev: Device whose PM QoS flags are to be hidden from user space.
722 */
723void dev_pm_qos_hide_flags(struct device *dev)
724{
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100725 pm_runtime_get_sync(dev);
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200726 mutex_lock(&dev_pm_qos_sysfs_mtx);
727
728 pm_qos_sysfs_remove_flags(dev);
729
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100730 mutex_lock(&dev_pm_qos_mtx);
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100731 __dev_pm_qos_hide_flags(dev);
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100732 mutex_unlock(&dev_pm_qos_mtx);
Rafael J. Wysocki0f703062013-04-02 01:25:24 +0200733
734 mutex_unlock(&dev_pm_qos_sysfs_mtx);
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100735 pm_runtime_put(dev);
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200736}
737EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags);
738
739/**
740 * dev_pm_qos_update_flags - Update PM QoS flags request owned by user space.
741 * @dev: Device to update the PM QoS flags request for.
742 * @mask: Flags to set/clear.
743 * @set: Whether to set or clear the flags (true means set).
744 */
745int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set)
746{
747 s32 value;
748 int ret;
749
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200750 pm_runtime_get_sync(dev);
751 mutex_lock(&dev_pm_qos_mtx);
752
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100753 if (IS_ERR_OR_NULL(dev->power.qos) || !dev->power.qos->flags_req) {
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100754 ret = -EINVAL;
755 goto out;
756 }
757
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200758 value = dev_pm_qos_requested_flags(dev);
759 if (set)
760 value |= mask;
761 else
762 value &= ~mask;
763
764 ret = __dev_pm_qos_update_request(dev->power.qos->flags_req, value);
765
Rafael J. Wysockib81ea1b2013-03-03 22:48:14 +0100766 out:
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200767 mutex_unlock(&dev_pm_qos_mtx);
768 pm_runtime_put(dev);
Rafael J. Wysockie39473d2012-10-24 02:08:18 +0200769 return ret;
770}
Rafael J. Wysocki37530f22013-03-04 14:22:57 +0100771#else /* !CONFIG_PM_RUNTIME */
772static void __dev_pm_qos_hide_latency_limit(struct device *dev) {}
773static void __dev_pm_qos_hide_flags(struct device *dev) {}
Rafael J. Wysocki85dc0b82012-03-13 01:01:39 +0100774#endif /* CONFIG_PM_RUNTIME */