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 #include <linux/pm_runtime.h> 44 45 #include "power.h" 46 47 static DEFINE_MUTEX(dev_pm_qos_mtx); 48 49 static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers); 50 51 /** 52 * __dev_pm_qos_flags - Check PM QoS flags for a given device. 53 * @dev: Device to check the PM QoS flags for. 54 * @mask: Flags to check against. 55 * 56 * This routine must be called with dev->power.lock held. 57 */ 58 enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask) 59 { 60 struct dev_pm_qos *qos = dev->power.qos; 61 struct pm_qos_flags *pqf; 62 s32 val; 63 64 if (!qos) 65 return PM_QOS_FLAGS_UNDEFINED; 66 67 pqf = &qos->flags; 68 if (list_empty(&pqf->list)) 69 return PM_QOS_FLAGS_UNDEFINED; 70 71 val = pqf->effective_flags & mask; 72 if (val) 73 return (val == mask) ? PM_QOS_FLAGS_ALL : PM_QOS_FLAGS_SOME; 74 75 return PM_QOS_FLAGS_NONE; 76 } 77 78 /** 79 * dev_pm_qos_flags - Check PM QoS flags for a given device (locked). 80 * @dev: Device to check the PM QoS flags for. 81 * @mask: Flags to check against. 82 */ 83 enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask) 84 { 85 unsigned long irqflags; 86 enum pm_qos_flags_status ret; 87 88 spin_lock_irqsave(&dev->power.lock, irqflags); 89 ret = __dev_pm_qos_flags(dev, mask); 90 spin_unlock_irqrestore(&dev->power.lock, irqflags); 91 92 return ret; 93 } 94 EXPORT_SYMBOL_GPL(dev_pm_qos_flags); 95 96 /** 97 * __dev_pm_qos_read_value - Get PM QoS constraint for a given device. 98 * @dev: Device to get the PM QoS constraint value for. 99 * 100 * This routine must be called with dev->power.lock held. 101 */ 102 s32 __dev_pm_qos_read_value(struct device *dev) 103 { 104 return dev->power.qos ? pm_qos_read_value(&dev->power.qos->latency) : 0; 105 } 106 107 /** 108 * dev_pm_qos_read_value - Get PM QoS constraint for a given device (locked). 109 * @dev: Device to get the PM QoS constraint value for. 110 */ 111 s32 dev_pm_qos_read_value(struct device *dev) 112 { 113 unsigned long flags; 114 s32 ret; 115 116 spin_lock_irqsave(&dev->power.lock, flags); 117 ret = __dev_pm_qos_read_value(dev); 118 spin_unlock_irqrestore(&dev->power.lock, flags); 119 120 return ret; 121 } 122 123 /** 124 * apply_constraint - Add/modify/remove device PM QoS request. 125 * @req: Constraint request to apply 126 * @action: Action to perform (add/update/remove). 127 * @value: Value to assign to the QoS request. 128 * 129 * Internal function to update the constraints list using the PM QoS core 130 * code and if needed call the per-device and the global notification 131 * callbacks 132 */ 133 static int apply_constraint(struct dev_pm_qos_request *req, 134 enum pm_qos_req_action action, s32 value) 135 { 136 struct dev_pm_qos *qos = req->dev->power.qos; 137 int ret; 138 139 switch(req->type) { 140 case DEV_PM_QOS_LATENCY: 141 ret = pm_qos_update_target(&qos->latency, &req->data.pnode, 142 action, value); 143 if (ret) { 144 value = pm_qos_read_value(&qos->latency); 145 blocking_notifier_call_chain(&dev_pm_notifiers, 146 (unsigned long)value, 147 req); 148 } 149 break; 150 case DEV_PM_QOS_FLAGS: 151 ret = pm_qos_update_flags(&qos->flags, &req->data.flr, 152 action, value); 153 break; 154 default: 155 ret = -EINVAL; 156 } 157 158 return ret; 159 } 160 161 /* 162 * dev_pm_qos_constraints_allocate 163 * @dev: device to allocate data for 164 * 165 * Called at the first call to add_request, for constraint data allocation 166 * Must be called with the dev_pm_qos_mtx mutex held 167 */ 168 static int dev_pm_qos_constraints_allocate(struct device *dev) 169 { 170 struct dev_pm_qos *qos; 171 struct pm_qos_constraints *c; 172 struct blocking_notifier_head *n; 173 174 qos = kzalloc(sizeof(*qos), GFP_KERNEL); 175 if (!qos) 176 return -ENOMEM; 177 178 n = kzalloc(sizeof(*n), GFP_KERNEL); 179 if (!n) { 180 kfree(qos); 181 return -ENOMEM; 182 } 183 BLOCKING_INIT_NOTIFIER_HEAD(n); 184 185 c = &qos->latency; 186 plist_head_init(&c->list); 187 c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE; 188 c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE; 189 c->type = PM_QOS_MIN; 190 c->notifiers = n; 191 192 INIT_LIST_HEAD(&qos->flags.list); 193 194 spin_lock_irq(&dev->power.lock); 195 dev->power.qos = qos; 196 spin_unlock_irq(&dev->power.lock); 197 198 return 0; 199 } 200 201 /** 202 * dev_pm_qos_constraints_init - Initalize device's PM QoS constraints pointer. 203 * @dev: target device 204 * 205 * Called from the device PM subsystem during device insertion under 206 * device_pm_lock(). 207 */ 208 void dev_pm_qos_constraints_init(struct device *dev) 209 { 210 mutex_lock(&dev_pm_qos_mtx); 211 dev->power.qos = NULL; 212 dev->power.power_state = PMSG_ON; 213 mutex_unlock(&dev_pm_qos_mtx); 214 } 215 216 /** 217 * dev_pm_qos_constraints_destroy 218 * @dev: target device 219 * 220 * Called from the device PM subsystem on device removal under device_pm_lock(). 221 */ 222 void dev_pm_qos_constraints_destroy(struct device *dev) 223 { 224 struct dev_pm_qos *qos; 225 struct dev_pm_qos_request *req, *tmp; 226 struct pm_qos_constraints *c; 227 struct pm_qos_flags *f; 228 229 /* 230 * If the device's PM QoS resume latency limit or PM QoS flags have been 231 * exposed to user space, they have to be hidden at this point. 232 */ 233 dev_pm_qos_hide_latency_limit(dev); 234 dev_pm_qos_hide_flags(dev); 235 236 mutex_lock(&dev_pm_qos_mtx); 237 238 dev->power.power_state = PMSG_INVALID; 239 qos = dev->power.qos; 240 if (!qos) 241 goto out; 242 243 /* Flush the constraints lists for the device. */ 244 c = &qos->latency; 245 plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) { 246 /* 247 * Update constraints list and call the notification 248 * callbacks if needed 249 */ 250 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); 251 memset(req, 0, sizeof(*req)); 252 } 253 f = &qos->flags; 254 list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) { 255 apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); 256 memset(req, 0, sizeof(*req)); 257 } 258 259 spin_lock_irq(&dev->power.lock); 260 dev->power.qos = NULL; 261 spin_unlock_irq(&dev->power.lock); 262 263 kfree(c->notifiers); 264 kfree(qos); 265 266 out: 267 mutex_unlock(&dev_pm_qos_mtx); 268 } 269 270 /** 271 * dev_pm_qos_add_request - inserts new qos request into the list 272 * @dev: target device for the constraint 273 * @req: pointer to a preallocated handle 274 * @type: type of the request 275 * @value: defines the qos request 276 * 277 * This function inserts a new entry in the device constraints list of 278 * requested qos performance characteristics. It recomputes the aggregate 279 * QoS expectations of parameters and initializes the dev_pm_qos_request 280 * handle. Caller needs to save this handle for later use in updates and 281 * removal. 282 * 283 * Returns 1 if the aggregated constraint value has changed, 284 * 0 if the aggregated constraint value has not changed, 285 * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory 286 * to allocate for data structures, -ENODEV if the device has just been removed 287 * from the system. 288 * 289 * Callers should ensure that the target device is not RPM_SUSPENDED before 290 * using this function for requests of type DEV_PM_QOS_FLAGS. 291 */ 292 int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, 293 enum dev_pm_qos_req_type type, s32 value) 294 { 295 int ret = 0; 296 297 if (!dev || !req) /*guard against callers passing in null */ 298 return -EINVAL; 299 300 if (WARN(dev_pm_qos_request_active(req), 301 "%s() called for already added request\n", __func__)) 302 return -EINVAL; 303 304 req->dev = dev; 305 306 mutex_lock(&dev_pm_qos_mtx); 307 308 if (!dev->power.qos) { 309 if (dev->power.power_state.event == PM_EVENT_INVALID) { 310 /* The device has been removed from the system. */ 311 req->dev = NULL; 312 ret = -ENODEV; 313 goto out; 314 } else { 315 /* 316 * Allocate the constraints data on the first call to 317 * add_request, i.e. only if the data is not already 318 * allocated and if the device has not been removed. 319 */ 320 ret = dev_pm_qos_constraints_allocate(dev); 321 } 322 } 323 324 if (!ret) { 325 req->type = type; 326 ret = apply_constraint(req, PM_QOS_ADD_REQ, value); 327 } 328 329 out: 330 mutex_unlock(&dev_pm_qos_mtx); 331 332 return ret; 333 } 334 EXPORT_SYMBOL_GPL(dev_pm_qos_add_request); 335 336 /** 337 * __dev_pm_qos_update_request - Modify an existing device PM QoS request. 338 * @req : PM QoS request to modify. 339 * @new_value: New value to request. 340 */ 341 static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req, 342 s32 new_value) 343 { 344 s32 curr_value; 345 int ret = 0; 346 347 if (!req->dev->power.qos) 348 return -ENODEV; 349 350 switch(req->type) { 351 case DEV_PM_QOS_LATENCY: 352 curr_value = req->data.pnode.prio; 353 break; 354 case DEV_PM_QOS_FLAGS: 355 curr_value = req->data.flr.flags; 356 break; 357 default: 358 return -EINVAL; 359 } 360 361 if (curr_value != new_value) 362 ret = apply_constraint(req, PM_QOS_UPDATE_REQ, new_value); 363 364 return ret; 365 } 366 367 /** 368 * dev_pm_qos_update_request - modifies an existing qos request 369 * @req : handle to list element holding a dev_pm_qos request to use 370 * @new_value: defines the qos request 371 * 372 * Updates an existing dev PM qos request along with updating the 373 * target value. 374 * 375 * Attempts are made to make this code callable on hot code paths. 376 * 377 * Returns 1 if the aggregated constraint value has changed, 378 * 0 if the aggregated constraint value has not changed, 379 * -EINVAL in case of wrong parameters, -ENODEV if the device has been 380 * removed from the system 381 * 382 * Callers should ensure that the target device is not RPM_SUSPENDED before 383 * using this function for requests of type DEV_PM_QOS_FLAGS. 384 */ 385 int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value) 386 { 387 int ret; 388 389 if (!req) /*guard against callers passing in null */ 390 return -EINVAL; 391 392 if (WARN(!dev_pm_qos_request_active(req), 393 "%s() called for unknown object\n", __func__)) 394 return -EINVAL; 395 396 mutex_lock(&dev_pm_qos_mtx); 397 ret = __dev_pm_qos_update_request(req, new_value); 398 mutex_unlock(&dev_pm_qos_mtx); 399 400 return ret; 401 } 402 EXPORT_SYMBOL_GPL(dev_pm_qos_update_request); 403 404 /** 405 * dev_pm_qos_remove_request - modifies an existing qos request 406 * @req: handle to request list element 407 * 408 * Will remove pm qos request from the list of constraints and 409 * recompute the current target value. Call this on slow code paths. 410 * 411 * Returns 1 if the aggregated constraint value has changed, 412 * 0 if the aggregated constraint value has not changed, 413 * -EINVAL in case of wrong parameters, -ENODEV if the device has been 414 * removed from the system 415 * 416 * Callers should ensure that the target device is not RPM_SUSPENDED before 417 * using this function for requests of type DEV_PM_QOS_FLAGS. 418 */ 419 int dev_pm_qos_remove_request(struct dev_pm_qos_request *req) 420 { 421 int ret = 0; 422 423 if (!req) /*guard against callers passing in null */ 424 return -EINVAL; 425 426 if (WARN(!dev_pm_qos_request_active(req), 427 "%s() called for unknown object\n", __func__)) 428 return -EINVAL; 429 430 mutex_lock(&dev_pm_qos_mtx); 431 432 if (req->dev->power.qos) { 433 ret = apply_constraint(req, PM_QOS_REMOVE_REQ, 434 PM_QOS_DEFAULT_VALUE); 435 memset(req, 0, sizeof(*req)); 436 } else { 437 /* Return if the device has been removed */ 438 ret = -ENODEV; 439 } 440 441 mutex_unlock(&dev_pm_qos_mtx); 442 return ret; 443 } 444 EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request); 445 446 /** 447 * dev_pm_qos_add_notifier - sets notification entry for changes to target value 448 * of per-device PM QoS constraints 449 * 450 * @dev: target device for the constraint 451 * @notifier: notifier block managed by caller. 452 * 453 * Will register the notifier into a notification chain that gets called 454 * upon changes to the target value for the device. 455 * 456 * If the device's constraints object doesn't exist when this routine is called, 457 * it will be created (or error code will be returned if that fails). 458 */ 459 int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier) 460 { 461 int ret = 0; 462 463 mutex_lock(&dev_pm_qos_mtx); 464 465 if (!dev->power.qos) 466 ret = dev->power.power_state.event != PM_EVENT_INVALID ? 467 dev_pm_qos_constraints_allocate(dev) : -ENODEV; 468 469 if (!ret) 470 ret = blocking_notifier_chain_register( 471 dev->power.qos->latency.notifiers, notifier); 472 473 mutex_unlock(&dev_pm_qos_mtx); 474 return ret; 475 } 476 EXPORT_SYMBOL_GPL(dev_pm_qos_add_notifier); 477 478 /** 479 * dev_pm_qos_remove_notifier - deletes notification for changes to target value 480 * of per-device PM QoS constraints 481 * 482 * @dev: target device for the constraint 483 * @notifier: notifier block to be removed. 484 * 485 * Will remove the notifier from the notification chain that gets called 486 * upon changes to the target value. 487 */ 488 int dev_pm_qos_remove_notifier(struct device *dev, 489 struct notifier_block *notifier) 490 { 491 int retval = 0; 492 493 mutex_lock(&dev_pm_qos_mtx); 494 495 /* Silently return if the constraints object is not present. */ 496 if (dev->power.qos) 497 retval = blocking_notifier_chain_unregister( 498 dev->power.qos->latency.notifiers, 499 notifier); 500 501 mutex_unlock(&dev_pm_qos_mtx); 502 return retval; 503 } 504 EXPORT_SYMBOL_GPL(dev_pm_qos_remove_notifier); 505 506 /** 507 * dev_pm_qos_add_global_notifier - sets notification entry for changes to 508 * target value of the PM QoS constraints for any device 509 * 510 * @notifier: notifier block managed by caller. 511 * 512 * Will register the notifier into a notification chain that gets called 513 * upon changes to the target value for any device. 514 */ 515 int dev_pm_qos_add_global_notifier(struct notifier_block *notifier) 516 { 517 return blocking_notifier_chain_register(&dev_pm_notifiers, notifier); 518 } 519 EXPORT_SYMBOL_GPL(dev_pm_qos_add_global_notifier); 520 521 /** 522 * dev_pm_qos_remove_global_notifier - deletes notification for changes to 523 * target value of PM QoS constraints for any device 524 * 525 * @notifier: notifier block to be removed. 526 * 527 * Will remove the notifier from the notification chain that gets called 528 * upon changes to the target value for any device. 529 */ 530 int dev_pm_qos_remove_global_notifier(struct notifier_block *notifier) 531 { 532 return blocking_notifier_chain_unregister(&dev_pm_notifiers, notifier); 533 } 534 EXPORT_SYMBOL_GPL(dev_pm_qos_remove_global_notifier); 535 536 /** 537 * dev_pm_qos_add_ancestor_request - Add PM QoS request for device's ancestor. 538 * @dev: Device whose ancestor to add the request for. 539 * @req: Pointer to the preallocated handle. 540 * @value: Constraint latency value. 541 */ 542 int dev_pm_qos_add_ancestor_request(struct device *dev, 543 struct dev_pm_qos_request *req, s32 value) 544 { 545 struct device *ancestor = dev->parent; 546 int ret = -ENODEV; 547 548 while (ancestor && !ancestor->power.ignore_children) 549 ancestor = ancestor->parent; 550 551 if (ancestor) 552 ret = dev_pm_qos_add_request(ancestor, req, 553 DEV_PM_QOS_LATENCY, value); 554 555 if (ret < 0) 556 req->dev = NULL; 557 558 return ret; 559 } 560 EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request); 561 562 #ifdef CONFIG_PM_RUNTIME 563 static void __dev_pm_qos_drop_user_request(struct device *dev, 564 enum dev_pm_qos_req_type type) 565 { 566 switch(type) { 567 case DEV_PM_QOS_LATENCY: 568 dev_pm_qos_remove_request(dev->power.qos->latency_req); 569 dev->power.qos->latency_req = NULL; 570 break; 571 case DEV_PM_QOS_FLAGS: 572 dev_pm_qos_remove_request(dev->power.qos->flags_req); 573 dev->power.qos->flags_req = NULL; 574 break; 575 } 576 } 577 578 /** 579 * dev_pm_qos_expose_latency_limit - Expose PM QoS latency limit to user space. 580 * @dev: Device whose PM QoS latency limit is to be exposed to user space. 581 * @value: Initial value of the latency limit. 582 */ 583 int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value) 584 { 585 struct dev_pm_qos_request *req; 586 int ret; 587 588 if (!device_is_registered(dev) || value < 0) 589 return -EINVAL; 590 591 if (dev->power.qos && dev->power.qos->latency_req) 592 return -EEXIST; 593 594 req = kzalloc(sizeof(*req), GFP_KERNEL); 595 if (!req) 596 return -ENOMEM; 597 598 ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY, value); 599 if (ret < 0) 600 return ret; 601 602 dev->power.qos->latency_req = req; 603 ret = pm_qos_sysfs_add_latency(dev); 604 if (ret) 605 __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); 606 607 return ret; 608 } 609 EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit); 610 611 /** 612 * dev_pm_qos_hide_latency_limit - Hide PM QoS latency limit from user space. 613 * @dev: Device whose PM QoS latency limit is to be hidden from user space. 614 */ 615 void dev_pm_qos_hide_latency_limit(struct device *dev) 616 { 617 if (dev->power.qos && dev->power.qos->latency_req) { 618 pm_qos_sysfs_remove_latency(dev); 619 __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); 620 } 621 } 622 EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit); 623 624 /** 625 * dev_pm_qos_expose_flags - Expose PM QoS flags of a device to user space. 626 * @dev: Device whose PM QoS flags are to be exposed to user space. 627 * @val: Initial values of the flags. 628 */ 629 int dev_pm_qos_expose_flags(struct device *dev, s32 val) 630 { 631 struct dev_pm_qos_request *req; 632 int ret; 633 634 if (!device_is_registered(dev)) 635 return -EINVAL; 636 637 if (dev->power.qos && dev->power.qos->flags_req) 638 return -EEXIST; 639 640 req = kzalloc(sizeof(*req), GFP_KERNEL); 641 if (!req) 642 return -ENOMEM; 643 644 pm_runtime_get_sync(dev); 645 ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_FLAGS, val); 646 if (ret < 0) 647 goto fail; 648 649 dev->power.qos->flags_req = req; 650 ret = pm_qos_sysfs_add_flags(dev); 651 if (ret) 652 __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS); 653 654 fail: 655 pm_runtime_put(dev); 656 return ret; 657 } 658 EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags); 659 660 /** 661 * dev_pm_qos_hide_flags - Hide PM QoS flags of a device from user space. 662 * @dev: Device whose PM QoS flags are to be hidden from user space. 663 */ 664 void dev_pm_qos_hide_flags(struct device *dev) 665 { 666 if (dev->power.qos && dev->power.qos->flags_req) { 667 pm_qos_sysfs_remove_flags(dev); 668 pm_runtime_get_sync(dev); 669 __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS); 670 pm_runtime_put(dev); 671 } 672 } 673 EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags); 674 675 /** 676 * dev_pm_qos_update_flags - Update PM QoS flags request owned by user space. 677 * @dev: Device to update the PM QoS flags request for. 678 * @mask: Flags to set/clear. 679 * @set: Whether to set or clear the flags (true means set). 680 */ 681 int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set) 682 { 683 s32 value; 684 int ret; 685 686 if (!dev->power.qos || !dev->power.qos->flags_req) 687 return -EINVAL; 688 689 pm_runtime_get_sync(dev); 690 mutex_lock(&dev_pm_qos_mtx); 691 692 value = dev_pm_qos_requested_flags(dev); 693 if (set) 694 value |= mask; 695 else 696 value &= ~mask; 697 698 ret = __dev_pm_qos_update_request(dev->power.qos->flags_req, value); 699 700 mutex_unlock(&dev_pm_qos_mtx); 701 pm_runtime_put(dev); 702 703 return ret; 704 } 705 #endif /* CONFIG_PM_RUNTIME */ 706