diff options
Diffstat (limited to 'drivers/base/power/main.c')
-rw-r--r-- | drivers/base/power/main.c | 191 |
1 files changed, 105 insertions, 86 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 1b1a786b7dec..e0dc4071e088 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/kallsyms.h> | 21 | #include <linux/kallsyms.h> |
22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | #include <linux/pm.h> | 23 | #include <linux/pm.h> |
24 | #include <linux/pm_runtime.h> | ||
24 | #include <linux/resume-trace.h> | 25 | #include <linux/resume-trace.h> |
25 | #include <linux/rwsem.h> | 26 | #include <linux/rwsem.h> |
26 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
@@ -49,7 +50,17 @@ static DEFINE_MUTEX(dpm_list_mtx); | |||
49 | static bool transition_started; | 50 | static bool transition_started; |
50 | 51 | ||
51 | /** | 52 | /** |
52 | * device_pm_lock - lock the list of active devices used by the PM core | 53 | * device_pm_init - Initialize the PM-related part of a device object. |
54 | * @dev: Device object being initialized. | ||
55 | */ | ||
56 | void device_pm_init(struct device *dev) | ||
57 | { | ||
58 | dev->power.status = DPM_ON; | ||
59 | pm_runtime_init(dev); | ||
60 | } | ||
61 | |||
62 | /** | ||
63 | * device_pm_lock - Lock the list of active devices used by the PM core. | ||
53 | */ | 64 | */ |
54 | void device_pm_lock(void) | 65 | void device_pm_lock(void) |
55 | { | 66 | { |
@@ -57,7 +68,7 @@ void device_pm_lock(void) | |||
57 | } | 68 | } |
58 | 69 | ||
59 | /** | 70 | /** |
60 | * device_pm_unlock - unlock the list of active devices used by the PM core | 71 | * device_pm_unlock - Unlock the list of active devices used by the PM core. |
61 | */ | 72 | */ |
62 | void device_pm_unlock(void) | 73 | void device_pm_unlock(void) |
63 | { | 74 | { |
@@ -65,8 +76,8 @@ void device_pm_unlock(void) | |||
65 | } | 76 | } |
66 | 77 | ||
67 | /** | 78 | /** |
68 | * device_pm_add - add a device to the list of active devices | 79 | * device_pm_add - Add a device to the PM core's list of active devices. |
69 | * @dev: Device to be added to the list | 80 | * @dev: Device to add to the list. |
70 | */ | 81 | */ |
71 | void device_pm_add(struct device *dev) | 82 | void device_pm_add(struct device *dev) |
72 | { | 83 | { |
@@ -92,10 +103,8 @@ void device_pm_add(struct device *dev) | |||
92 | } | 103 | } |
93 | 104 | ||
94 | /** | 105 | /** |
95 | * device_pm_remove - remove a device from the list of active devices | 106 | * device_pm_remove - Remove a device from the PM core's list of active devices. |
96 | * @dev: Device to be removed from the list | 107 | * @dev: Device to be removed from the list. |
97 | * | ||
98 | * This function also removes the device's PM-related sysfs attributes. | ||
99 | */ | 108 | */ |
100 | void device_pm_remove(struct device *dev) | 109 | void device_pm_remove(struct device *dev) |
101 | { | 110 | { |
@@ -105,12 +114,13 @@ void device_pm_remove(struct device *dev) | |||
105 | mutex_lock(&dpm_list_mtx); | 114 | mutex_lock(&dpm_list_mtx); |
106 | list_del_init(&dev->power.entry); | 115 | list_del_init(&dev->power.entry); |
107 | mutex_unlock(&dpm_list_mtx); | 116 | mutex_unlock(&dpm_list_mtx); |
117 | pm_runtime_remove(dev); | ||
108 | } | 118 | } |
109 | 119 | ||
110 | /** | 120 | /** |
111 | * device_pm_move_before - move device in dpm_list | 121 | * device_pm_move_before - Move device in the PM core's list of active devices. |
112 | * @deva: Device to move in dpm_list | 122 | * @deva: Device to move in dpm_list. |
113 | * @devb: Device @deva should come before | 123 | * @devb: Device @deva should come before. |
114 | */ | 124 | */ |
115 | void device_pm_move_before(struct device *deva, struct device *devb) | 125 | void device_pm_move_before(struct device *deva, struct device *devb) |
116 | { | 126 | { |
@@ -124,9 +134,9 @@ void device_pm_move_before(struct device *deva, struct device *devb) | |||
124 | } | 134 | } |
125 | 135 | ||
126 | /** | 136 | /** |
127 | * device_pm_move_after - move device in dpm_list | 137 | * device_pm_move_after - Move device in the PM core's list of active devices. |
128 | * @deva: Device to move in dpm_list | 138 | * @deva: Device to move in dpm_list. |
129 | * @devb: Device @deva should come after | 139 | * @devb: Device @deva should come after. |
130 | */ | 140 | */ |
131 | void device_pm_move_after(struct device *deva, struct device *devb) | 141 | void device_pm_move_after(struct device *deva, struct device *devb) |
132 | { | 142 | { |
@@ -140,8 +150,8 @@ void device_pm_move_after(struct device *deva, struct device *devb) | |||
140 | } | 150 | } |
141 | 151 | ||
142 | /** | 152 | /** |
143 | * device_pm_move_last - move device to end of dpm_list | 153 | * device_pm_move_last - Move device to end of the PM core's list of devices. |
144 | * @dev: Device to move in dpm_list | 154 | * @dev: Device to move in dpm_list. |
145 | */ | 155 | */ |
146 | void device_pm_move_last(struct device *dev) | 156 | void device_pm_move_last(struct device *dev) |
147 | { | 157 | { |
@@ -152,10 +162,10 @@ void device_pm_move_last(struct device *dev) | |||
152 | } | 162 | } |
153 | 163 | ||
154 | /** | 164 | /** |
155 | * pm_op - execute the PM operation appropiate for given PM event | 165 | * pm_op - Execute the PM operation appropriate for given PM event. |
156 | * @dev: Device. | 166 | * @dev: Device to handle. |
157 | * @ops: PM operations to choose from. | 167 | * @ops: PM operations to choose from. |
158 | * @state: PM transition of the system being carried out. | 168 | * @state: PM transition of the system being carried out. |
159 | */ | 169 | */ |
160 | static int pm_op(struct device *dev, | 170 | static int pm_op(struct device *dev, |
161 | const struct dev_pm_ops *ops, | 171 | const struct dev_pm_ops *ops, |
@@ -213,13 +223,13 @@ static int pm_op(struct device *dev, | |||
213 | } | 223 | } |
214 | 224 | ||
215 | /** | 225 | /** |
216 | * pm_noirq_op - execute the PM operation appropiate for given PM event | 226 | * pm_noirq_op - Execute the PM operation appropriate for given PM event. |
217 | * @dev: Device. | 227 | * @dev: Device to handle. |
218 | * @ops: PM operations to choose from. | 228 | * @ops: PM operations to choose from. |
219 | * @state: PM transition of the system being carried out. | 229 | * @state: PM transition of the system being carried out. |
220 | * | 230 | * |
221 | * The operation is executed with interrupts disabled by the only remaining | 231 | * The driver of @dev will not receive interrupts while this function is being |
222 | * functional CPU in the system. | 232 | * executed. |
223 | */ | 233 | */ |
224 | static int pm_noirq_op(struct device *dev, | 234 | static int pm_noirq_op(struct device *dev, |
225 | const struct dev_pm_ops *ops, | 235 | const struct dev_pm_ops *ops, |
@@ -317,11 +327,12 @@ static void pm_dev_err(struct device *dev, pm_message_t state, char *info, | |||
317 | /*------------------------- Resume routines -------------------------*/ | 327 | /*------------------------- Resume routines -------------------------*/ |
318 | 328 | ||
319 | /** | 329 | /** |
320 | * device_resume_noirq - Power on one device (early resume). | 330 | * device_resume_noirq - Execute an "early resume" callback for given device. |
321 | * @dev: Device. | 331 | * @dev: Device to handle. |
322 | * @state: PM transition of the system being carried out. | 332 | * @state: PM transition of the system being carried out. |
323 | * | 333 | * |
324 | * Must be called with interrupts disabled. | 334 | * The driver of @dev will not receive interrupts while this function is being |
335 | * executed. | ||
325 | */ | 336 | */ |
326 | static int device_resume_noirq(struct device *dev, pm_message_t state) | 337 | static int device_resume_noirq(struct device *dev, pm_message_t state) |
327 | { | 338 | { |
@@ -343,20 +354,18 @@ static int device_resume_noirq(struct device *dev, pm_message_t state) | |||
343 | } | 354 | } |
344 | 355 | ||
345 | /** | 356 | /** |
346 | * dpm_resume_noirq - Power on all regular (non-sysdev) devices. | 357 | * dpm_resume_noirq - Execute "early resume" callbacks for non-sysdev devices. |
347 | * @state: PM transition of the system being carried out. | 358 | * @state: PM transition of the system being carried out. |
348 | * | ||
349 | * Call the "noirq" resume handlers for all devices marked as | ||
350 | * DPM_OFF_IRQ and enable device drivers to receive interrupts. | ||
351 | * | 359 | * |
352 | * Must be called under dpm_list_mtx. Device drivers should not receive | 360 | * Call the "noirq" resume handlers for all devices marked as DPM_OFF_IRQ and |
353 | * interrupts while it's being executed. | 361 | * enable device drivers to receive interrupts. |
354 | */ | 362 | */ |
355 | void dpm_resume_noirq(pm_message_t state) | 363 | void dpm_resume_noirq(pm_message_t state) |
356 | { | 364 | { |
357 | struct device *dev; | 365 | struct device *dev; |
358 | 366 | ||
359 | mutex_lock(&dpm_list_mtx); | 367 | mutex_lock(&dpm_list_mtx); |
368 | transition_started = false; | ||
360 | list_for_each_entry(dev, &dpm_list, power.entry) | 369 | list_for_each_entry(dev, &dpm_list, power.entry) |
361 | if (dev->power.status > DPM_OFF) { | 370 | if (dev->power.status > DPM_OFF) { |
362 | int error; | 371 | int error; |
@@ -372,9 +381,9 @@ void dpm_resume_noirq(pm_message_t state) | |||
372 | EXPORT_SYMBOL_GPL(dpm_resume_noirq); | 381 | EXPORT_SYMBOL_GPL(dpm_resume_noirq); |
373 | 382 | ||
374 | /** | 383 | /** |
375 | * device_resume - Restore state for one device. | 384 | * device_resume - Execute "resume" callbacks for given device. |
376 | * @dev: Device. | 385 | * @dev: Device to handle. |
377 | * @state: PM transition of the system being carried out. | 386 | * @state: PM transition of the system being carried out. |
378 | */ | 387 | */ |
379 | static int device_resume(struct device *dev, pm_message_t state) | 388 | static int device_resume(struct device *dev, pm_message_t state) |
380 | { | 389 | { |
@@ -423,11 +432,11 @@ static int device_resume(struct device *dev, pm_message_t state) | |||
423 | } | 432 | } |
424 | 433 | ||
425 | /** | 434 | /** |
426 | * dpm_resume - Resume every device. | 435 | * dpm_resume - Execute "resume" callbacks for non-sysdev devices. |
427 | * @state: PM transition of the system being carried out. | 436 | * @state: PM transition of the system being carried out. |
428 | * | 437 | * |
429 | * Execute the appropriate "resume" callback for all devices the status of | 438 | * Execute the appropriate "resume" callback for all devices whose status |
430 | * which indicates that they are inactive. | 439 | * indicates that they are suspended. |
431 | */ | 440 | */ |
432 | static void dpm_resume(pm_message_t state) | 441 | static void dpm_resume(pm_message_t state) |
433 | { | 442 | { |
@@ -435,7 +444,6 @@ static void dpm_resume(pm_message_t state) | |||
435 | 444 | ||
436 | INIT_LIST_HEAD(&list); | 445 | INIT_LIST_HEAD(&list); |
437 | mutex_lock(&dpm_list_mtx); | 446 | mutex_lock(&dpm_list_mtx); |
438 | transition_started = false; | ||
439 | while (!list_empty(&dpm_list)) { | 447 | while (!list_empty(&dpm_list)) { |
440 | struct device *dev = to_device(dpm_list.next); | 448 | struct device *dev = to_device(dpm_list.next); |
441 | 449 | ||
@@ -464,9 +472,9 @@ static void dpm_resume(pm_message_t state) | |||
464 | } | 472 | } |
465 | 473 | ||
466 | /** | 474 | /** |
467 | * device_complete - Complete a PM transition for given device | 475 | * device_complete - Complete a PM transition for given device. |
468 | * @dev: Device. | 476 | * @dev: Device to handle. |
469 | * @state: PM transition of the system being carried out. | 477 | * @state: PM transition of the system being carried out. |
470 | */ | 478 | */ |
471 | static void device_complete(struct device *dev, pm_message_t state) | 479 | static void device_complete(struct device *dev, pm_message_t state) |
472 | { | 480 | { |
@@ -491,11 +499,11 @@ static void device_complete(struct device *dev, pm_message_t state) | |||
491 | } | 499 | } |
492 | 500 | ||
493 | /** | 501 | /** |
494 | * dpm_complete - Complete a PM transition for all devices. | 502 | * dpm_complete - Complete a PM transition for all non-sysdev devices. |
495 | * @state: PM transition of the system being carried out. | 503 | * @state: PM transition of the system being carried out. |
496 | * | 504 | * |
497 | * Execute the ->complete() callbacks for all devices that are not marked | 505 | * Execute the ->complete() callbacks for all devices whose PM status is not |
498 | * as DPM_ON. | 506 | * DPM_ON (this allows new devices to be registered). |
499 | */ | 507 | */ |
500 | static void dpm_complete(pm_message_t state) | 508 | static void dpm_complete(pm_message_t state) |
501 | { | 509 | { |
@@ -512,6 +520,7 @@ static void dpm_complete(pm_message_t state) | |||
512 | mutex_unlock(&dpm_list_mtx); | 520 | mutex_unlock(&dpm_list_mtx); |
513 | 521 | ||
514 | device_complete(dev, state); | 522 | device_complete(dev, state); |
523 | pm_runtime_put_noidle(dev); | ||
515 | 524 | ||
516 | mutex_lock(&dpm_list_mtx); | 525 | mutex_lock(&dpm_list_mtx); |
517 | } | 526 | } |
@@ -524,11 +533,11 @@ static void dpm_complete(pm_message_t state) | |||
524 | } | 533 | } |
525 | 534 | ||
526 | /** | 535 | /** |
527 | * dpm_resume_end - Restore state of each device in system. | 536 | * dpm_resume_end - Execute "resume" callbacks and complete system transition. |
528 | * @state: PM transition of the system being carried out. | 537 | * @state: PM transition of the system being carried out. |
529 | * | 538 | * |
530 | * Resume all the devices, unlock them all, and allow new | 539 | * Execute "resume" callbacks for all devices and complete the PM transition of |
531 | * devices to be registered once again. | 540 | * the system. |
532 | */ | 541 | */ |
533 | void dpm_resume_end(pm_message_t state) | 542 | void dpm_resume_end(pm_message_t state) |
534 | { | 543 | { |
@@ -542,9 +551,11 @@ EXPORT_SYMBOL_GPL(dpm_resume_end); | |||
542 | /*------------------------- Suspend routines -------------------------*/ | 551 | /*------------------------- Suspend routines -------------------------*/ |
543 | 552 | ||
544 | /** | 553 | /** |
545 | * resume_event - return a PM message representing the resume event | 554 | * resume_event - Return a "resume" message for given "suspend" sleep state. |
546 | * corresponding to given sleep state. | 555 | * @sleep_state: PM message representing a sleep state. |
547 | * @sleep_state: PM message representing a sleep state. | 556 | * |
557 | * Return a PM message representing the resume event corresponding to given | ||
558 | * sleep state. | ||
548 | */ | 559 | */ |
549 | static pm_message_t resume_event(pm_message_t sleep_state) | 560 | static pm_message_t resume_event(pm_message_t sleep_state) |
550 | { | 561 | { |
@@ -561,11 +572,12 @@ static pm_message_t resume_event(pm_message_t sleep_state) | |||
561 | } | 572 | } |
562 | 573 | ||
563 | /** | 574 | /** |
564 | * device_suspend_noirq - Shut down one device (late suspend). | 575 | * device_suspend_noirq - Execute a "late suspend" callback for given device. |
565 | * @dev: Device. | 576 | * @dev: Device to handle. |
566 | * @state: PM transition of the system being carried out. | 577 | * @state: PM transition of the system being carried out. |
567 | * | 578 | * |
568 | * This is called with interrupts off and only a single CPU running. | 579 | * The driver of @dev will not receive interrupts while this function is being |
580 | * executed. | ||
569 | */ | 581 | */ |
570 | static int device_suspend_noirq(struct device *dev, pm_message_t state) | 582 | static int device_suspend_noirq(struct device *dev, pm_message_t state) |
571 | { | 583 | { |
@@ -582,13 +594,11 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state) | |||
582 | } | 594 | } |
583 | 595 | ||
584 | /** | 596 | /** |
585 | * dpm_suspend_noirq - Power down all regular (non-sysdev) devices. | 597 | * dpm_suspend_noirq - Execute "late suspend" callbacks for non-sysdev devices. |
586 | * @state: PM transition of the system being carried out. | 598 | * @state: PM transition of the system being carried out. |
587 | * | ||
588 | * Prevent device drivers from receiving interrupts and call the "noirq" | ||
589 | * suspend handlers. | ||
590 | * | 599 | * |
591 | * Must be called under dpm_list_mtx. | 600 | * Prevent device drivers from receiving interrupts and call the "noirq" suspend |
601 | * handlers for all non-sysdev devices. | ||
592 | */ | 602 | */ |
593 | int dpm_suspend_noirq(pm_message_t state) | 603 | int dpm_suspend_noirq(pm_message_t state) |
594 | { | 604 | { |
@@ -613,9 +623,9 @@ int dpm_suspend_noirq(pm_message_t state) | |||
613 | EXPORT_SYMBOL_GPL(dpm_suspend_noirq); | 623 | EXPORT_SYMBOL_GPL(dpm_suspend_noirq); |
614 | 624 | ||
615 | /** | 625 | /** |
616 | * device_suspend - Save state of one device. | 626 | * device_suspend - Execute "suspend" callbacks for given device. |
617 | * @dev: Device. | 627 | * @dev: Device to handle. |
618 | * @state: PM transition of the system being carried out. | 628 | * @state: PM transition of the system being carried out. |
619 | */ | 629 | */ |
620 | static int device_suspend(struct device *dev, pm_message_t state) | 630 | static int device_suspend(struct device *dev, pm_message_t state) |
621 | { | 631 | { |
@@ -662,10 +672,8 @@ static int device_suspend(struct device *dev, pm_message_t state) | |||
662 | } | 672 | } |
663 | 673 | ||
664 | /** | 674 | /** |
665 | * dpm_suspend - Suspend every device. | 675 | * dpm_suspend - Execute "suspend" callbacks for all non-sysdev devices. |
666 | * @state: PM transition of the system being carried out. | 676 | * @state: PM transition of the system being carried out. |
667 | * | ||
668 | * Execute the appropriate "suspend" callbacks for all devices. | ||
669 | */ | 677 | */ |
670 | static int dpm_suspend(pm_message_t state) | 678 | static int dpm_suspend(pm_message_t state) |
671 | { | 679 | { |
@@ -699,9 +707,12 @@ static int dpm_suspend(pm_message_t state) | |||
699 | } | 707 | } |
700 | 708 | ||
701 | /** | 709 | /** |
702 | * device_prepare - Execute the ->prepare() callback(s) for given device. | 710 | * device_prepare - Prepare a device for system power transition. |
703 | * @dev: Device. | 711 | * @dev: Device to handle. |
704 | * @state: PM transition of the system being carried out. | 712 | * @state: PM transition of the system being carried out. |
713 | * | ||
714 | * Execute the ->prepare() callback(s) for given device. No new children of the | ||
715 | * device may be registered after this function has returned. | ||
705 | */ | 716 | */ |
706 | static int device_prepare(struct device *dev, pm_message_t state) | 717 | static int device_prepare(struct device *dev, pm_message_t state) |
707 | { | 718 | { |
@@ -737,10 +748,10 @@ static int device_prepare(struct device *dev, pm_message_t state) | |||
737 | } | 748 | } |
738 | 749 | ||
739 | /** | 750 | /** |
740 | * dpm_prepare - Prepare all devices for a PM transition. | 751 | * dpm_prepare - Prepare all non-sysdev devices for a system PM transition. |
741 | * @state: PM transition of the system being carried out. | 752 | * @state: PM transition of the system being carried out. |
742 | * | 753 | * |
743 | * Execute the ->prepare() callback for all devices. | 754 | * Execute the ->prepare() callback(s) for all devices. |
744 | */ | 755 | */ |
745 | static int dpm_prepare(pm_message_t state) | 756 | static int dpm_prepare(pm_message_t state) |
746 | { | 757 | { |
@@ -757,7 +768,14 @@ static int dpm_prepare(pm_message_t state) | |||
757 | dev->power.status = DPM_PREPARING; | 768 | dev->power.status = DPM_PREPARING; |
758 | mutex_unlock(&dpm_list_mtx); | 769 | mutex_unlock(&dpm_list_mtx); |
759 | 770 | ||
760 | error = device_prepare(dev, state); | 771 | pm_runtime_get_noresume(dev); |
772 | if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) { | ||
773 | /* Wake-up requested during system sleep transition. */ | ||
774 | pm_runtime_put_noidle(dev); | ||
775 | error = -EBUSY; | ||
776 | } else { | ||
777 | error = device_prepare(dev, state); | ||
778 | } | ||
761 | 779 | ||
762 | mutex_lock(&dpm_list_mtx); | 780 | mutex_lock(&dpm_list_mtx); |
763 | if (error) { | 781 | if (error) { |
@@ -784,10 +802,11 @@ static int dpm_prepare(pm_message_t state) | |||
784 | } | 802 | } |
785 | 803 | ||
786 | /** | 804 | /** |
787 | * dpm_suspend_start - Save state and stop all devices in system. | 805 | * dpm_suspend_start - Prepare devices for PM transition and suspend them. |
788 | * @state: PM transition of the system being carried out. | 806 | * @state: PM transition of the system being carried out. |
789 | * | 807 | * |
790 | * Prepare and suspend all devices. | 808 | * Prepare all non-sysdev devices for system PM transition and execute "suspend" |
809 | * callbacks for them. | ||
791 | */ | 810 | */ |
792 | int dpm_suspend_start(pm_message_t state) | 811 | int dpm_suspend_start(pm_message_t state) |
793 | { | 812 | { |