diff options
-rw-r--r-- | Documentation/power/devices.txt | 67 | ||||
-rw-r--r-- | Documentation/power/runtime_pm.txt | 5 | ||||
-rw-r--r-- | drivers/base/power/clock_ops.c | 4 | ||||
-rw-r--r-- | drivers/base/power/main.c | 28 | ||||
-rw-r--r-- | drivers/pci/pci-driver.c | 4 | ||||
-rw-r--r-- | drivers/usb/core/driver.c | 6 | ||||
-rw-r--r-- | include/linux/device.h | 4 | ||||
-rw-r--r-- | include/linux/pm.h | 3 | ||||
-rw-r--r-- | kernel/power/user.c | 4 |
9 files changed, 50 insertions, 75 deletions
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index 88880839ece4..64565aac6e40 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt | |||
@@ -520,59 +520,20 @@ Support for power domains is provided through the pwr_domain field of struct | |||
520 | device. This field is a pointer to an object of type struct dev_power_domain, | 520 | device. This field is a pointer to an object of type struct dev_power_domain, |
521 | defined in include/linux/pm.h, providing a set of power management callbacks | 521 | defined in include/linux/pm.h, providing a set of power management callbacks |
522 | analogous to the subsystem-level and device driver callbacks that are executed | 522 | analogous to the subsystem-level and device driver callbacks that are executed |
523 | for the given device during all power transitions, in addition to the respective | 523 | for the given device during all power transitions, instead of the respective |
524 | subsystem-level callbacks. Specifically, the power domain "suspend" callbacks | 524 | subsystem-level callbacks. Specifically, if a device's pm_domain pointer is |
525 | (i.e. ->runtime_suspend(), ->suspend(), ->freeze(), ->poweroff(), etc.) are | 525 | not NULL, the ->suspend() callback from the object pointed to by it will be |
526 | executed after the analogous subsystem-level callbacks, while the power domain | 526 | executed instead of its subsystem's (e.g. bus type's) ->suspend() callback and |
527 | "resume" callbacks (i.e. ->runtime_resume(), ->resume(), ->thaw(), ->restore, | 527 | anlogously for all of the remaining callbacks. In other words, power management |
528 | etc.) are executed before the analogous subsystem-level callbacks. Error codes | 528 | domain callbacks, if defined for the given device, always take precedence over |
529 | returned by the "suspend" and "resume" power domain callbacks are ignored. | 529 | the callbacks provided by the device's subsystem (e.g. bus type). |
530 | 530 | ||
531 | Power domain ->runtime_idle() callback is executed before the subsystem-level | 531 | The support for device power management domains is only relevant to platforms |
532 | ->runtime_idle() callback and the result returned by it is not ignored. Namely, | 532 | needing to use the same device driver power management callbacks in many |
533 | if it returns error code, the subsystem-level ->runtime_idle() callback will not | 533 | different power domain configurations and wanting to avoid incorporating the |
534 | be called and the helper function rpm_idle() executing it will return error | 534 | support for power domains into subsystem-level callbacks, for example by |
535 | code. This mechanism is intended to help platforms where saving device state | 535 | modifying the platform bus type. Other platforms need not implement it or take |
536 | is a time consuming operation and should only be carried out if all devices | 536 | it into account in any way. |
537 | in the power domain are idle, before turning off the shared power resource(s). | ||
538 | Namely, the power domain ->runtime_idle() callback may return error code until | ||
539 | the pm_runtime_idle() helper (or its asychronous version) has been called for | ||
540 | all devices in the power domain (it is recommended that the returned error code | ||
541 | be -EBUSY in those cases), preventing the subsystem-level ->runtime_idle() | ||
542 | callback from being run prematurely. | ||
543 | |||
544 | The support for device power domains is only relevant to platforms needing to | ||
545 | use the same subsystem-level (e.g. platform bus type) and device driver power | ||
546 | management callbacks in many different power domain configurations and wanting | ||
547 | to avoid incorporating the support for power domains into the subsystem-level | ||
548 | callbacks. The other platforms need not implement it or take it into account | ||
549 | in any way. | ||
550 | |||
551 | |||
552 | System Devices | ||
553 | -------------- | ||
554 | System devices (sysdevs) follow a slightly different API, which can be found in | ||
555 | |||
556 | include/linux/sysdev.h | ||
557 | drivers/base/sys.c | ||
558 | |||
559 | System devices will be suspended with interrupts disabled, and after all other | ||
560 | devices have been suspended. On resume, they will be resumed before any other | ||
561 | devices, and also with interrupts disabled. These things occur in special | ||
562 | "sysdev_driver" phases, which affect only system devices. | ||
563 | |||
564 | Thus, after the suspend_noirq (or freeze_noirq or poweroff_noirq) phase, when | ||
565 | the non-boot CPUs are all offline and IRQs are disabled on the remaining online | ||
566 | CPU, then a sysdev_driver.suspend phase is carried out, and the system enters a | ||
567 | sleep state (or a system image is created). During resume (or after the image | ||
568 | has been created or loaded) a sysdev_driver.resume phase is carried out, IRQs | ||
569 | are enabled on the only online CPU, the non-boot CPUs are enabled, and the | ||
570 | resume_noirq (or thaw_noirq or restore_noirq) phase begins. | ||
571 | |||
572 | Code to actually enter and exit the system-wide low power state sometimes | ||
573 | involves hardware details that are only known to the boot firmware, and | ||
574 | may leave a CPU running software (from SRAM or flash memory) that monitors | ||
575 | the system and manages its wakeup sequence. | ||
576 | 537 | ||
577 | 538 | ||
578 | Device Low Power (suspend) States | 539 | Device Low Power (suspend) States |
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 654097b130b4..22accb3eb40e 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt | |||
@@ -566,11 +566,6 @@ to do this is: | |||
566 | pm_runtime_set_active(dev); | 566 | pm_runtime_set_active(dev); |
567 | pm_runtime_enable(dev); | 567 | pm_runtime_enable(dev); |
568 | 568 | ||
569 | The PM core always increments the run-time usage counter before calling the | ||
570 | ->prepare() callback and decrements it after calling the ->complete() callback. | ||
571 | Hence disabling run-time PM temporarily like this will not cause any run-time | ||
572 | suspend callbacks to be lost. | ||
573 | |||
574 | 7. Generic subsystem callbacks | 569 | 7. Generic subsystem callbacks |
575 | 570 | ||
576 | Subsystems may wish to conserve code space by using the set of generic power | 571 | Subsystems may wish to conserve code space by using the set of generic power |
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index eaa8a854af03..ad367c4139b1 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c | |||
@@ -387,7 +387,7 @@ static int pm_runtime_clk_notify(struct notifier_block *nb, | |||
387 | clknb = container_of(nb, struct pm_clk_notifier_block, nb); | 387 | clknb = container_of(nb, struct pm_clk_notifier_block, nb); |
388 | 388 | ||
389 | switch (action) { | 389 | switch (action) { |
390 | case BUS_NOTIFY_ADD_DEVICE: | 390 | case BUS_NOTIFY_BIND_DRIVER: |
391 | if (clknb->con_ids[0]) { | 391 | if (clknb->con_ids[0]) { |
392 | for (con_id = clknb->con_ids; *con_id; con_id++) | 392 | for (con_id = clknb->con_ids; *con_id; con_id++) |
393 | enable_clock(dev, *con_id); | 393 | enable_clock(dev, *con_id); |
@@ -395,7 +395,7 @@ static int pm_runtime_clk_notify(struct notifier_block *nb, | |||
395 | enable_clock(dev, NULL); | 395 | enable_clock(dev, NULL); |
396 | } | 396 | } |
397 | break; | 397 | break; |
398 | case BUS_NOTIFY_DEL_DEVICE: | 398 | case BUS_NOTIFY_UNBOUND_DRIVER: |
399 | if (clknb->con_ids[0]) { | 399 | if (clknb->con_ids[0]) { |
400 | for (con_id = clknb->con_ids; *con_id; con_id++) | 400 | for (con_id = clknb->con_ids; *con_id; con_id++) |
401 | disable_clock(dev, *con_id); | 401 | disable_clock(dev, *con_id); |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index aa6320207745..06f09bf89cb2 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -57,7 +57,8 @@ static int async_error; | |||
57 | */ | 57 | */ |
58 | void device_pm_init(struct device *dev) | 58 | void device_pm_init(struct device *dev) |
59 | { | 59 | { |
60 | dev->power.in_suspend = false; | 60 | dev->power.is_prepared = false; |
61 | dev->power.is_suspended = false; | ||
61 | init_completion(&dev->power.completion); | 62 | init_completion(&dev->power.completion); |
62 | complete_all(&dev->power.completion); | 63 | complete_all(&dev->power.completion); |
63 | dev->power.wakeup = NULL; | 64 | dev->power.wakeup = NULL; |
@@ -91,7 +92,7 @@ void device_pm_add(struct device *dev) | |||
91 | pr_debug("PM: Adding info for %s:%s\n", | 92 | pr_debug("PM: Adding info for %s:%s\n", |
92 | dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); | 93 | dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); |
93 | mutex_lock(&dpm_list_mtx); | 94 | mutex_lock(&dpm_list_mtx); |
94 | if (dev->parent && dev->parent->power.in_suspend) | 95 | if (dev->parent && dev->parent->power.is_prepared) |
95 | dev_warn(dev, "parent %s should not be sleeping\n", | 96 | dev_warn(dev, "parent %s should not be sleeping\n", |
96 | dev_name(dev->parent)); | 97 | dev_name(dev->parent)); |
97 | list_add_tail(&dev->power.entry, &dpm_list); | 98 | list_add_tail(&dev->power.entry, &dpm_list); |
@@ -511,7 +512,14 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) | |||
511 | dpm_wait(dev->parent, async); | 512 | dpm_wait(dev->parent, async); |
512 | device_lock(dev); | 513 | device_lock(dev); |
513 | 514 | ||
514 | dev->power.in_suspend = false; | 515 | /* |
516 | * This is a fib. But we'll allow new children to be added below | ||
517 | * a resumed device, even if the device hasn't been completed yet. | ||
518 | */ | ||
519 | dev->power.is_prepared = false; | ||
520 | |||
521 | if (!dev->power.is_suspended) | ||
522 | goto Unlock; | ||
515 | 523 | ||
516 | if (dev->pwr_domain) { | 524 | if (dev->pwr_domain) { |
517 | pm_dev_dbg(dev, state, "power domain "); | 525 | pm_dev_dbg(dev, state, "power domain "); |
@@ -548,6 +556,9 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) | |||
548 | } | 556 | } |
549 | 557 | ||
550 | End: | 558 | End: |
559 | dev->power.is_suspended = false; | ||
560 | |||
561 | Unlock: | ||
551 | device_unlock(dev); | 562 | device_unlock(dev); |
552 | complete_all(&dev->power.completion); | 563 | complete_all(&dev->power.completion); |
553 | 564 | ||
@@ -670,7 +681,7 @@ void dpm_complete(pm_message_t state) | |||
670 | struct device *dev = to_device(dpm_prepared_list.prev); | 681 | struct device *dev = to_device(dpm_prepared_list.prev); |
671 | 682 | ||
672 | get_device(dev); | 683 | get_device(dev); |
673 | dev->power.in_suspend = false; | 684 | dev->power.is_prepared = false; |
674 | list_move(&dev->power.entry, &list); | 685 | list_move(&dev->power.entry, &list); |
675 | mutex_unlock(&dpm_list_mtx); | 686 | mutex_unlock(&dpm_list_mtx); |
676 | 687 | ||
@@ -835,11 +846,11 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
835 | device_lock(dev); | 846 | device_lock(dev); |
836 | 847 | ||
837 | if (async_error) | 848 | if (async_error) |
838 | goto End; | 849 | goto Unlock; |
839 | 850 | ||
840 | if (pm_wakeup_pending()) { | 851 | if (pm_wakeup_pending()) { |
841 | async_error = -EBUSY; | 852 | async_error = -EBUSY; |
842 | goto End; | 853 | goto Unlock; |
843 | } | 854 | } |
844 | 855 | ||
845 | if (dev->pwr_domain) { | 856 | if (dev->pwr_domain) { |
@@ -877,6 +888,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
877 | } | 888 | } |
878 | 889 | ||
879 | End: | 890 | End: |
891 | dev->power.is_suspended = !error; | ||
892 | |||
893 | Unlock: | ||
880 | device_unlock(dev); | 894 | device_unlock(dev); |
881 | complete_all(&dev->power.completion); | 895 | complete_all(&dev->power.completion); |
882 | 896 | ||
@@ -1042,7 +1056,7 @@ int dpm_prepare(pm_message_t state) | |||
1042 | put_device(dev); | 1056 | put_device(dev); |
1043 | break; | 1057 | break; |
1044 | } | 1058 | } |
1045 | dev->power.in_suspend = true; | 1059 | dev->power.is_prepared = true; |
1046 | if (!list_empty(&dev->power.entry)) | 1060 | if (!list_empty(&dev->power.entry)) |
1047 | list_move_tail(&dev->power.entry, &dpm_prepared_list); | 1061 | list_move_tail(&dev->power.entry, &dpm_prepared_list); |
1048 | put_device(dev); | 1062 | put_device(dev); |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 135df164a4c1..46767c53917a 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -624,7 +624,7 @@ static int pci_pm_prepare(struct device *dev) | |||
624 | * system from the sleep state, we'll have to prevent it from signaling | 624 | * system from the sleep state, we'll have to prevent it from signaling |
625 | * wake-up. | 625 | * wake-up. |
626 | */ | 626 | */ |
627 | pm_runtime_resume(dev); | 627 | pm_runtime_get_sync(dev); |
628 | 628 | ||
629 | if (drv && drv->pm && drv->pm->prepare) | 629 | if (drv && drv->pm && drv->pm->prepare) |
630 | error = drv->pm->prepare(dev); | 630 | error = drv->pm->prepare(dev); |
@@ -638,6 +638,8 @@ static void pci_pm_complete(struct device *dev) | |||
638 | 638 | ||
639 | if (drv && drv->pm && drv->pm->complete) | 639 | if (drv && drv->pm && drv->pm->complete) |
640 | drv->pm->complete(dev); | 640 | drv->pm->complete(dev); |
641 | |||
642 | pm_runtime_put_sync(dev); | ||
641 | } | 643 | } |
642 | 644 | ||
643 | #else /* !CONFIG_PM_SLEEP */ | 645 | #else /* !CONFIG_PM_SLEEP */ |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index e35a17687c05..aa3cc465a601 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -375,7 +375,7 @@ static int usb_unbind_interface(struct device *dev) | |||
375 | * Just re-enable it without affecting the endpoint toggles. | 375 | * Just re-enable it without affecting the endpoint toggles. |
376 | */ | 376 | */ |
377 | usb_enable_interface(udev, intf, false); | 377 | usb_enable_interface(udev, intf, false); |
378 | } else if (!error && !intf->dev.power.in_suspend) { | 378 | } else if (!error && !intf->dev.power.is_prepared) { |
379 | r = usb_set_interface(udev, intf->altsetting[0]. | 379 | r = usb_set_interface(udev, intf->altsetting[0]. |
380 | desc.bInterfaceNumber, 0); | 380 | desc.bInterfaceNumber, 0); |
381 | if (r < 0) | 381 | if (r < 0) |
@@ -960,7 +960,7 @@ void usb_rebind_intf(struct usb_interface *intf) | |||
960 | } | 960 | } |
961 | 961 | ||
962 | /* Try to rebind the interface */ | 962 | /* Try to rebind the interface */ |
963 | if (!intf->dev.power.in_suspend) { | 963 | if (!intf->dev.power.is_prepared) { |
964 | intf->needs_binding = 0; | 964 | intf->needs_binding = 0; |
965 | rc = device_attach(&intf->dev); | 965 | rc = device_attach(&intf->dev); |
966 | if (rc < 0) | 966 | if (rc < 0) |
@@ -1107,7 +1107,7 @@ static int usb_resume_interface(struct usb_device *udev, | |||
1107 | if (intf->condition == USB_INTERFACE_UNBOUND) { | 1107 | if (intf->condition == USB_INTERFACE_UNBOUND) { |
1108 | 1108 | ||
1109 | /* Carry out a deferred switch to altsetting 0 */ | 1109 | /* Carry out a deferred switch to altsetting 0 */ |
1110 | if (intf->needs_altsetting0 && !intf->dev.power.in_suspend) { | 1110 | if (intf->needs_altsetting0 && !intf->dev.power.is_prepared) { |
1111 | usb_set_interface(udev, intf->altsetting[0]. | 1111 | usb_set_interface(udev, intf->altsetting[0]. |
1112 | desc.bInterfaceNumber, 0); | 1112 | desc.bInterfaceNumber, 0); |
1113 | intf->needs_altsetting0 = 0; | 1113 | intf->needs_altsetting0 = 0; |
diff --git a/include/linux/device.h b/include/linux/device.h index c66111affca9..553fd37b173b 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -654,13 +654,13 @@ static inline int device_is_registered(struct device *dev) | |||
654 | 654 | ||
655 | static inline void device_enable_async_suspend(struct device *dev) | 655 | static inline void device_enable_async_suspend(struct device *dev) |
656 | { | 656 | { |
657 | if (!dev->power.in_suspend) | 657 | if (!dev->power.is_prepared) |
658 | dev->power.async_suspend = true; | 658 | dev->power.async_suspend = true; |
659 | } | 659 | } |
660 | 660 | ||
661 | static inline void device_disable_async_suspend(struct device *dev) | 661 | static inline void device_disable_async_suspend(struct device *dev) |
662 | { | 662 | { |
663 | if (!dev->power.in_suspend) | 663 | if (!dev->power.is_prepared) |
664 | dev->power.async_suspend = false; | 664 | dev->power.async_suspend = false; |
665 | } | 665 | } |
666 | 666 | ||
diff --git a/include/linux/pm.h b/include/linux/pm.h index 3160648ccdda..411e4f4be52b 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
@@ -425,7 +425,8 @@ struct dev_pm_info { | |||
425 | pm_message_t power_state; | 425 | pm_message_t power_state; |
426 | unsigned int can_wakeup:1; | 426 | unsigned int can_wakeup:1; |
427 | unsigned int async_suspend:1; | 427 | unsigned int async_suspend:1; |
428 | unsigned int in_suspend:1; /* Owned by the PM core */ | 428 | bool is_prepared:1; /* Owned by the PM core */ |
429 | bool is_suspended:1; /* Ditto */ | ||
429 | spinlock_t lock; | 430 | spinlock_t lock; |
430 | #ifdef CONFIG_PM_SLEEP | 431 | #ifdef CONFIG_PM_SLEEP |
431 | struct list_head entry; | 432 | struct list_head entry; |
diff --git a/kernel/power/user.c b/kernel/power/user.c index 7d02d33be699..42ddbc6f0de6 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c | |||
@@ -113,8 +113,10 @@ static int snapshot_open(struct inode *inode, struct file *filp) | |||
113 | if (error) | 113 | if (error) |
114 | pm_notifier_call_chain(PM_POST_RESTORE); | 114 | pm_notifier_call_chain(PM_POST_RESTORE); |
115 | } | 115 | } |
116 | if (error) | 116 | if (error) { |
117 | free_basic_memory_bitmaps(); | ||
117 | atomic_inc(&snapshot_device_available); | 118 | atomic_inc(&snapshot_device_available); |
119 | } | ||
118 | data->frozen = 0; | 120 | data->frozen = 0; |
119 | data->ready = 0; | 121 | data->ready = 0; |
120 | data->platform_support = 0; | 122 | data->platform_support = 0; |