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 #include <linux/export.h> 43 44 45 static DEFINE_MUTEX(dev_pm_qos_mtx); 46 47 static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers); 48 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. 52 * 53 * This routine must be called with dev->power.lock held. 54 */ 55 s32 __dev_pm_qos_read_value(struct device *dev) 56 { 57 struct pm_qos_constraints *c = dev->power.constraints; 58 59 return c ? pm_qos_read_value(c) : 0; 60 } 61 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. 65 */ 66 s32 dev_pm_qos_read_value(struct device *dev) 67 { 68 unsigned long flags; 69 s32 ret; 70 71 spin_lock_irqsave(&dev->power.lock, flags); 72 ret = __dev_pm_qos_read_value(dev); 73 spin_unlock_irqrestore(&dev->power.lock, flags); 74 75 return ret; 76 } 77 78 /* 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 83 * 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 87 */ 88 static int apply_constraint(struct dev_pm_qos_request *req, 89 enum pm_qos_req_action action, int value) 90 { 91 int ret, curr_value; 92 93 ret = pm_qos_update_target(req->dev->power.constraints, 94 &req->node, action, value); 95 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); 102 } 103 104 return ret; 105 } 106 107 /* 108 * dev_pm_qos_constraints_allocate 109 * @dev: device to allocate data for 110 * 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 113 */ 114 static int dev_pm_qos_constraints_allocate(struct device *dev) 115 { 116 struct pm_qos_constraints *c; 117 struct blocking_notifier_head *n; 118 119 c = kzalloc(sizeof(*c), GFP_KERNEL); 120 if (!c) 121 return -ENOMEM; 122 123 n = kzalloc(sizeof(*n), GFP_KERNEL); 124 if (!n) { 125 kfree(c); 126 return -ENOMEM; 127 } 128 BLOCKING_INIT_NOTIFIER_HEAD(n); 129 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; 135 136 spin_lock_irq(&dev->power.lock); 137 dev->power.constraints = c; 138 spin_unlock_irq(&dev->power.lock); 139 140 return 0; 141 } 142 143 /** 144 * dev_pm_qos_constraints_init - Initalize device's PM QoS constraints pointer. 145 * @dev: target device 146 * 147 * Called from the device PM subsystem during device insertion under 148 * device_pm_lock(). 149 */ 150 void dev_pm_qos_constraints_init(struct device *dev) 151 { 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); 156 } 157 158 /** 159 * dev_pm_qos_constraints_destroy 160 * @dev: target device 161 * 162 * Called from the device PM subsystem on device removal under device_pm_lock(). 163 */ 164 void dev_pm_qos_constraints_destroy(struct device *dev) 165 { 166 struct dev_pm_qos_request *req, *tmp; 167 struct pm_qos_constraints *c; 168 169 mutex_lock(&dev_pm_qos_mtx); 170 171 dev->power.power_state = PMSG_INVALID; 172 c = dev->power.constraints; 173 if (!c) 174 goto out; 175 176 /* Flush the constraints list for the device */ 177 plist_for_each_entry_safe(req, tmp, &c->list, node) { 178 /* 179 * Update constraints list and call the notification 180 * callbacks if needed 181 */ 182 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); 183 memset(req, 0, sizeof(*req)); 184 } 185 186 spin_lock_irq(&dev->power.lock); 187 dev->power.constraints = NULL; 188 spin_unlock_irq(&dev->power.lock); 189 190 kfree(c->notifiers); 191 kfree(c); 192 193 out: 194 mutex_unlock(&dev_pm_qos_mtx); 195 } 196 197 /** 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 202 * 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. 208 * 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. 214 */ 215 int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, 216 s32 value) 217 { 218 int ret = 0; 219 220 if (!dev || !req) /*guard against callers passing in null */ 221 return -EINVAL; 222 223 if (WARN(dev_pm_qos_request_active(req), 224 "%s() called for already added request\n", __func__)) 225 return -EINVAL; 226 227 req->dev = dev; 228 229 mutex_lock(&dev_pm_qos_mtx); 230 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 { 238 /* 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. 242 */ 243 ret = dev_pm_qos_constraints_allocate(dev); 244 } 245 } 246 247 if (!ret) 248 ret = apply_constraint(req, PM_QOS_ADD_REQ, value); 249 250 out: 251 mutex_unlock(&dev_pm_qos_mtx); 252 253 return ret; 254 } 255 EXPORT_SYMBOL_GPL(dev_pm_qos_add_request); 256 257 /** 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 261 * 262 * Updates an existing dev PM qos request along with updating the 263 * target value. 264 * 265 * Attempts are made to make this code callable on hot code paths. 266 * 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 271 */ 272 int dev_pm_qos_update_request(struct dev_pm_qos_request *req, 273 s32 new_value) 274 { 275 int ret = 0; 276 277 if (!req) /*guard against callers passing in null */ 278 return -EINVAL; 279 280 if (WARN(!dev_pm_qos_request_active(req), 281 "%s() called for unknown object\n", __func__)) 282 return -EINVAL; 283 284 mutex_lock(&dev_pm_qos_mtx); 285 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; 293 } 294 295 mutex_unlock(&dev_pm_qos_mtx); 296 return ret; 297 } 298 EXPORT_SYMBOL_GPL(dev_pm_qos_update_request); 299 300 /** 301 * dev_pm_qos_remove_request - modifies an existing qos request 302 * @req: handle to request list element 303 * 304 * Will remove pm qos request from the list of constraints and 305 * recompute the current target value. Call this on slow code paths. 306 * 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 311 */ 312 int dev_pm_qos_remove_request(struct dev_pm_qos_request *req) 313 { 314 int ret = 0; 315 316 if (!req) /*guard against callers passing in null */ 317 return -EINVAL; 318 319 if (WARN(!dev_pm_qos_request_active(req), 320 "%s() called for unknown object\n", __func__)) 321 return -EINVAL; 322 323 mutex_lock(&dev_pm_qos_mtx); 324 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; 332 } 333 334 mutex_unlock(&dev_pm_qos_mtx); 335 return ret; 336 } 337 EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request); 338 339 /** 340 * dev_pm_qos_add_notifier - sets notification entry for changes to target value 341 * of per-device PM QoS constraints 342 * 343 * @dev: target device for the constraint 344 * @notifier: notifier block managed by caller. 345 * 346 * Will register the notifier into a notification chain that gets called 347 * upon changes to the target value for the device. 348 */ 349 int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier) 350 { 351 int retval = 0; 352 353 mutex_lock(&dev_pm_qos_mtx); 354 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); 360 361 mutex_unlock(&dev_pm_qos_mtx); 362 return retval; 363 } 364 EXPORT_SYMBOL_GPL(dev_pm_qos_add_notifier); 365 366 /** 367 * dev_pm_qos_remove_notifier - deletes notification for changes to target value 368 * of per-device PM QoS constraints 369 * 370 * @dev: target device for the constraint 371 * @notifier: notifier block to be removed. 372 * 373 * Will remove the notifier from the notification chain that gets called 374 * upon changes to the target value. 375 */ 376 int dev_pm_qos_remove_notifier(struct device *dev, 377 struct notifier_block *notifier) 378 { 379 int retval = 0; 380 381 mutex_lock(&dev_pm_qos_mtx); 382 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); 388 389 mutex_unlock(&dev_pm_qos_mtx); 390 return retval; 391 } 392 EXPORT_SYMBOL_GPL(dev_pm_qos_remove_notifier); 393 394 /** 395 * dev_pm_qos_add_global_notifier - sets notification entry for changes to 396 * target value of the PM QoS constraints for any device 397 * 398 * @notifier: notifier block managed by caller. 399 * 400 * Will register the notifier into a notification chain that gets called 401 * upon changes to the target value for any device. 402 */ 403 int dev_pm_qos_add_global_notifier(struct notifier_block *notifier) 404 { 405 return blocking_notifier_chain_register(&dev_pm_notifiers, notifier); 406 } 407 EXPORT_SYMBOL_GPL(dev_pm_qos_add_global_notifier); 408 409 /** 410 * dev_pm_qos_remove_global_notifier - deletes notification for changes to 411 * target value of PM QoS constraints for any device 412 * 413 * @notifier: notifier block to be removed. 414 * 415 * Will remove the notifier from the notification chain that gets called 416 * upon changes to the target value for any device. 417 */ 418 int dev_pm_qos_remove_global_notifier(struct notifier_block *notifier) 419 { 420 return blocking_notifier_chain_unregister(&dev_pm_notifiers, notifier); 421 } 422 EXPORT_SYMBOL_GPL(dev_pm_qos_remove_global_notifier); 423 424 /** 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. 429 */ 430 int dev_pm_qos_add_ancestor_request(struct device *dev, 431 struct dev_pm_qos_request *req, s32 value) 432 { 433 struct device *ancestor = dev->parent; 434 int error = -ENODEV; 435 436 while (ancestor && !ancestor->power.ignore_children) 437 ancestor = ancestor->parent; 438 439 if (ancestor) 440 error = dev_pm_qos_add_request(ancestor, req, value); 441 442 if (error) 443 req->dev = NULL; 444 445 return error; 446 } 447 EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request); 448