diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2017-07-03 08:23:09 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2017-07-03 08:23:09 -0400 |
commit | 8f8e5c3e2796eaf150d6262115af12707c2616dd (patch) | |
tree | 85f3ec09ce6960fd57c85610a5c97841f2ded9ba | |
parent | 9a5f2c871af4cf6bd63ddb20061faa7049103350 (diff) | |
parent | de3ef1eb1cd0cc3a75f7a3661e10ed827f370ab8 (diff) |
Merge branch 'acpi-pm'
* acpi-pm:
PM / core: Drop run_wake flag from struct dev_pm_info
PCI / PM: Simplify device wakeup settings code
PCI / PM: Drop pme_interrupt flag from struct pci_dev
ACPI / PM: Consolidate device wakeup settings code
ACPI / PM: Drop run_wake from struct acpi_device_wakeup_flags
ACPI / sleep: EC-based wakeup from suspend-to-idle on recent systems
platform: x86: intel-hid: Wake up the system from suspend-to-idle
platform: x86: intel-vbtn: Wake up the system from suspend-to-idle
ACPI / PM: Ignore spurious SCI wakeups from suspend-to-idle
platform/x86: Add driver for ACPI INT0002 Virtual GPIO device
PCI / PM: Restore PME Enable if skipping wakeup setup
PM / sleep: Print timing information if debug is enabled
ACPI / PM: Clean up device wakeup enable/disable code
ACPI / PM: Change log level of wakeup-related message
USB / PCI / PM: Allow the PCI core to do the resume cleanup
ACPI / PM: Run wakeup notify handlers synchronously
Conflicts:
drivers/base/power/main.c
35 files changed, 669 insertions, 301 deletions
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index ee69d7532172..0fde3dcf077a 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt | |||
@@ -105,9 +105,9 @@ knows what to do to handle the device). | |||
105 | 105 | ||
106 | In particular, if the driver requires remote wakeup capability (i.e. hardware | 106 | In particular, if the driver requires remote wakeup capability (i.e. hardware |
107 | mechanism allowing the device to request a change of its power state, such as | 107 | mechanism allowing the device to request a change of its power state, such as |
108 | PCI PME) for proper functioning and device_run_wake() returns 'false' for the | 108 | PCI PME) for proper functioning and device_can_wakeup() returns 'false' for the |
109 | device, then ->runtime_suspend() should return -EBUSY. On the other hand, if | 109 | device, then ->runtime_suspend() should return -EBUSY. On the other hand, if |
110 | device_run_wake() returns 'true' for the device and the device is put into a | 110 | device_can_wakeup() returns 'true' for the device and the device is put into a |
111 | low-power state during the execution of the suspend callback, it is expected | 111 | low-power state during the execution of the suspend callback, it is expected |
112 | that remote wakeup will be enabled for the device. Generally, remote wakeup | 112 | that remote wakeup will be enabled for the device. Generally, remote wakeup |
113 | should be enabled for all input devices put into low-power states at run time. | 113 | should be enabled for all input devices put into low-power states at run time. |
@@ -253,9 +253,6 @@ defined in include/linux/pm.h: | |||
253 | being executed for that device and it is not practical to wait for the | 253 | being executed for that device and it is not practical to wait for the |
254 | suspend to complete; means "start a resume as soon as you've suspended" | 254 | suspend to complete; means "start a resume as soon as you've suspended" |
255 | 255 | ||
256 | unsigned int run_wake; | ||
257 | - set if the device is capable of generating runtime wake-up events | ||
258 | |||
259 | enum rpm_status runtime_status; | 256 | enum rpm_status runtime_status; |
260 | - the runtime PM status of the device; this field's initial value is | 257 | - the runtime PM status of the device; this field's initial value is |
261 | RPM_SUSPENDED, which means that each device is initially regarded by the | 258 | RPM_SUSPENDED, which means that each device is initially regarded by the |
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index d42eeef9d928..1cbb88d938e5 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
@@ -782,7 +782,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume) | |||
782 | if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) || | 782 | if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) || |
783 | (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) && | 783 | (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) && |
784 | (battery->capacity_now <= battery->alarm))) | 784 | (battery->capacity_now <= battery->alarm))) |
785 | pm_wakeup_event(&battery->device->dev, 0); | 785 | acpi_pm_wakeup_event(&battery->device->dev); |
786 | 786 | ||
787 | return result; | 787 | return result; |
788 | } | 788 | } |
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index e19f530f1083..91cfdf377df7 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -217,7 +217,7 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state) | |||
217 | } | 217 | } |
218 | 218 | ||
219 | if (state) | 219 | if (state) |
220 | pm_wakeup_event(&device->dev, 0); | 220 | acpi_pm_wakeup_event(&device->dev); |
221 | 221 | ||
222 | ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); | 222 | ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); |
223 | if (ret == NOTIFY_DONE) | 223 | if (ret == NOTIFY_DONE) |
@@ -402,7 +402,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) | |||
402 | } else { | 402 | } else { |
403 | int keycode; | 403 | int keycode; |
404 | 404 | ||
405 | pm_wakeup_event(&device->dev, 0); | 405 | acpi_pm_wakeup_event(&device->dev); |
406 | if (button->suspended) | 406 | if (button->suspended) |
407 | break; | 407 | break; |
408 | 408 | ||
@@ -534,6 +534,7 @@ static int acpi_button_add(struct acpi_device *device) | |||
534 | lid_device = device; | 534 | lid_device = device; |
535 | } | 535 | } |
536 | 536 | ||
537 | device_init_wakeup(&device->dev, true); | ||
537 | printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); | 538 | printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); |
538 | return 0; | 539 | return 0; |
539 | 540 | ||
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 993fd31394c8..28938b5a334e 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/pm_qos.h> | 24 | #include <linux/pm_qos.h> |
25 | #include <linux/pm_domain.h> | 25 | #include <linux/pm_domain.h> |
26 | #include <linux/pm_runtime.h> | 26 | #include <linux/pm_runtime.h> |
27 | #include <linux/suspend.h> | ||
27 | 28 | ||
28 | #include "internal.h" | 29 | #include "internal.h" |
29 | 30 | ||
@@ -385,6 +386,12 @@ EXPORT_SYMBOL(acpi_bus_power_manageable); | |||
385 | #ifdef CONFIG_PM | 386 | #ifdef CONFIG_PM |
386 | static DEFINE_MUTEX(acpi_pm_notifier_lock); | 387 | static DEFINE_MUTEX(acpi_pm_notifier_lock); |
387 | 388 | ||
389 | void acpi_pm_wakeup_event(struct device *dev) | ||
390 | { | ||
391 | pm_wakeup_dev_event(dev, 0, acpi_s2idle_wakeup()); | ||
392 | } | ||
393 | EXPORT_SYMBOL_GPL(acpi_pm_wakeup_event); | ||
394 | |||
388 | static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used) | 395 | static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used) |
389 | { | 396 | { |
390 | struct acpi_device *adev; | 397 | struct acpi_device *adev; |
@@ -399,9 +406,9 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used) | |||
399 | mutex_lock(&acpi_pm_notifier_lock); | 406 | mutex_lock(&acpi_pm_notifier_lock); |
400 | 407 | ||
401 | if (adev->wakeup.flags.notifier_present) { | 408 | if (adev->wakeup.flags.notifier_present) { |
402 | __pm_wakeup_event(adev->wakeup.ws, 0); | 409 | pm_wakeup_ws_event(adev->wakeup.ws, 0, acpi_s2idle_wakeup()); |
403 | if (adev->wakeup.context.work.func) | 410 | if (adev->wakeup.context.func) |
404 | queue_pm_work(&adev->wakeup.context.work); | 411 | adev->wakeup.context.func(&adev->wakeup.context); |
405 | } | 412 | } |
406 | 413 | ||
407 | mutex_unlock(&acpi_pm_notifier_lock); | 414 | mutex_unlock(&acpi_pm_notifier_lock); |
@@ -413,7 +420,7 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used) | |||
413 | * acpi_add_pm_notifier - Register PM notify handler for given ACPI device. | 420 | * acpi_add_pm_notifier - Register PM notify handler for given ACPI device. |
414 | * @adev: ACPI device to add the notify handler for. | 421 | * @adev: ACPI device to add the notify handler for. |
415 | * @dev: Device to generate a wakeup event for while handling the notification. | 422 | * @dev: Device to generate a wakeup event for while handling the notification. |
416 | * @work_func: Work function to execute when handling the notification. | 423 | * @func: Work function to execute when handling the notification. |
417 | * | 424 | * |
418 | * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of | 425 | * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of |
419 | * PM wakeup events. For example, wakeup events may be generated for bridges | 426 | * PM wakeup events. For example, wakeup events may be generated for bridges |
@@ -421,11 +428,11 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used) | |||
421 | * bridge itself doesn't have a wakeup GPE associated with it. | 428 | * bridge itself doesn't have a wakeup GPE associated with it. |
422 | */ | 429 | */ |
423 | acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev, | 430 | acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev, |
424 | void (*work_func)(struct work_struct *work)) | 431 | void (*func)(struct acpi_device_wakeup_context *context)) |
425 | { | 432 | { |
426 | acpi_status status = AE_ALREADY_EXISTS; | 433 | acpi_status status = AE_ALREADY_EXISTS; |
427 | 434 | ||
428 | if (!dev && !work_func) | 435 | if (!dev && !func) |
429 | return AE_BAD_PARAMETER; | 436 | return AE_BAD_PARAMETER; |
430 | 437 | ||
431 | mutex_lock(&acpi_pm_notifier_lock); | 438 | mutex_lock(&acpi_pm_notifier_lock); |
@@ -435,8 +442,7 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev, | |||
435 | 442 | ||
436 | adev->wakeup.ws = wakeup_source_register(dev_name(&adev->dev)); | 443 | adev->wakeup.ws = wakeup_source_register(dev_name(&adev->dev)); |
437 | adev->wakeup.context.dev = dev; | 444 | adev->wakeup.context.dev = dev; |
438 | if (work_func) | 445 | adev->wakeup.context.func = func; |
439 | INIT_WORK(&adev->wakeup.context.work, work_func); | ||
440 | 446 | ||
441 | status = acpi_install_notify_handler(adev->handle, ACPI_SYSTEM_NOTIFY, | 447 | status = acpi_install_notify_handler(adev->handle, ACPI_SYSTEM_NOTIFY, |
442 | acpi_pm_notify_handler, NULL); | 448 | acpi_pm_notify_handler, NULL); |
@@ -469,10 +475,7 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev) | |||
469 | if (ACPI_FAILURE(status)) | 475 | if (ACPI_FAILURE(status)) |
470 | goto out; | 476 | goto out; |
471 | 477 | ||
472 | if (adev->wakeup.context.work.func) { | 478 | adev->wakeup.context.func = NULL; |
473 | cancel_work_sync(&adev->wakeup.context.work); | ||
474 | adev->wakeup.context.work.func = NULL; | ||
475 | } | ||
476 | adev->wakeup.context.dev = NULL; | 479 | adev->wakeup.context.dev = NULL; |
477 | wakeup_source_unregister(adev->wakeup.ws); | 480 | wakeup_source_unregister(adev->wakeup.ws); |
478 | 481 | ||
@@ -493,6 +496,13 @@ bool acpi_bus_can_wakeup(acpi_handle handle) | |||
493 | } | 496 | } |
494 | EXPORT_SYMBOL(acpi_bus_can_wakeup); | 497 | EXPORT_SYMBOL(acpi_bus_can_wakeup); |
495 | 498 | ||
499 | bool acpi_pm_device_can_wakeup(struct device *dev) | ||
500 | { | ||
501 | struct acpi_device *adev = ACPI_COMPANION(dev); | ||
502 | |||
503 | return adev ? acpi_device_can_wakeup(adev) : false; | ||
504 | } | ||
505 | |||
496 | /** | 506 | /** |
497 | * acpi_dev_pm_get_state - Get preferred power state of ACPI device. | 507 | * acpi_dev_pm_get_state - Get preferred power state of ACPI device. |
498 | * @dev: Device whose preferred target power state to return. | 508 | * @dev: Device whose preferred target power state to return. |
@@ -658,16 +668,15 @@ EXPORT_SYMBOL(acpi_pm_device_sleep_state); | |||
658 | 668 | ||
659 | /** | 669 | /** |
660 | * acpi_pm_notify_work_func - ACPI devices wakeup notification work function. | 670 | * acpi_pm_notify_work_func - ACPI devices wakeup notification work function. |
661 | * @work: Work item to handle. | 671 | * @context: Device wakeup context. |
662 | */ | 672 | */ |
663 | static void acpi_pm_notify_work_func(struct work_struct *work) | 673 | static void acpi_pm_notify_work_func(struct acpi_device_wakeup_context *context) |
664 | { | 674 | { |
665 | struct device *dev; | 675 | struct device *dev = context->dev; |
666 | 676 | ||
667 | dev = container_of(work, struct acpi_device_wakeup_context, work)->dev; | ||
668 | if (dev) { | 677 | if (dev) { |
669 | pm_wakeup_event(dev, 0); | 678 | pm_wakeup_event(dev, 0); |
670 | pm_runtime_resume(dev); | 679 | pm_request_resume(dev); |
671 | } | 680 | } |
672 | } | 681 | } |
673 | 682 | ||
@@ -693,80 +702,53 @@ static int acpi_device_wakeup(struct acpi_device *adev, u32 target_state, | |||
693 | acpi_status res; | 702 | acpi_status res; |
694 | int error; | 703 | int error; |
695 | 704 | ||
705 | if (adev->wakeup.flags.enabled) | ||
706 | return 0; | ||
707 | |||
696 | error = acpi_enable_wakeup_device_power(adev, target_state); | 708 | error = acpi_enable_wakeup_device_power(adev, target_state); |
697 | if (error) | 709 | if (error) |
698 | return error; | 710 | return error; |
699 | 711 | ||
700 | if (adev->wakeup.flags.enabled) | ||
701 | return 0; | ||
702 | |||
703 | res = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number); | 712 | res = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number); |
704 | if (ACPI_SUCCESS(res)) { | 713 | if (ACPI_FAILURE(res)) { |
705 | adev->wakeup.flags.enabled = 1; | ||
706 | } else { | ||
707 | acpi_disable_wakeup_device_power(adev); | 714 | acpi_disable_wakeup_device_power(adev); |
708 | return -EIO; | 715 | return -EIO; |
709 | } | 716 | } |
710 | } else { | 717 | adev->wakeup.flags.enabled = 1; |
711 | if (adev->wakeup.flags.enabled) { | 718 | } else if (adev->wakeup.flags.enabled) { |
712 | acpi_disable_gpe(wakeup->gpe_device, wakeup->gpe_number); | 719 | acpi_disable_gpe(wakeup->gpe_device, wakeup->gpe_number); |
713 | adev->wakeup.flags.enabled = 0; | ||
714 | } | ||
715 | acpi_disable_wakeup_device_power(adev); | 720 | acpi_disable_wakeup_device_power(adev); |
721 | adev->wakeup.flags.enabled = 0; | ||
716 | } | 722 | } |
717 | return 0; | 723 | return 0; |
718 | } | 724 | } |
719 | 725 | ||
720 | /** | 726 | /** |
721 | * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device. | 727 | * acpi_pm_set_device_wakeup - Enable/disable remote wakeup for given device. |
722 | * @dev: Device to enable/disable the platform to wake up. | 728 | * @dev: Device to enable/disable to generate wakeup events. |
723 | * @enable: Whether to enable or disable the wakeup functionality. | 729 | * @enable: Whether to enable or disable the wakeup functionality. |
724 | */ | 730 | */ |
725 | int acpi_pm_device_run_wake(struct device *phys_dev, bool enable) | 731 | int acpi_pm_set_device_wakeup(struct device *dev, bool enable) |
726 | { | ||
727 | struct acpi_device *adev; | ||
728 | |||
729 | if (!device_run_wake(phys_dev)) | ||
730 | return -EINVAL; | ||
731 | |||
732 | adev = ACPI_COMPANION(phys_dev); | ||
733 | if (!adev) { | ||
734 | dev_dbg(phys_dev, "ACPI companion missing in %s!\n", __func__); | ||
735 | return -ENODEV; | ||
736 | } | ||
737 | |||
738 | return acpi_device_wakeup(adev, ACPI_STATE_S0, enable); | ||
739 | } | ||
740 | EXPORT_SYMBOL(acpi_pm_device_run_wake); | ||
741 | |||
742 | #ifdef CONFIG_PM_SLEEP | ||
743 | /** | ||
744 | * acpi_pm_device_sleep_wake - Enable or disable device to wake up the system. | ||
745 | * @dev: Device to enable/desible to wake up the system from sleep states. | ||
746 | * @enable: Whether to enable or disable @dev to wake up the system. | ||
747 | */ | ||
748 | int acpi_pm_device_sleep_wake(struct device *dev, bool enable) | ||
749 | { | 732 | { |
750 | struct acpi_device *adev; | 733 | struct acpi_device *adev; |
751 | int error; | 734 | int error; |
752 | 735 | ||
753 | if (!device_can_wakeup(dev)) | ||
754 | return -EINVAL; | ||
755 | |||
756 | adev = ACPI_COMPANION(dev); | 736 | adev = ACPI_COMPANION(dev); |
757 | if (!adev) { | 737 | if (!adev) { |
758 | dev_dbg(dev, "ACPI companion missing in %s!\n", __func__); | 738 | dev_dbg(dev, "ACPI companion missing in %s!\n", __func__); |
759 | return -ENODEV; | 739 | return -ENODEV; |
760 | } | 740 | } |
761 | 741 | ||
742 | if (!acpi_device_can_wakeup(adev)) | ||
743 | return -EINVAL; | ||
744 | |||
762 | error = acpi_device_wakeup(adev, acpi_target_system_state(), enable); | 745 | error = acpi_device_wakeup(adev, acpi_target_system_state(), enable); |
763 | if (!error) | 746 | if (!error) |
764 | dev_info(dev, "System wakeup %s by ACPI\n", | 747 | dev_dbg(dev, "Wakeup %s by ACPI\n", enable ? "enabled" : "disabled"); |
765 | enable ? "enabled" : "disabled"); | ||
766 | 748 | ||
767 | return error; | 749 | return error; |
768 | } | 750 | } |
769 | #endif /* CONFIG_PM_SLEEP */ | 751 | EXPORT_SYMBOL(acpi_pm_set_device_wakeup); |
770 | 752 | ||
771 | /** | 753 | /** |
772 | * acpi_dev_pm_low_power - Put ACPI device into a low-power state. | 754 | * acpi_dev_pm_low_power - Put ACPI device into a low-power state. |
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index c24235d8fb52..156e15c35ffa 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -1835,7 +1835,7 @@ static int acpi_ec_suspend(struct device *dev) | |||
1835 | struct acpi_ec *ec = | 1835 | struct acpi_ec *ec = |
1836 | acpi_driver_data(to_acpi_device(dev)); | 1836 | acpi_driver_data(to_acpi_device(dev)); |
1837 | 1837 | ||
1838 | if (ec_freeze_events) | 1838 | if (acpi_sleep_no_ec_events() && ec_freeze_events) |
1839 | acpi_ec_disable_event(ec); | 1839 | acpi_ec_disable_event(ec); |
1840 | return 0; | 1840 | return 0; |
1841 | } | 1841 | } |
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 66229ffa909b..be79f7db1850 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
@@ -198,8 +198,12 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit); | |||
198 | Suspend/Resume | 198 | Suspend/Resume |
199 | -------------------------------------------------------------------------- */ | 199 | -------------------------------------------------------------------------- */ |
200 | #ifdef CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT | 200 | #ifdef CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT |
201 | extern bool acpi_s2idle_wakeup(void); | ||
202 | extern bool acpi_sleep_no_ec_events(void); | ||
201 | extern int acpi_sleep_init(void); | 203 | extern int acpi_sleep_init(void); |
202 | #else | 204 | #else |
205 | static inline bool acpi_s2idle_wakeup(void) { return false; } | ||
206 | static inline bool acpi_sleep_no_ec_events(void) { return true; } | ||
203 | static inline int acpi_sleep_init(void) { return -ENXIO; } | 207 | static inline int acpi_sleep_init(void) { return -ENXIO; } |
204 | #endif | 208 | #endif |
205 | 209 | ||
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 919be0aa2578..0d34e622a8b5 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -608,8 +608,7 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
608 | pcie_no_aspm(); | 608 | pcie_no_aspm(); |
609 | 609 | ||
610 | pci_acpi_add_bus_pm_notifier(device); | 610 | pci_acpi_add_bus_pm_notifier(device); |
611 | if (device->wakeup.flags.run_wake) | 611 | device_set_wakeup_capable(root->bus->bridge, device->wakeup.flags.valid); |
612 | device_set_run_wake(root->bus->bridge, true); | ||
613 | 612 | ||
614 | if (hotadd) { | 613 | if (hotadd) { |
615 | pcibios_resource_survey_bus(root->bus); | 614 | pcibios_resource_survey_bus(root->bus); |
@@ -649,7 +648,7 @@ static void acpi_pci_root_remove(struct acpi_device *device) | |||
649 | pci_stop_root_bus(root->bus); | 648 | pci_stop_root_bus(root->bus); |
650 | 649 | ||
651 | pci_ioapic_remove(root); | 650 | pci_ioapic_remove(root); |
652 | device_set_run_wake(root->bus->bridge, false); | 651 | device_set_wakeup_capable(root->bus->bridge, false); |
653 | pci_acpi_remove_bus_pm_notifier(device); | 652 | pci_acpi_remove_bus_pm_notifier(device); |
654 | 653 | ||
655 | pci_remove_root_bus(root->bus); | 654 | pci_remove_root_bus(root->bus); |
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c index a34669cc823b..85ac848ac6ab 100644 --- a/drivers/acpi/proc.c +++ b/drivers/acpi/proc.c | |||
@@ -42,7 +42,7 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) | |||
42 | 42 | ||
43 | if (!dev->physical_node_count) { | 43 | if (!dev->physical_node_count) { |
44 | seq_printf(seq, "%c%-8s\n", | 44 | seq_printf(seq, "%c%-8s\n", |
45 | dev->wakeup.flags.run_wake ? '*' : ' ', | 45 | dev->wakeup.flags.valid ? '*' : ' ', |
46 | device_may_wakeup(&dev->dev) ? | 46 | device_may_wakeup(&dev->dev) ? |
47 | "enabled" : "disabled"); | 47 | "enabled" : "disabled"); |
48 | } else { | 48 | } else { |
@@ -58,7 +58,7 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) | |||
58 | seq_printf(seq, "\t\t"); | 58 | seq_printf(seq, "\t\t"); |
59 | 59 | ||
60 | seq_printf(seq, "%c%-8s %s:%s\n", | 60 | seq_printf(seq, "%c%-8s %s:%s\n", |
61 | dev->wakeup.flags.run_wake ? '*' : ' ', | 61 | dev->wakeup.flags.valid ? '*' : ' ', |
62 | (device_may_wakeup(&dev->dev) || | 62 | (device_may_wakeup(&dev->dev) || |
63 | device_may_wakeup(ldev)) ? | 63 | device_may_wakeup(ldev)) ? |
64 | "enabled" : "disabled", | 64 | "enabled" : "disabled", |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index d53162997f32..09f65f57bebe 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -835,7 +835,7 @@ static int acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, | |||
835 | return err; | 835 | return err; |
836 | } | 836 | } |
837 | 837 | ||
838 | static void acpi_wakeup_gpe_init(struct acpi_device *device) | 838 | static bool acpi_wakeup_gpe_init(struct acpi_device *device) |
839 | { | 839 | { |
840 | static const struct acpi_device_id button_device_ids[] = { | 840 | static const struct acpi_device_id button_device_ids[] = { |
841 | {"PNP0C0C", 0}, | 841 | {"PNP0C0C", 0}, |
@@ -845,13 +845,11 @@ static void acpi_wakeup_gpe_init(struct acpi_device *device) | |||
845 | }; | 845 | }; |
846 | struct acpi_device_wakeup *wakeup = &device->wakeup; | 846 | struct acpi_device_wakeup *wakeup = &device->wakeup; |
847 | acpi_status status; | 847 | acpi_status status; |
848 | acpi_event_status event_status; | ||
849 | 848 | ||
850 | wakeup->flags.notifier_present = 0; | 849 | wakeup->flags.notifier_present = 0; |
851 | 850 | ||
852 | /* Power button, Lid switch always enable wakeup */ | 851 | /* Power button, Lid switch always enable wakeup */ |
853 | if (!acpi_match_device_ids(device, button_device_ids)) { | 852 | if (!acpi_match_device_ids(device, button_device_ids)) { |
854 | wakeup->flags.run_wake = 1; | ||
855 | if (!acpi_match_device_ids(device, &button_device_ids[1])) { | 853 | if (!acpi_match_device_ids(device, &button_device_ids[1])) { |
856 | /* Do not use Lid/sleep button for S5 wakeup */ | 854 | /* Do not use Lid/sleep button for S5 wakeup */ |
857 | if (wakeup->sleep_state == ACPI_STATE_S5) | 855 | if (wakeup->sleep_state == ACPI_STATE_S5) |
@@ -859,17 +857,12 @@ static void acpi_wakeup_gpe_init(struct acpi_device *device) | |||
859 | } | 857 | } |
860 | acpi_mark_gpe_for_wake(wakeup->gpe_device, wakeup->gpe_number); | 858 | acpi_mark_gpe_for_wake(wakeup->gpe_device, wakeup->gpe_number); |
861 | device_set_wakeup_capable(&device->dev, true); | 859 | device_set_wakeup_capable(&device->dev, true); |
862 | return; | 860 | return true; |
863 | } | 861 | } |
864 | 862 | ||
865 | acpi_setup_gpe_for_wake(device->handle, wakeup->gpe_device, | 863 | status = acpi_setup_gpe_for_wake(device->handle, wakeup->gpe_device, |
866 | wakeup->gpe_number); | 864 | wakeup->gpe_number); |
867 | status = acpi_get_gpe_status(wakeup->gpe_device, wakeup->gpe_number, | 865 | return ACPI_SUCCESS(status); |
868 | &event_status); | ||
869 | if (ACPI_FAILURE(status)) | ||
870 | return; | ||
871 | |||
872 | wakeup->flags.run_wake = !!(event_status & ACPI_EVENT_FLAG_HAS_HANDLER); | ||
873 | } | 866 | } |
874 | 867 | ||
875 | static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | 868 | static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) |
@@ -887,10 +880,10 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | |||
887 | return; | 880 | return; |
888 | } | 881 | } |
889 | 882 | ||
890 | device->wakeup.flags.valid = 1; | 883 | device->wakeup.flags.valid = acpi_wakeup_gpe_init(device); |
891 | device->wakeup.prepare_count = 0; | 884 | device->wakeup.prepare_count = 0; |
892 | acpi_wakeup_gpe_init(device); | 885 | /* |
893 | /* Call _PSW/_DSW object to disable its ability to wake the sleeping | 886 | * Call _PSW/_DSW object to disable its ability to wake the sleeping |
894 | * system for the ACPI device with the _PRW object. | 887 | * system for the ACPI device with the _PRW object. |
895 | * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW. | 888 | * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW. |
896 | * So it is necessary to call _DSW object first. Only when it is not | 889 | * So it is necessary to call _DSW object first. Only when it is not |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 097d630ab886..be17664736b2 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -650,38 +650,165 @@ static const struct platform_suspend_ops acpi_suspend_ops_old = { | |||
650 | .recover = acpi_pm_finish, | 650 | .recover = acpi_pm_finish, |
651 | }; | 651 | }; |
652 | 652 | ||
653 | static bool s2idle_in_progress; | ||
654 | static bool s2idle_wakeup; | ||
655 | |||
656 | /* | ||
657 | * On platforms supporting the Low Power S0 Idle interface there is an ACPI | ||
658 | * device object with the PNP0D80 compatible device ID (System Power Management | ||
659 | * Controller) and a specific _DSM method under it. That method, if present, | ||
660 | * can be used to indicate to the platform that the OS is transitioning into a | ||
661 | * low-power state in which certain types of activity are not desirable or that | ||
662 | * it is leaving such a state, which allows the platform to adjust its operation | ||
663 | * mode accordingly. | ||
664 | */ | ||
665 | static const struct acpi_device_id lps0_device_ids[] = { | ||
666 | {"PNP0D80", }, | ||
667 | {"", }, | ||
668 | }; | ||
669 | |||
670 | #define ACPI_LPS0_DSM_UUID "c4eb40a0-6cd2-11e2-bcfd-0800200c9a66" | ||
671 | |||
672 | #define ACPI_LPS0_SCREEN_OFF 3 | ||
673 | #define ACPI_LPS0_SCREEN_ON 4 | ||
674 | #define ACPI_LPS0_ENTRY 5 | ||
675 | #define ACPI_LPS0_EXIT 6 | ||
676 | |||
677 | #define ACPI_S2IDLE_FUNC_MASK ((1 << ACPI_LPS0_ENTRY) | (1 << ACPI_LPS0_EXIT)) | ||
678 | |||
679 | static acpi_handle lps0_device_handle; | ||
680 | static guid_t lps0_dsm_guid; | ||
681 | static char lps0_dsm_func_mask; | ||
682 | |||
683 | static void acpi_sleep_run_lps0_dsm(unsigned int func) | ||
684 | { | ||
685 | union acpi_object *out_obj; | ||
686 | |||
687 | if (!(lps0_dsm_func_mask & (1 << func))) | ||
688 | return; | ||
689 | |||
690 | out_obj = acpi_evaluate_dsm(lps0_device_handle, &lps0_dsm_guid, 1, func, NULL); | ||
691 | ACPI_FREE(out_obj); | ||
692 | |||
693 | acpi_handle_debug(lps0_device_handle, "_DSM function %u evaluation %s\n", | ||
694 | func, out_obj ? "successful" : "failed"); | ||
695 | } | ||
696 | |||
697 | static int lps0_device_attach(struct acpi_device *adev, | ||
698 | const struct acpi_device_id *not_used) | ||
699 | { | ||
700 | union acpi_object *out_obj; | ||
701 | |||
702 | if (lps0_device_handle) | ||
703 | return 0; | ||
704 | |||
705 | if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) | ||
706 | return 0; | ||
707 | |||
708 | guid_parse(ACPI_LPS0_DSM_UUID, &lps0_dsm_guid); | ||
709 | /* Check if the _DSM is present and as expected. */ | ||
710 | out_obj = acpi_evaluate_dsm(adev->handle, &lps0_dsm_guid, 1, 0, NULL); | ||
711 | if (out_obj && out_obj->type == ACPI_TYPE_BUFFER) { | ||
712 | char bitmask = *(char *)out_obj->buffer.pointer; | ||
713 | |||
714 | if ((bitmask & ACPI_S2IDLE_FUNC_MASK) == ACPI_S2IDLE_FUNC_MASK) { | ||
715 | lps0_dsm_func_mask = bitmask; | ||
716 | lps0_device_handle = adev->handle; | ||
717 | } | ||
718 | |||
719 | acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n", | ||
720 | bitmask); | ||
721 | } else { | ||
722 | acpi_handle_debug(adev->handle, | ||
723 | "_DSM function 0 evaluation failed\n"); | ||
724 | } | ||
725 | ACPI_FREE(out_obj); | ||
726 | return 0; | ||
727 | } | ||
728 | |||
729 | static struct acpi_scan_handler lps0_handler = { | ||
730 | .ids = lps0_device_ids, | ||
731 | .attach = lps0_device_attach, | ||
732 | }; | ||
733 | |||
653 | static int acpi_freeze_begin(void) | 734 | static int acpi_freeze_begin(void) |
654 | { | 735 | { |
655 | acpi_scan_lock_acquire(); | 736 | acpi_scan_lock_acquire(); |
737 | s2idle_in_progress = true; | ||
656 | return 0; | 738 | return 0; |
657 | } | 739 | } |
658 | 740 | ||
659 | static int acpi_freeze_prepare(void) | 741 | static int acpi_freeze_prepare(void) |
660 | { | 742 | { |
661 | acpi_enable_wakeup_devices(ACPI_STATE_S0); | 743 | if (lps0_device_handle) { |
662 | acpi_enable_all_wakeup_gpes(); | 744 | acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF); |
663 | acpi_os_wait_events_complete(); | 745 | acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY); |
746 | } else { | ||
747 | /* | ||
748 | * The configuration of GPEs is changed here to avoid spurious | ||
749 | * wakeups, but that should not be necessary if this is a | ||
750 | * "low-power S0" platform and the low-power S0 _DSM is present. | ||
751 | */ | ||
752 | acpi_enable_all_wakeup_gpes(); | ||
753 | acpi_os_wait_events_complete(); | ||
754 | } | ||
664 | if (acpi_sci_irq_valid()) | 755 | if (acpi_sci_irq_valid()) |
665 | enable_irq_wake(acpi_sci_irq); | 756 | enable_irq_wake(acpi_sci_irq); |
757 | |||
666 | return 0; | 758 | return 0; |
667 | } | 759 | } |
668 | 760 | ||
761 | static void acpi_freeze_wake(void) | ||
762 | { | ||
763 | /* | ||
764 | * If IRQD_WAKEUP_ARMED is not set for the SCI at this point, it means | ||
765 | * that the SCI has triggered while suspended, so cancel the wakeup in | ||
766 | * case it has not been a wakeup event (the GPEs will be checked later). | ||
767 | */ | ||
768 | if (acpi_sci_irq_valid() && | ||
769 | !irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) { | ||
770 | pm_system_cancel_wakeup(); | ||
771 | s2idle_wakeup = true; | ||
772 | } | ||
773 | } | ||
774 | |||
775 | static void acpi_freeze_sync(void) | ||
776 | { | ||
777 | /* | ||
778 | * Process all pending events in case there are any wakeup ones. | ||
779 | * | ||
780 | * The EC driver uses the system workqueue, so that one needs to be | ||
781 | * flushed too. | ||
782 | */ | ||
783 | acpi_os_wait_events_complete(); | ||
784 | flush_scheduled_work(); | ||
785 | s2idle_wakeup = false; | ||
786 | } | ||
787 | |||
669 | static void acpi_freeze_restore(void) | 788 | static void acpi_freeze_restore(void) |
670 | { | 789 | { |
671 | acpi_disable_wakeup_devices(ACPI_STATE_S0); | ||
672 | if (acpi_sci_irq_valid()) | 790 | if (acpi_sci_irq_valid()) |
673 | disable_irq_wake(acpi_sci_irq); | 791 | disable_irq_wake(acpi_sci_irq); |
674 | acpi_enable_all_runtime_gpes(); | 792 | |
793 | if (lps0_device_handle) { | ||
794 | acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT); | ||
795 | acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON); | ||
796 | } else { | ||
797 | acpi_enable_all_runtime_gpes(); | ||
798 | } | ||
675 | } | 799 | } |
676 | 800 | ||
677 | static void acpi_freeze_end(void) | 801 | static void acpi_freeze_end(void) |
678 | { | 802 | { |
803 | s2idle_in_progress = false; | ||
679 | acpi_scan_lock_release(); | 804 | acpi_scan_lock_release(); |
680 | } | 805 | } |
681 | 806 | ||
682 | static const struct platform_freeze_ops acpi_freeze_ops = { | 807 | static const struct platform_freeze_ops acpi_freeze_ops = { |
683 | .begin = acpi_freeze_begin, | 808 | .begin = acpi_freeze_begin, |
684 | .prepare = acpi_freeze_prepare, | 809 | .prepare = acpi_freeze_prepare, |
810 | .wake = acpi_freeze_wake, | ||
811 | .sync = acpi_freeze_sync, | ||
685 | .restore = acpi_freeze_restore, | 812 | .restore = acpi_freeze_restore, |
686 | .end = acpi_freeze_end, | 813 | .end = acpi_freeze_end, |
687 | }; | 814 | }; |
@@ -696,13 +823,28 @@ static void acpi_sleep_suspend_setup(void) | |||
696 | 823 | ||
697 | suspend_set_ops(old_suspend_ordering ? | 824 | suspend_set_ops(old_suspend_ordering ? |
698 | &acpi_suspend_ops_old : &acpi_suspend_ops); | 825 | &acpi_suspend_ops_old : &acpi_suspend_ops); |
826 | |||
827 | acpi_scan_add_handler(&lps0_handler); | ||
699 | freeze_set_ops(&acpi_freeze_ops); | 828 | freeze_set_ops(&acpi_freeze_ops); |
700 | } | 829 | } |
701 | 830 | ||
702 | #else /* !CONFIG_SUSPEND */ | 831 | #else /* !CONFIG_SUSPEND */ |
832 | #define s2idle_in_progress (false) | ||
833 | #define s2idle_wakeup (false) | ||
834 | #define lps0_device_handle (NULL) | ||
703 | static inline void acpi_sleep_suspend_setup(void) {} | 835 | static inline void acpi_sleep_suspend_setup(void) {} |
704 | #endif /* !CONFIG_SUSPEND */ | 836 | #endif /* !CONFIG_SUSPEND */ |
705 | 837 | ||
838 | bool acpi_s2idle_wakeup(void) | ||
839 | { | ||
840 | return s2idle_wakeup; | ||
841 | } | ||
842 | |||
843 | bool acpi_sleep_no_ec_events(void) | ||
844 | { | ||
845 | return !s2idle_in_progress || !lps0_device_handle; | ||
846 | } | ||
847 | |||
706 | #ifdef CONFIG_PM_SLEEP | 848 | #ifdef CONFIG_PM_SLEEP |
707 | static u32 saved_bm_rld; | 849 | static u32 saved_bm_rld; |
708 | 850 | ||
diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c index f3a65a3140d3..8a01d09ac4db 100644 --- a/drivers/ata/libata-zpodd.c +++ b/drivers/ata/libata-zpodd.c | |||
@@ -174,8 +174,7 @@ void zpodd_enable_run_wake(struct ata_device *dev) | |||
174 | sdev_disable_disk_events(dev->sdev); | 174 | sdev_disable_disk_events(dev->sdev); |
175 | 175 | ||
176 | zpodd->powered_off = true; | 176 | zpodd->powered_off = true; |
177 | device_set_run_wake(&dev->tdev, true); | 177 | acpi_pm_set_device_wakeup(&dev->tdev, true); |
178 | acpi_pm_device_run_wake(&dev->tdev, true); | ||
179 | } | 178 | } |
180 | 179 | ||
181 | /* Disable runtime wake capability if it is enabled */ | 180 | /* Disable runtime wake capability if it is enabled */ |
@@ -183,10 +182,8 @@ void zpodd_disable_run_wake(struct ata_device *dev) | |||
183 | { | 182 | { |
184 | struct zpodd *zpodd = dev->zpodd; | 183 | struct zpodd *zpodd = dev->zpodd; |
185 | 184 | ||
186 | if (zpodd->powered_off) { | 185 | if (zpodd->powered_off) |
187 | acpi_pm_device_run_wake(&dev->tdev, false); | 186 | acpi_pm_set_device_wakeup(&dev->tdev, false); |
188 | device_set_run_wake(&dev->tdev, false); | ||
189 | } | ||
190 | } | 187 | } |
191 | 188 | ||
192 | /* | 189 | /* |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 6add28799f6d..c99f8730de82 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -418,6 +418,7 @@ static void pm_dev_err(struct device *dev, pm_message_t state, const char *info, | |||
418 | dev_name(dev), pm_verb(state.event), info, error); | 418 | dev_name(dev), pm_verb(state.event), info, error); |
419 | } | 419 | } |
420 | 420 | ||
421 | #ifdef CONFIG_PM_DEBUG | ||
421 | static void dpm_show_time(ktime_t starttime, pm_message_t state, | 422 | static void dpm_show_time(ktime_t starttime, pm_message_t state, |
422 | const char *info) | 423 | const char *info) |
423 | { | 424 | { |
@@ -435,6 +436,10 @@ static void dpm_show_time(ktime_t starttime, pm_message_t state, | |||
435 | info ?: "", info ? " " : "", pm_verb(state.event), | 436 | info ?: "", info ? " " : "", pm_verb(state.event), |
436 | usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC); | 437 | usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC); |
437 | } | 438 | } |
439 | #else | ||
440 | static inline void dpm_show_time(ktime_t starttime, pm_message_t state, | ||
441 | const char *info) {} | ||
442 | #endif /* CONFIG_PM_DEBUG */ | ||
438 | 443 | ||
439 | static int dpm_run_callback(pm_callback_t cb, struct device *dev, | 444 | static int dpm_run_callback(pm_callback_t cb, struct device *dev, |
440 | pm_message_t state, const char *info) | 445 | pm_message_t state, const char *info) |
@@ -1093,11 +1098,6 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a | |||
1093 | if (async_error) | 1098 | if (async_error) |
1094 | goto Complete; | 1099 | goto Complete; |
1095 | 1100 | ||
1096 | if (pm_wakeup_pending()) { | ||
1097 | async_error = -EBUSY; | ||
1098 | goto Complete; | ||
1099 | } | ||
1100 | |||
1101 | if (dev->power.syscore || dev->power.direct_complete) | 1101 | if (dev->power.syscore || dev->power.direct_complete) |
1102 | goto Complete; | 1102 | goto Complete; |
1103 | 1103 | ||
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 994bbf8b1476..144e6d8fafc8 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c | |||
@@ -28,8 +28,8 @@ bool events_check_enabled __read_mostly; | |||
28 | /* First wakeup IRQ seen by the kernel in the last cycle. */ | 28 | /* First wakeup IRQ seen by the kernel in the last cycle. */ |
29 | unsigned int pm_wakeup_irq __read_mostly; | 29 | unsigned int pm_wakeup_irq __read_mostly; |
30 | 30 | ||
31 | /* If set and the system is suspending, terminate the suspend. */ | 31 | /* If greater than 0 and the system is suspending, terminate the suspend. */ |
32 | static bool pm_abort_suspend __read_mostly; | 32 | static atomic_t pm_abort_suspend __read_mostly; |
33 | 33 | ||
34 | /* | 34 | /* |
35 | * Combined counters of registered wakeup events and wakeup events in progress. | 35 | * Combined counters of registered wakeup events and wakeup events in progress. |
@@ -857,20 +857,26 @@ bool pm_wakeup_pending(void) | |||
857 | pm_print_active_wakeup_sources(); | 857 | pm_print_active_wakeup_sources(); |
858 | } | 858 | } |
859 | 859 | ||
860 | return ret || pm_abort_suspend; | 860 | return ret || atomic_read(&pm_abort_suspend) > 0; |
861 | } | 861 | } |
862 | 862 | ||
863 | void pm_system_wakeup(void) | 863 | void pm_system_wakeup(void) |
864 | { | 864 | { |
865 | pm_abort_suspend = true; | 865 | atomic_inc(&pm_abort_suspend); |
866 | freeze_wake(); | 866 | freeze_wake(); |
867 | } | 867 | } |
868 | EXPORT_SYMBOL_GPL(pm_system_wakeup); | 868 | EXPORT_SYMBOL_GPL(pm_system_wakeup); |
869 | 869 | ||
870 | void pm_wakeup_clear(void) | 870 | void pm_system_cancel_wakeup(void) |
871 | { | ||
872 | atomic_dec(&pm_abort_suspend); | ||
873 | } | ||
874 | |||
875 | void pm_wakeup_clear(bool reset) | ||
871 | { | 876 | { |
872 | pm_abort_suspend = false; | ||
873 | pm_wakeup_irq = 0; | 877 | pm_wakeup_irq = 0; |
878 | if (reset) | ||
879 | atomic_set(&pm_abort_suspend, 0); | ||
874 | } | 880 | } |
875 | 881 | ||
876 | void pm_system_irq_wakeup(unsigned int irq_number) | 882 | void pm_system_irq_wakeup(unsigned int irq_number) |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 47070cff508c..e70c1c7ba1bf 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -394,29 +394,26 @@ bool pciehp_is_native(struct pci_dev *pdev) | |||
394 | 394 | ||
395 | /** | 395 | /** |
396 | * pci_acpi_wake_bus - Root bus wakeup notification fork function. | 396 | * pci_acpi_wake_bus - Root bus wakeup notification fork function. |
397 | * @work: Work item to handle. | 397 | * @context: Device wakeup context. |
398 | */ | 398 | */ |
399 | static void pci_acpi_wake_bus(struct work_struct *work) | 399 | static void pci_acpi_wake_bus(struct acpi_device_wakeup_context *context) |
400 | { | 400 | { |
401 | struct acpi_device *adev; | 401 | struct acpi_device *adev; |
402 | struct acpi_pci_root *root; | 402 | struct acpi_pci_root *root; |
403 | 403 | ||
404 | adev = container_of(work, struct acpi_device, wakeup.context.work); | 404 | adev = container_of(context, struct acpi_device, wakeup.context); |
405 | root = acpi_driver_data(adev); | 405 | root = acpi_driver_data(adev); |
406 | pci_pme_wakeup_bus(root->bus); | 406 | pci_pme_wakeup_bus(root->bus); |
407 | } | 407 | } |
408 | 408 | ||
409 | /** | 409 | /** |
410 | * pci_acpi_wake_dev - PCI device wakeup notification work function. | 410 | * pci_acpi_wake_dev - PCI device wakeup notification work function. |
411 | * @handle: ACPI handle of a device the notification is for. | 411 | * @context: Device wakeup context. |
412 | * @work: Work item to handle. | ||
413 | */ | 412 | */ |
414 | static void pci_acpi_wake_dev(struct work_struct *work) | 413 | static void pci_acpi_wake_dev(struct acpi_device_wakeup_context *context) |
415 | { | 414 | { |
416 | struct acpi_device_wakeup_context *context; | ||
417 | struct pci_dev *pci_dev; | 415 | struct pci_dev *pci_dev; |
418 | 416 | ||
419 | context = container_of(work, struct acpi_device_wakeup_context, work); | ||
420 | pci_dev = to_pci_dev(context->dev); | 417 | pci_dev = to_pci_dev(context->dev); |
421 | 418 | ||
422 | if (pci_dev->pme_poll) | 419 | if (pci_dev->pme_poll) |
@@ -424,7 +421,7 @@ static void pci_acpi_wake_dev(struct work_struct *work) | |||
424 | 421 | ||
425 | if (pci_dev->current_state == PCI_D3cold) { | 422 | if (pci_dev->current_state == PCI_D3cold) { |
426 | pci_wakeup_event(pci_dev); | 423 | pci_wakeup_event(pci_dev); |
427 | pm_runtime_resume(&pci_dev->dev); | 424 | pm_request_resume(&pci_dev->dev); |
428 | return; | 425 | return; |
429 | } | 426 | } |
430 | 427 | ||
@@ -433,7 +430,7 @@ static void pci_acpi_wake_dev(struct work_struct *work) | |||
433 | pci_check_pme_status(pci_dev); | 430 | pci_check_pme_status(pci_dev); |
434 | 431 | ||
435 | pci_wakeup_event(pci_dev); | 432 | pci_wakeup_event(pci_dev); |
436 | pm_runtime_resume(&pci_dev->dev); | 433 | pm_request_resume(&pci_dev->dev); |
437 | 434 | ||
438 | pci_pme_wakeup_bus(pci_dev->subordinate); | 435 | pci_pme_wakeup_bus(pci_dev->subordinate); |
439 | } | 436 | } |
@@ -572,67 +569,29 @@ static pci_power_t acpi_pci_get_power_state(struct pci_dev *dev) | |||
572 | return state_conv[state]; | 569 | return state_conv[state]; |
573 | } | 570 | } |
574 | 571 | ||
575 | static bool acpi_pci_can_wakeup(struct pci_dev *dev) | 572 | static int acpi_pci_propagate_wakeup(struct pci_bus *bus, bool enable) |
576 | { | ||
577 | struct acpi_device *adev = ACPI_COMPANION(&dev->dev); | ||
578 | return adev ? acpi_device_can_wakeup(adev) : false; | ||
579 | } | ||
580 | |||
581 | static void acpi_pci_propagate_wakeup_enable(struct pci_bus *bus, bool enable) | ||
582 | { | ||
583 | while (bus->parent) { | ||
584 | if (!acpi_pm_device_sleep_wake(&bus->self->dev, enable)) | ||
585 | return; | ||
586 | bus = bus->parent; | ||
587 | } | ||
588 | |||
589 | /* We have reached the root bus. */ | ||
590 | if (bus->bridge) | ||
591 | acpi_pm_device_sleep_wake(bus->bridge, enable); | ||
592 | } | ||
593 | |||
594 | static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable) | ||
595 | { | ||
596 | if (acpi_pci_can_wakeup(dev)) | ||
597 | return acpi_pm_device_sleep_wake(&dev->dev, enable); | ||
598 | |||
599 | acpi_pci_propagate_wakeup_enable(dev->bus, enable); | ||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable) | ||
604 | { | 573 | { |
605 | while (bus->parent) { | 574 | while (bus->parent) { |
606 | struct pci_dev *bridge = bus->self; | 575 | if (acpi_pm_device_can_wakeup(&bus->self->dev)) |
576 | return acpi_pm_set_device_wakeup(&bus->self->dev, enable); | ||
607 | 577 | ||
608 | if (bridge->pme_interrupt) | ||
609 | return; | ||
610 | if (!acpi_pm_device_run_wake(&bridge->dev, enable)) | ||
611 | return; | ||
612 | bus = bus->parent; | 578 | bus = bus->parent; |
613 | } | 579 | } |
614 | 580 | ||
615 | /* We have reached the root bus. */ | 581 | /* We have reached the root bus. */ |
616 | if (bus->bridge) | 582 | if (bus->bridge) { |
617 | acpi_pm_device_run_wake(bus->bridge, enable); | 583 | if (acpi_pm_device_can_wakeup(bus->bridge)) |
584 | return acpi_pm_set_device_wakeup(bus->bridge, enable); | ||
585 | } | ||
586 | return 0; | ||
618 | } | 587 | } |
619 | 588 | ||
620 | static int acpi_pci_run_wake(struct pci_dev *dev, bool enable) | 589 | static int acpi_pci_wakeup(struct pci_dev *dev, bool enable) |
621 | { | 590 | { |
622 | /* | 591 | if (acpi_pm_device_can_wakeup(&dev->dev)) |
623 | * Per PCI Express Base Specification Revision 2.0 section | 592 | return acpi_pm_set_device_wakeup(&dev->dev, enable); |
624 | * 5.3.3.2 Link Wakeup, platform support is needed for D3cold | ||
625 | * waking up to power on the main link even if there is PME | ||
626 | * support for D3cold | ||
627 | */ | ||
628 | if (dev->pme_interrupt && !dev->runtime_d3cold) | ||
629 | return 0; | ||
630 | |||
631 | if (!acpi_pm_device_run_wake(&dev->dev, enable)) | ||
632 | return 0; | ||
633 | 593 | ||
634 | acpi_pci_propagate_run_wake(dev->bus, enable); | 594 | return acpi_pci_propagate_wakeup(dev->bus, enable); |
635 | return 0; | ||
636 | } | 595 | } |
637 | 596 | ||
638 | static bool acpi_pci_need_resume(struct pci_dev *dev) | 597 | static bool acpi_pci_need_resume(struct pci_dev *dev) |
@@ -656,8 +615,7 @@ static const struct pci_platform_pm_ops acpi_pci_platform_pm = { | |||
656 | .set_state = acpi_pci_set_power_state, | 615 | .set_state = acpi_pci_set_power_state, |
657 | .get_state = acpi_pci_get_power_state, | 616 | .get_state = acpi_pci_get_power_state, |
658 | .choose_state = acpi_pci_choose_state, | 617 | .choose_state = acpi_pci_choose_state, |
659 | .sleep_wake = acpi_pci_sleep_wake, | 618 | .set_wakeup = acpi_pci_wakeup, |
660 | .run_wake = acpi_pci_run_wake, | ||
661 | .need_resume = acpi_pci_need_resume, | 619 | .need_resume = acpi_pci_need_resume, |
662 | }; | 620 | }; |
663 | 621 | ||
@@ -780,9 +738,7 @@ static void pci_acpi_setup(struct device *dev) | |||
780 | return; | 738 | return; |
781 | 739 | ||
782 | device_set_wakeup_capable(dev, true); | 740 | device_set_wakeup_capable(dev, true); |
783 | acpi_pci_sleep_wake(pci_dev, false); | 741 | acpi_pci_wakeup(pci_dev, false); |
784 | if (adev->wakeup.flags.run_wake) | ||
785 | device_set_run_wake(dev, true); | ||
786 | } | 742 | } |
787 | 743 | ||
788 | static void pci_acpi_cleanup(struct device *dev) | 744 | static void pci_acpi_cleanup(struct device *dev) |
@@ -793,10 +749,8 @@ static void pci_acpi_cleanup(struct device *dev) | |||
793 | return; | 749 | return; |
794 | 750 | ||
795 | pci_acpi_remove_pm_notifier(adev); | 751 | pci_acpi_remove_pm_notifier(adev); |
796 | if (adev->wakeup.flags.valid) { | 752 | if (adev->wakeup.flags.valid) |
797 | device_set_wakeup_capable(dev, false); | 753 | device_set_wakeup_capable(dev, false); |
798 | device_set_run_wake(dev, false); | ||
799 | } | ||
800 | } | 754 | } |
801 | 755 | ||
802 | static bool pci_acpi_bus_match(struct device *dev) | 756 | static bool pci_acpi_bus_match(struct device *dev) |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 192e7b681b96..ffe7d54d9328 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -1216,7 +1216,7 @@ static int pci_pm_runtime_resume(struct device *dev) | |||
1216 | 1216 | ||
1217 | pci_restore_standard_config(pci_dev); | 1217 | pci_restore_standard_config(pci_dev); |
1218 | pci_fixup_device(pci_fixup_resume_early, pci_dev); | 1218 | pci_fixup_device(pci_fixup_resume_early, pci_dev); |
1219 | __pci_enable_wake(pci_dev, PCI_D0, true, false); | 1219 | pci_enable_wake(pci_dev, PCI_D0, false); |
1220 | pci_fixup_device(pci_fixup_resume, pci_dev); | 1220 | pci_fixup_device(pci_fixup_resume, pci_dev); |
1221 | 1221 | ||
1222 | rc = pm->runtime_resume(dev); | 1222 | rc = pm->runtime_resume(dev); |
diff --git a/drivers/pci/pci-mid.c b/drivers/pci/pci-mid.c index 1c4af7227bca..a4ac940c7696 100644 --- a/drivers/pci/pci-mid.c +++ b/drivers/pci/pci-mid.c | |||
@@ -39,12 +39,7 @@ static pci_power_t mid_pci_choose_state(struct pci_dev *pdev) | |||
39 | return PCI_D3hot; | 39 | return PCI_D3hot; |
40 | } | 40 | } |
41 | 41 | ||
42 | static int mid_pci_sleep_wake(struct pci_dev *dev, bool enable) | 42 | static int mid_pci_wakeup(struct pci_dev *dev, bool enable) |
43 | { | ||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | static int mid_pci_run_wake(struct pci_dev *dev, bool enable) | ||
48 | { | 43 | { |
49 | return 0; | 44 | return 0; |
50 | } | 45 | } |
@@ -59,8 +54,7 @@ static const struct pci_platform_pm_ops mid_pci_platform_pm = { | |||
59 | .set_state = mid_pci_set_power_state, | 54 | .set_state = mid_pci_set_power_state, |
60 | .get_state = mid_pci_get_power_state, | 55 | .get_state = mid_pci_get_power_state, |
61 | .choose_state = mid_pci_choose_state, | 56 | .choose_state = mid_pci_choose_state, |
62 | .sleep_wake = mid_pci_sleep_wake, | 57 | .set_wakeup = mid_pci_wakeup, |
63 | .run_wake = mid_pci_run_wake, | ||
64 | .need_resume = mid_pci_need_resume, | 58 | .need_resume = mid_pci_need_resume, |
65 | }; | 59 | }; |
66 | 60 | ||
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 563901cd9c06..0b5302a9fdae 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -574,8 +574,7 @@ static const struct pci_platform_pm_ops *pci_platform_pm; | |||
574 | int pci_set_platform_pm(const struct pci_platform_pm_ops *ops) | 574 | int pci_set_platform_pm(const struct pci_platform_pm_ops *ops) |
575 | { | 575 | { |
576 | if (!ops->is_manageable || !ops->set_state || !ops->get_state || | 576 | if (!ops->is_manageable || !ops->set_state || !ops->get_state || |
577 | !ops->choose_state || !ops->sleep_wake || !ops->run_wake || | 577 | !ops->choose_state || !ops->set_wakeup || !ops->need_resume) |
578 | !ops->need_resume) | ||
579 | return -EINVAL; | 578 | return -EINVAL; |
580 | pci_platform_pm = ops; | 579 | pci_platform_pm = ops; |
581 | return 0; | 580 | return 0; |
@@ -603,16 +602,10 @@ static inline pci_power_t platform_pci_choose_state(struct pci_dev *dev) | |||
603 | pci_platform_pm->choose_state(dev) : PCI_POWER_ERROR; | 602 | pci_platform_pm->choose_state(dev) : PCI_POWER_ERROR; |
604 | } | 603 | } |
605 | 604 | ||
606 | static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable) | 605 | static inline int platform_pci_set_wakeup(struct pci_dev *dev, bool enable) |
607 | { | 606 | { |
608 | return pci_platform_pm ? | 607 | return pci_platform_pm ? |
609 | pci_platform_pm->sleep_wake(dev, enable) : -ENODEV; | 608 | pci_platform_pm->set_wakeup(dev, enable) : -ENODEV; |
610 | } | ||
611 | |||
612 | static inline int platform_pci_run_wake(struct pci_dev *dev, bool enable) | ||
613 | { | ||
614 | return pci_platform_pm ? | ||
615 | pci_platform_pm->run_wake(dev, enable) : -ENODEV; | ||
616 | } | 609 | } |
617 | 610 | ||
618 | static inline bool platform_pci_need_resume(struct pci_dev *dev) | 611 | static inline bool platform_pci_need_resume(struct pci_dev *dev) |
@@ -1805,6 +1798,23 @@ static void __pci_pme_active(struct pci_dev *dev, bool enable) | |||
1805 | pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); | 1798 | pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); |
1806 | } | 1799 | } |
1807 | 1800 | ||
1801 | static void pci_pme_restore(struct pci_dev *dev) | ||
1802 | { | ||
1803 | u16 pmcsr; | ||
1804 | |||
1805 | if (!dev->pme_support) | ||
1806 | return; | ||
1807 | |||
1808 | pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); | ||
1809 | if (dev->wakeup_prepared) { | ||
1810 | pmcsr |= PCI_PM_CTRL_PME_ENABLE; | ||
1811 | } else { | ||
1812 | pmcsr &= ~PCI_PM_CTRL_PME_ENABLE; | ||
1813 | pmcsr |= PCI_PM_CTRL_PME_STATUS; | ||
1814 | } | ||
1815 | pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); | ||
1816 | } | ||
1817 | |||
1808 | /** | 1818 | /** |
1809 | * pci_pme_active - enable or disable PCI device's PME# function | 1819 | * pci_pme_active - enable or disable PCI device's PME# function |
1810 | * @dev: PCI device to handle. | 1820 | * @dev: PCI device to handle. |
@@ -1872,10 +1882,9 @@ void pci_pme_active(struct pci_dev *dev, bool enable) | |||
1872 | EXPORT_SYMBOL(pci_pme_active); | 1882 | EXPORT_SYMBOL(pci_pme_active); |
1873 | 1883 | ||
1874 | /** | 1884 | /** |
1875 | * __pci_enable_wake - enable PCI device as wakeup event source | 1885 | * pci_enable_wake - enable PCI device as wakeup event source |
1876 | * @dev: PCI device affected | 1886 | * @dev: PCI device affected |
1877 | * @state: PCI state from which device will issue wakeup events | 1887 | * @state: PCI state from which device will issue wakeup events |
1878 | * @runtime: True if the events are to be generated at run time | ||
1879 | * @enable: True to enable event generation; false to disable | 1888 | * @enable: True to enable event generation; false to disable |
1880 | * | 1889 | * |
1881 | * This enables the device as a wakeup event source, or disables it. | 1890 | * This enables the device as a wakeup event source, or disables it. |
@@ -1891,17 +1900,18 @@ EXPORT_SYMBOL(pci_pme_active); | |||
1891 | * Error code depending on the platform is returned if both the platform and | 1900 | * Error code depending on the platform is returned if both the platform and |
1892 | * the native mechanism fail to enable the generation of wake-up events | 1901 | * the native mechanism fail to enable the generation of wake-up events |
1893 | */ | 1902 | */ |
1894 | int __pci_enable_wake(struct pci_dev *dev, pci_power_t state, | 1903 | int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable) |
1895 | bool runtime, bool enable) | ||
1896 | { | 1904 | { |
1897 | int ret = 0; | 1905 | int ret = 0; |
1898 | 1906 | ||
1899 | if (enable && !runtime && !device_may_wakeup(&dev->dev)) | 1907 | /* |
1900 | return -EINVAL; | 1908 | * Don't do the same thing twice in a row for one device, but restore |
1901 | 1909 | * PME Enable in case it has been updated by config space restoration. | |
1902 | /* Don't do the same thing twice in a row for one device. */ | 1910 | */ |
1903 | if (!!enable == !!dev->wakeup_prepared) | 1911 | if (!!enable == !!dev->wakeup_prepared) { |
1912 | pci_pme_restore(dev); | ||
1904 | return 0; | 1913 | return 0; |
1914 | } | ||
1905 | 1915 | ||
1906 | /* | 1916 | /* |
1907 | * According to "PCI System Architecture" 4th ed. by Tom Shanley & Don | 1917 | * According to "PCI System Architecture" 4th ed. by Tom Shanley & Don |
@@ -1916,24 +1926,20 @@ int __pci_enable_wake(struct pci_dev *dev, pci_power_t state, | |||
1916 | pci_pme_active(dev, true); | 1926 | pci_pme_active(dev, true); |
1917 | else | 1927 | else |
1918 | ret = 1; | 1928 | ret = 1; |
1919 | error = runtime ? platform_pci_run_wake(dev, true) : | 1929 | error = platform_pci_set_wakeup(dev, true); |
1920 | platform_pci_sleep_wake(dev, true); | ||
1921 | if (ret) | 1930 | if (ret) |
1922 | ret = error; | 1931 | ret = error; |
1923 | if (!ret) | 1932 | if (!ret) |
1924 | dev->wakeup_prepared = true; | 1933 | dev->wakeup_prepared = true; |
1925 | } else { | 1934 | } else { |
1926 | if (runtime) | 1935 | platform_pci_set_wakeup(dev, false); |
1927 | platform_pci_run_wake(dev, false); | ||
1928 | else | ||
1929 | platform_pci_sleep_wake(dev, false); | ||
1930 | pci_pme_active(dev, false); | 1936 | pci_pme_active(dev, false); |
1931 | dev->wakeup_prepared = false; | 1937 | dev->wakeup_prepared = false; |
1932 | } | 1938 | } |
1933 | 1939 | ||
1934 | return ret; | 1940 | return ret; |
1935 | } | 1941 | } |
1936 | EXPORT_SYMBOL(__pci_enable_wake); | 1942 | EXPORT_SYMBOL(pci_enable_wake); |
1937 | 1943 | ||
1938 | /** | 1944 | /** |
1939 | * pci_wake_from_d3 - enable/disable device to wake up from D3_hot or D3_cold | 1945 | * pci_wake_from_d3 - enable/disable device to wake up from D3_hot or D3_cold |
@@ -2075,12 +2081,12 @@ int pci_finish_runtime_suspend(struct pci_dev *dev) | |||
2075 | 2081 | ||
2076 | dev->runtime_d3cold = target_state == PCI_D3cold; | 2082 | dev->runtime_d3cold = target_state == PCI_D3cold; |
2077 | 2083 | ||
2078 | __pci_enable_wake(dev, target_state, true, pci_dev_run_wake(dev)); | 2084 | pci_enable_wake(dev, target_state, pci_dev_run_wake(dev)); |
2079 | 2085 | ||
2080 | error = pci_set_power_state(dev, target_state); | 2086 | error = pci_set_power_state(dev, target_state); |
2081 | 2087 | ||
2082 | if (error) { | 2088 | if (error) { |
2083 | __pci_enable_wake(dev, target_state, true, false); | 2089 | pci_enable_wake(dev, target_state, false); |
2084 | dev->runtime_d3cold = false; | 2090 | dev->runtime_d3cold = false; |
2085 | } | 2091 | } |
2086 | 2092 | ||
@@ -2099,7 +2105,7 @@ bool pci_dev_run_wake(struct pci_dev *dev) | |||
2099 | { | 2105 | { |
2100 | struct pci_bus *bus = dev->bus; | 2106 | struct pci_bus *bus = dev->bus; |
2101 | 2107 | ||
2102 | if (device_run_wake(&dev->dev)) | 2108 | if (device_can_wakeup(&dev->dev)) |
2103 | return true; | 2109 | return true; |
2104 | 2110 | ||
2105 | if (!dev->pme_support) | 2111 | if (!dev->pme_support) |
@@ -2112,7 +2118,7 @@ bool pci_dev_run_wake(struct pci_dev *dev) | |||
2112 | while (bus->parent) { | 2118 | while (bus->parent) { |
2113 | struct pci_dev *bridge = bus->self; | 2119 | struct pci_dev *bridge = bus->self; |
2114 | 2120 | ||
2115 | if (device_run_wake(&bridge->dev)) | 2121 | if (device_can_wakeup(&bridge->dev)) |
2116 | return true; | 2122 | return true; |
2117 | 2123 | ||
2118 | bus = bus->parent; | 2124 | bus = bus->parent; |
@@ -2120,7 +2126,7 @@ bool pci_dev_run_wake(struct pci_dev *dev) | |||
2120 | 2126 | ||
2121 | /* We have reached the root bus. */ | 2127 | /* We have reached the root bus. */ |
2122 | if (bus->bridge) | 2128 | if (bus->bridge) |
2123 | return device_run_wake(bus->bridge); | 2129 | return device_can_wakeup(bus->bridge); |
2124 | 2130 | ||
2125 | return false; | 2131 | return false; |
2126 | } | 2132 | } |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index f8113e5b9812..240b2c0fed4b 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -47,11 +47,7 @@ int pci_probe_reset_function(struct pci_dev *dev); | |||
47 | * platform; to be used during system-wide transitions from a | 47 | * platform; to be used during system-wide transitions from a |
48 | * sleeping state to the working state and vice versa | 48 | * sleeping state to the working state and vice versa |
49 | * | 49 | * |
50 | * @sleep_wake: enables/disables the system wake up capability of given device | 50 | * @set_wakeup: enables/disables wakeup capability for the device |
51 | * | ||
52 | * @run_wake: enables/disables the platform to generate run-time wake-up events | ||
53 | * for given device (the device's wake-up capability has to be | ||
54 | * enabled by @sleep_wake for this feature to work) | ||
55 | * | 51 | * |
56 | * @need_resume: returns 'true' if the given device (which is currently | 52 | * @need_resume: returns 'true' if the given device (which is currently |
57 | * suspended) needs to be resumed to be configured for system | 53 | * suspended) needs to be resumed to be configured for system |
@@ -65,8 +61,7 @@ struct pci_platform_pm_ops { | |||
65 | int (*set_state)(struct pci_dev *dev, pci_power_t state); | 61 | int (*set_state)(struct pci_dev *dev, pci_power_t state); |
66 | pci_power_t (*get_state)(struct pci_dev *dev); | 62 | pci_power_t (*get_state)(struct pci_dev *dev); |
67 | pci_power_t (*choose_state)(struct pci_dev *dev); | 63 | pci_power_t (*choose_state)(struct pci_dev *dev); |
68 | int (*sleep_wake)(struct pci_dev *dev, bool enable); | 64 | int (*set_wakeup)(struct pci_dev *dev, bool enable); |
69 | int (*run_wake)(struct pci_dev *dev, bool enable); | ||
70 | bool (*need_resume)(struct pci_dev *dev); | 65 | bool (*need_resume)(struct pci_dev *dev); |
71 | }; | 66 | }; |
72 | 67 | ||
diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c index 2dd1c68e6de8..80e58d25006d 100644 --- a/drivers/pci/pcie/pme.c +++ b/drivers/pci/pcie/pme.c | |||
@@ -294,31 +294,29 @@ static irqreturn_t pcie_pme_irq(int irq, void *context) | |||
294 | } | 294 | } |
295 | 295 | ||
296 | /** | 296 | /** |
297 | * pcie_pme_set_native - Set the PME interrupt flag for given device. | 297 | * pcie_pme_can_wakeup - Set the wakeup capability flag. |
298 | * @dev: PCI device to handle. | 298 | * @dev: PCI device to handle. |
299 | * @ign: Ignored. | 299 | * @ign: Ignored. |
300 | */ | 300 | */ |
301 | static int pcie_pme_set_native(struct pci_dev *dev, void *ign) | 301 | static int pcie_pme_can_wakeup(struct pci_dev *dev, void *ign) |
302 | { | 302 | { |
303 | device_set_run_wake(&dev->dev, true); | 303 | device_set_wakeup_capable(&dev->dev, true); |
304 | dev->pme_interrupt = true; | ||
305 | return 0; | 304 | return 0; |
306 | } | 305 | } |
307 | 306 | ||
308 | /** | 307 | /** |
309 | * pcie_pme_mark_devices - Set the PME interrupt flag for devices below a port. | 308 | * pcie_pme_mark_devices - Set the wakeup flag for devices below a port. |
310 | * @port: PCIe root port or event collector to handle. | 309 | * @port: PCIe root port or event collector to handle. |
311 | * | 310 | * |
312 | * For each device below given root port, including the port itself (or for each | 311 | * For each device below given root port, including the port itself (or for each |
313 | * root complex integrated endpoint if @port is a root complex event collector) | 312 | * root complex integrated endpoint if @port is a root complex event collector) |
314 | * set the flag indicating that it can signal run-time wake-up events via PCIe | 313 | * set the flag indicating that it can signal run-time wake-up events. |
315 | * PME interrupts. | ||
316 | */ | 314 | */ |
317 | static void pcie_pme_mark_devices(struct pci_dev *port) | 315 | static void pcie_pme_mark_devices(struct pci_dev *port) |
318 | { | 316 | { |
319 | pcie_pme_set_native(port, NULL); | 317 | pcie_pme_can_wakeup(port, NULL); |
320 | if (port->subordinate) | 318 | if (port->subordinate) |
321 | pci_walk_bus(port->subordinate, pcie_pme_set_native, NULL); | 319 | pci_walk_bus(port->subordinate, pcie_pme_can_wakeup, NULL); |
322 | } | 320 | } |
323 | 321 | ||
324 | /** | 322 | /** |
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 8489020ecf44..a3ccc3c795a5 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -794,6 +794,25 @@ config INTEL_CHT_INT33FE | |||
794 | This driver instantiates i2c-clients for these, so that standard | 794 | This driver instantiates i2c-clients for these, so that standard |
795 | i2c drivers for these chips can bind to the them. | 795 | i2c drivers for these chips can bind to the them. |
796 | 796 | ||
797 | config INTEL_INT0002_VGPIO | ||
798 | tristate "Intel ACPI INT0002 Virtual GPIO driver" | ||
799 | depends on GPIOLIB && ACPI | ||
800 | select GPIOLIB_IRQCHIP | ||
801 | ---help--- | ||
802 | Some peripherals on Bay Trail and Cherry Trail platforms signal a | ||
803 | Power Management Event (PME) to the Power Management Controller (PMC) | ||
804 | to wakeup the system. When this happens software needs to explicitly | ||
805 | clear the PME bus 0 status bit in the GPE0a_STS register to avoid an | ||
806 | IRQ storm on IRQ 9. | ||
807 | |||
808 | This is modelled in ACPI through the INT0002 ACPI device, which is | ||
809 | called a "Virtual GPIO controller" in ACPI because it defines the | ||
810 | event handler to call when the PME triggers through _AEI and _L02 | ||
811 | methods as would be done for a real GPIO interrupt in ACPI. | ||
812 | |||
813 | To compile this driver as a module, choose M here: the module will | ||
814 | be called intel_int0002_vgpio. | ||
815 | |||
797 | config INTEL_HID_EVENT | 816 | config INTEL_HID_EVENT |
798 | tristate "INTEL HID Event" | 817 | tristate "INTEL HID Event" |
799 | depends on ACPI | 818 | depends on ACPI |
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 182a3ed6605a..ab22ce77fb66 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile | |||
@@ -46,6 +46,7 @@ obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o | |||
46 | obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o | 46 | obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o |
47 | obj-$(CONFIG_TOSHIBA_WMI) += toshiba-wmi.o | 47 | obj-$(CONFIG_TOSHIBA_WMI) += toshiba-wmi.o |
48 | obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o | 48 | obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o |
49 | obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o | ||
49 | obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o | 50 | obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o |
50 | obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o | 51 | obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o |
51 | obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o | 52 | obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o |
diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index 63ba2cbd04c2..8519e0f97bdd 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/input/sparse-keymap.h> | 24 | #include <linux/input/sparse-keymap.h> |
25 | #include <linux/acpi.h> | 25 | #include <linux/acpi.h> |
26 | #include <linux/suspend.h> | ||
26 | #include <acpi/acpi_bus.h> | 27 | #include <acpi/acpi_bus.h> |
27 | 28 | ||
28 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
@@ -75,6 +76,7 @@ static const struct key_entry intel_array_keymap[] = { | |||
75 | struct intel_hid_priv { | 76 | struct intel_hid_priv { |
76 | struct input_dev *input_dev; | 77 | struct input_dev *input_dev; |
77 | struct input_dev *array; | 78 | struct input_dev *array; |
79 | bool wakeup_mode; | ||
78 | }; | 80 | }; |
79 | 81 | ||
80 | static int intel_hid_set_enable(struct device *device, bool enable) | 82 | static int intel_hid_set_enable(struct device *device, bool enable) |
@@ -116,23 +118,37 @@ static void intel_button_array_enable(struct device *device, bool enable) | |||
116 | dev_warn(device, "failed to set button capability\n"); | 118 | dev_warn(device, "failed to set button capability\n"); |
117 | } | 119 | } |
118 | 120 | ||
119 | static int intel_hid_pl_suspend_handler(struct device *device) | 121 | static int intel_hid_pm_prepare(struct device *device) |
120 | { | 122 | { |
121 | intel_hid_set_enable(device, false); | 123 | struct intel_hid_priv *priv = dev_get_drvdata(device); |
122 | intel_button_array_enable(device, false); | 124 | |
125 | priv->wakeup_mode = true; | ||
126 | return 0; | ||
127 | } | ||
123 | 128 | ||
129 | static int intel_hid_pl_suspend_handler(struct device *device) | ||
130 | { | ||
131 | if (pm_suspend_via_firmware()) { | ||
132 | intel_hid_set_enable(device, false); | ||
133 | intel_button_array_enable(device, false); | ||
134 | } | ||
124 | return 0; | 135 | return 0; |
125 | } | 136 | } |
126 | 137 | ||
127 | static int intel_hid_pl_resume_handler(struct device *device) | 138 | static int intel_hid_pl_resume_handler(struct device *device) |
128 | { | 139 | { |
129 | intel_hid_set_enable(device, true); | 140 | struct intel_hid_priv *priv = dev_get_drvdata(device); |
130 | intel_button_array_enable(device, true); | ||
131 | 141 | ||
142 | priv->wakeup_mode = false; | ||
143 | if (pm_resume_via_firmware()) { | ||
144 | intel_hid_set_enable(device, true); | ||
145 | intel_button_array_enable(device, true); | ||
146 | } | ||
132 | return 0; | 147 | return 0; |
133 | } | 148 | } |
134 | 149 | ||
135 | static const struct dev_pm_ops intel_hid_pl_pm_ops = { | 150 | static const struct dev_pm_ops intel_hid_pl_pm_ops = { |
151 | .prepare = intel_hid_pm_prepare, | ||
136 | .freeze = intel_hid_pl_suspend_handler, | 152 | .freeze = intel_hid_pl_suspend_handler, |
137 | .thaw = intel_hid_pl_resume_handler, | 153 | .thaw = intel_hid_pl_resume_handler, |
138 | .restore = intel_hid_pl_resume_handler, | 154 | .restore = intel_hid_pl_resume_handler, |
@@ -186,6 +202,19 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) | |||
186 | unsigned long long ev_index; | 202 | unsigned long long ev_index; |
187 | acpi_status status; | 203 | acpi_status status; |
188 | 204 | ||
205 | if (priv->wakeup_mode) { | ||
206 | /* Wake up on 5-button array events only. */ | ||
207 | if (event == 0xc0 || !priv->array) | ||
208 | return; | ||
209 | |||
210 | if (sparse_keymap_entry_from_scancode(priv->array, event)) | ||
211 | pm_wakeup_hard_event(&device->dev); | ||
212 | else | ||
213 | dev_info(&device->dev, "unknown event 0x%x\n", event); | ||
214 | |||
215 | return; | ||
216 | } | ||
217 | |||
189 | /* 0xC0 is for HID events, other values are for 5 button array */ | 218 | /* 0xC0 is for HID events, other values are for 5 button array */ |
190 | if (event != 0xc0) { | 219 | if (event != 0xc0) { |
191 | if (!priv->array || | 220 | if (!priv->array || |
@@ -270,6 +299,7 @@ static int intel_hid_probe(struct platform_device *device) | |||
270 | "failed to enable HID power button\n"); | 299 | "failed to enable HID power button\n"); |
271 | } | 300 | } |
272 | 301 | ||
302 | device_init_wakeup(&device->dev, true); | ||
273 | return 0; | 303 | return 0; |
274 | 304 | ||
275 | err_remove_notify: | 305 | err_remove_notify: |
diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c index c2035e121ac2..61f106377661 100644 --- a/drivers/platform/x86/intel-vbtn.c +++ b/drivers/platform/x86/intel-vbtn.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/input/sparse-keymap.h> | 24 | #include <linux/input/sparse-keymap.h> |
25 | #include <linux/acpi.h> | 25 | #include <linux/acpi.h> |
26 | #include <linux/suspend.h> | ||
26 | #include <acpi/acpi_bus.h> | 27 | #include <acpi/acpi_bus.h> |
27 | 28 | ||
28 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
@@ -46,6 +47,7 @@ static const struct key_entry intel_vbtn_keymap[] = { | |||
46 | 47 | ||
47 | struct intel_vbtn_priv { | 48 | struct intel_vbtn_priv { |
48 | struct input_dev *input_dev; | 49 | struct input_dev *input_dev; |
50 | bool wakeup_mode; | ||
49 | }; | 51 | }; |
50 | 52 | ||
51 | static int intel_vbtn_input_setup(struct platform_device *device) | 53 | static int intel_vbtn_input_setup(struct platform_device *device) |
@@ -73,9 +75,15 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) | |||
73 | struct platform_device *device = context; | 75 | struct platform_device *device = context; |
74 | struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev); | 76 | struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev); |
75 | 77 | ||
76 | if (!sparse_keymap_report_event(priv->input_dev, event, 1, true)) | 78 | if (priv->wakeup_mode) { |
77 | dev_info(&device->dev, "unknown event index 0x%x\n", | 79 | if (sparse_keymap_entry_from_scancode(priv->input_dev, event)) { |
78 | event); | 80 | pm_wakeup_hard_event(&device->dev); |
81 | return; | ||
82 | } | ||
83 | } else if (sparse_keymap_report_event(priv->input_dev, event, 1, true)) { | ||
84 | return; | ||
85 | } | ||
86 | dev_info(&device->dev, "unknown event index 0x%x\n", event); | ||
79 | } | 87 | } |
80 | 88 | ||
81 | static int intel_vbtn_probe(struct platform_device *device) | 89 | static int intel_vbtn_probe(struct platform_device *device) |
@@ -109,6 +117,7 @@ static int intel_vbtn_probe(struct platform_device *device) | |||
109 | if (ACPI_FAILURE(status)) | 117 | if (ACPI_FAILURE(status)) |
110 | return -EBUSY; | 118 | return -EBUSY; |
111 | 119 | ||
120 | device_init_wakeup(&device->dev, true); | ||
112 | return 0; | 121 | return 0; |
113 | } | 122 | } |
114 | 123 | ||
@@ -125,10 +134,34 @@ static int intel_vbtn_remove(struct platform_device *device) | |||
125 | return 0; | 134 | return 0; |
126 | } | 135 | } |
127 | 136 | ||
137 | static int intel_vbtn_pm_prepare(struct device *dev) | ||
138 | { | ||
139 | struct intel_vbtn_priv *priv = dev_get_drvdata(dev); | ||
140 | |||
141 | priv->wakeup_mode = true; | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static int intel_vbtn_pm_resume(struct device *dev) | ||
146 | { | ||
147 | struct intel_vbtn_priv *priv = dev_get_drvdata(dev); | ||
148 | |||
149 | priv->wakeup_mode = false; | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static const struct dev_pm_ops intel_vbtn_pm_ops = { | ||
154 | .prepare = intel_vbtn_pm_prepare, | ||
155 | .resume = intel_vbtn_pm_resume, | ||
156 | .restore = intel_vbtn_pm_resume, | ||
157 | .thaw = intel_vbtn_pm_resume, | ||
158 | }; | ||
159 | |||
128 | static struct platform_driver intel_vbtn_pl_driver = { | 160 | static struct platform_driver intel_vbtn_pl_driver = { |
129 | .driver = { | 161 | .driver = { |
130 | .name = "intel-vbtn", | 162 | .name = "intel-vbtn", |
131 | .acpi_match_table = intel_vbtn_ids, | 163 | .acpi_match_table = intel_vbtn_ids, |
164 | .pm = &intel_vbtn_pm_ops, | ||
132 | }, | 165 | }, |
133 | .probe = intel_vbtn_probe, | 166 | .probe = intel_vbtn_probe, |
134 | .remove = intel_vbtn_remove, | 167 | .remove = intel_vbtn_remove, |
diff --git a/drivers/platform/x86/intel_int0002_vgpio.c b/drivers/platform/x86/intel_int0002_vgpio.c new file mode 100644 index 000000000000..92dc230ef5b2 --- /dev/null +++ b/drivers/platform/x86/intel_int0002_vgpio.c | |||
@@ -0,0 +1,219 @@ | |||
1 | /* | ||
2 | * Intel INT0002 "Virtual GPIO" driver | ||
3 | * | ||
4 | * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com> | ||
5 | * | ||
6 | * Loosely based on android x86 kernel code which is: | ||
7 | * | ||
8 | * Copyright (c) 2014, Intel Corporation. | ||
9 | * | ||
10 | * Author: Dyut Kumar Sil <dyut.k.sil@intel.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | * | ||
16 | * Some peripherals on Bay Trail and Cherry Trail platforms signal a Power | ||
17 | * Management Event (PME) to the Power Management Controller (PMC) to wakeup | ||
18 | * the system. When this happens software needs to clear the PME bus 0 status | ||
19 | * bit in the GPE0a_STS register to avoid an IRQ storm on IRQ 9. | ||
20 | * | ||
21 | * This is modelled in ACPI through the INT0002 ACPI device, which is | ||
22 | * called a "Virtual GPIO controller" in ACPI because it defines the event | ||
23 | * handler to call when the PME triggers through _AEI and _L02 / _E02 | ||
24 | * methods as would be done for a real GPIO interrupt in ACPI. Note this | ||
25 | * is a hack to define an AML event handler for the PME while using existing | ||
26 | * ACPI mechanisms, this is not a real GPIO at all. | ||
27 | * | ||
28 | * This driver will bind to the INT0002 device, and register as a GPIO | ||
29 | * controller, letting gpiolib-acpi.c call the _L02 handler as it would | ||
30 | * for a real GPIO controller. | ||
31 | */ | ||
32 | |||
33 | #include <linux/acpi.h> | ||
34 | #include <linux/bitmap.h> | ||
35 | #include <linux/gpio/driver.h> | ||
36 | #include <linux/interrupt.h> | ||
37 | #include <linux/io.h> | ||
38 | #include <linux/kernel.h> | ||
39 | #include <linux/module.h> | ||
40 | #include <linux/platform_device.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/suspend.h> | ||
43 | |||
44 | #include <asm/cpu_device_id.h> | ||
45 | #include <asm/intel-family.h> | ||
46 | |||
47 | #define DRV_NAME "INT0002 Virtual GPIO" | ||
48 | |||
49 | /* For some reason the virtual GPIO pin tied to the GPE is numbered pin 2 */ | ||
50 | #define GPE0A_PME_B0_VIRT_GPIO_PIN 2 | ||
51 | |||
52 | #define GPE0A_PME_B0_STS_BIT BIT(13) | ||
53 | #define GPE0A_PME_B0_EN_BIT BIT(13) | ||
54 | #define GPE0A_STS_PORT 0x420 | ||
55 | #define GPE0A_EN_PORT 0x428 | ||
56 | |||
57 | #define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, } | ||
58 | |||
59 | static const struct x86_cpu_id int0002_cpu_ids[] = { | ||
60 | /* | ||
61 | * Limit ourselves to Cherry Trail for now, until testing shows we | ||
62 | * need to handle the INT0002 device on Baytrail too. | ||
63 | * ICPU(INTEL_FAM6_ATOM_SILVERMONT1), * Valleyview, Bay Trail * | ||
64 | */ | ||
65 | ICPU(INTEL_FAM6_ATOM_AIRMONT), /* Braswell, Cherry Trail */ | ||
66 | {} | ||
67 | }; | ||
68 | |||
69 | /* | ||
70 | * As this is not a real GPIO at all, but just a hack to model an event in | ||
71 | * ACPI the get / set functions are dummy functions. | ||
72 | */ | ||
73 | |||
74 | static int int0002_gpio_get(struct gpio_chip *chip, unsigned int offset) | ||
75 | { | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static void int0002_gpio_set(struct gpio_chip *chip, unsigned int offset, | ||
80 | int value) | ||
81 | { | ||
82 | } | ||
83 | |||
84 | static int int0002_gpio_direction_output(struct gpio_chip *chip, | ||
85 | unsigned int offset, int value) | ||
86 | { | ||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static void int0002_irq_ack(struct irq_data *data) | ||
91 | { | ||
92 | outl(GPE0A_PME_B0_STS_BIT, GPE0A_STS_PORT); | ||
93 | } | ||
94 | |||
95 | static void int0002_irq_unmask(struct irq_data *data) | ||
96 | { | ||
97 | u32 gpe_en_reg; | ||
98 | |||
99 | gpe_en_reg = inl(GPE0A_EN_PORT); | ||
100 | gpe_en_reg |= GPE0A_PME_B0_EN_BIT; | ||
101 | outl(gpe_en_reg, GPE0A_EN_PORT); | ||
102 | } | ||
103 | |||
104 | static void int0002_irq_mask(struct irq_data *data) | ||
105 | { | ||
106 | u32 gpe_en_reg; | ||
107 | |||
108 | gpe_en_reg = inl(GPE0A_EN_PORT); | ||
109 | gpe_en_reg &= ~GPE0A_PME_B0_EN_BIT; | ||
110 | outl(gpe_en_reg, GPE0A_EN_PORT); | ||
111 | } | ||
112 | |||
113 | static irqreturn_t int0002_irq(int irq, void *data) | ||
114 | { | ||
115 | struct gpio_chip *chip = data; | ||
116 | u32 gpe_sts_reg; | ||
117 | |||
118 | gpe_sts_reg = inl(GPE0A_STS_PORT); | ||
119 | if (!(gpe_sts_reg & GPE0A_PME_B0_STS_BIT)) | ||
120 | return IRQ_NONE; | ||
121 | |||
122 | generic_handle_irq(irq_find_mapping(chip->irqdomain, | ||
123 | GPE0A_PME_B0_VIRT_GPIO_PIN)); | ||
124 | |||
125 | pm_system_wakeup(); | ||
126 | |||
127 | return IRQ_HANDLED; | ||
128 | } | ||
129 | |||
130 | static struct irq_chip int0002_irqchip = { | ||
131 | .name = DRV_NAME, | ||
132 | .irq_ack = int0002_irq_ack, | ||
133 | .irq_mask = int0002_irq_mask, | ||
134 | .irq_unmask = int0002_irq_unmask, | ||
135 | }; | ||
136 | |||
137 | static int int0002_probe(struct platform_device *pdev) | ||
138 | { | ||
139 | struct device *dev = &pdev->dev; | ||
140 | const struct x86_cpu_id *cpu_id; | ||
141 | struct gpio_chip *chip; | ||
142 | int irq, ret; | ||
143 | |||
144 | /* Menlow has a different INT0002 device? <sigh> */ | ||
145 | cpu_id = x86_match_cpu(int0002_cpu_ids); | ||
146 | if (!cpu_id) | ||
147 | return -ENODEV; | ||
148 | |||
149 | irq = platform_get_irq(pdev, 0); | ||
150 | if (irq < 0) { | ||
151 | dev_err(dev, "Error getting IRQ: %d\n", irq); | ||
152 | return irq; | ||
153 | } | ||
154 | |||
155 | chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); | ||
156 | if (!chip) | ||
157 | return -ENOMEM; | ||
158 | |||
159 | chip->label = DRV_NAME; | ||
160 | chip->parent = dev; | ||
161 | chip->owner = THIS_MODULE; | ||
162 | chip->get = int0002_gpio_get; | ||
163 | chip->set = int0002_gpio_set; | ||
164 | chip->direction_input = int0002_gpio_get; | ||
165 | chip->direction_output = int0002_gpio_direction_output; | ||
166 | chip->base = -1; | ||
167 | chip->ngpio = GPE0A_PME_B0_VIRT_GPIO_PIN + 1; | ||
168 | chip->irq_need_valid_mask = true; | ||
169 | |||
170 | ret = devm_gpiochip_add_data(&pdev->dev, chip, NULL); | ||
171 | if (ret) { | ||
172 | dev_err(dev, "Error adding gpio chip: %d\n", ret); | ||
173 | return ret; | ||
174 | } | ||
175 | |||
176 | bitmap_clear(chip->irq_valid_mask, 0, GPE0A_PME_B0_VIRT_GPIO_PIN); | ||
177 | |||
178 | /* | ||
179 | * We manually request the irq here instead of passing a flow-handler | ||
180 | * to gpiochip_set_chained_irqchip, because the irq is shared. | ||
181 | */ | ||
182 | ret = devm_request_irq(dev, irq, int0002_irq, | ||
183 | IRQF_SHARED | IRQF_NO_THREAD, "INT0002", chip); | ||
184 | if (ret) { | ||
185 | dev_err(dev, "Error requesting IRQ %d: %d\n", irq, ret); | ||
186 | return ret; | ||
187 | } | ||
188 | |||
189 | ret = gpiochip_irqchip_add(chip, &int0002_irqchip, 0, handle_edge_irq, | ||
190 | IRQ_TYPE_NONE); | ||
191 | if (ret) { | ||
192 | dev_err(dev, "Error adding irqchip: %d\n", ret); | ||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | gpiochip_set_chained_irqchip(chip, &int0002_irqchip, irq, NULL); | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static const struct acpi_device_id int0002_acpi_ids[] = { | ||
202 | { "INT0002", 0 }, | ||
203 | { }, | ||
204 | }; | ||
205 | MODULE_DEVICE_TABLE(acpi, int0002_acpi_ids); | ||
206 | |||
207 | static struct platform_driver int0002_driver = { | ||
208 | .driver = { | ||
209 | .name = DRV_NAME, | ||
210 | .acpi_match_table = int0002_acpi_ids, | ||
211 | }, | ||
212 | .probe = int0002_probe, | ||
213 | }; | ||
214 | |||
215 | module_platform_driver(int0002_driver); | ||
216 | |||
217 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); | ||
218 | MODULE_DESCRIPTION("Intel INT0002 Virtual GPIO driver"); | ||
219 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 9113876487ed..3a4c1aa0201e 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c | |||
@@ -149,8 +149,8 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state) | |||
149 | } | 149 | } |
150 | 150 | ||
151 | if (device_can_wakeup(&dev->dev)) { | 151 | if (device_can_wakeup(&dev->dev)) { |
152 | error = acpi_pm_device_sleep_wake(&dev->dev, | 152 | error = acpi_pm_set_device_wakeup(&dev->dev, |
153 | device_may_wakeup(&dev->dev)); | 153 | device_may_wakeup(&dev->dev)); |
154 | if (error) | 154 | if (error) |
155 | return error; | 155 | return error; |
156 | } | 156 | } |
@@ -185,7 +185,7 @@ static int pnpacpi_resume(struct pnp_dev *dev) | |||
185 | } | 185 | } |
186 | 186 | ||
187 | if (device_may_wakeup(&dev->dev)) | 187 | if (device_may_wakeup(&dev->dev)) |
188 | acpi_pm_device_sleep_wake(&dev->dev, false); | 188 | acpi_pm_set_device_wakeup(&dev->dev, false); |
189 | 189 | ||
190 | if (acpi_device_power_manageable(acpi_dev)) | 190 | if (acpi_device_power_manageable(acpi_dev)) |
191 | error = acpi_device_set_power(acpi_dev, ACPI_STATE_D0); | 191 | error = acpi_device_set_power(acpi_dev, ACPI_STATE_D0); |
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 7859d738df41..ea829ad798c0 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c | |||
@@ -584,12 +584,7 @@ static int hcd_pci_suspend_noirq(struct device *dev) | |||
584 | 584 | ||
585 | static int hcd_pci_resume_noirq(struct device *dev) | 585 | static int hcd_pci_resume_noirq(struct device *dev) |
586 | { | 586 | { |
587 | struct pci_dev *pci_dev = to_pci_dev(dev); | 587 | powermac_set_asic(to_pci_dev(dev), 1); |
588 | |||
589 | powermac_set_asic(pci_dev, 1); | ||
590 | |||
591 | /* Go back to D0 and disable remote wakeup */ | ||
592 | pci_back_from_sleep(pci_dev); | ||
593 | return 0; | 588 | return 0; |
594 | } | 589 | } |
595 | 590 | ||
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index fe851544d7fb..7e995df7a797 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c | |||
@@ -230,7 +230,6 @@ static int dwc3_pci_probe(struct pci_dev *pci, | |||
230 | } | 230 | } |
231 | 231 | ||
232 | device_init_wakeup(dev, true); | 232 | device_init_wakeup(dev, true); |
233 | device_set_run_wake(dev, true); | ||
234 | pci_set_drvdata(pci, dwc); | 233 | pci_set_drvdata(pci, dwc); |
235 | pm_runtime_put(dev); | 234 | pm_runtime_put(dev); |
236 | 235 | ||
@@ -310,7 +309,7 @@ static int dwc3_pci_runtime_suspend(struct device *dev) | |||
310 | { | 309 | { |
311 | struct dwc3_pci *dwc = dev_get_drvdata(dev); | 310 | struct dwc3_pci *dwc = dev_get_drvdata(dev); |
312 | 311 | ||
313 | if (device_run_wake(dev)) | 312 | if (device_can_wakeup(dev)) |
314 | return dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D3); | 313 | return dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D3); |
315 | 314 | ||
316 | return -EBUSY; | 315 | return -EBUSY; |
diff --git a/drivers/usb/host/uhci-pci.c b/drivers/usb/host/uhci-pci.c index 02260cfdedb1..49effdc0d857 100644 --- a/drivers/usb/host/uhci-pci.c +++ b/drivers/usb/host/uhci-pci.c | |||
@@ -131,7 +131,7 @@ static int uhci_pci_init(struct usb_hcd *hcd) | |||
131 | 131 | ||
132 | /* Intel controllers use non-PME wakeup signalling */ | 132 | /* Intel controllers use non-PME wakeup signalling */ |
133 | if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_INTEL) | 133 | if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_INTEL) |
134 | device_set_run_wake(uhci_dev(uhci), 1); | 134 | device_set_wakeup_capable(uhci_dev(uhci), true); |
135 | 135 | ||
136 | /* Set up pointers to PCI-specific functions */ | 136 | /* Set up pointers to PCI-specific functions */ |
137 | uhci->reset_hc = uhci_pci_reset_hc; | 137 | uhci->reset_hc = uhci_pci_reset_hc; |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index c1b163cb68b1..68bc6be447fd 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -315,13 +315,12 @@ struct acpi_device_perf { | |||
315 | /* Wakeup Management */ | 315 | /* Wakeup Management */ |
316 | struct acpi_device_wakeup_flags { | 316 | struct acpi_device_wakeup_flags { |
317 | u8 valid:1; /* Can successfully enable wakeup? */ | 317 | u8 valid:1; /* Can successfully enable wakeup? */ |
318 | u8 run_wake:1; /* Run-Wake GPE devices */ | ||
319 | u8 notifier_present:1; /* Wake-up notify handler has been installed */ | 318 | u8 notifier_present:1; /* Wake-up notify handler has been installed */ |
320 | u8 enabled:1; /* Enabled for wakeup */ | 319 | u8 enabled:1; /* Enabled for wakeup */ |
321 | }; | 320 | }; |
322 | 321 | ||
323 | struct acpi_device_wakeup_context { | 322 | struct acpi_device_wakeup_context { |
324 | struct work_struct work; | 323 | void (*func)(struct acpi_device_wakeup_context *context); |
325 | struct device *dev; | 324 | struct device *dev; |
326 | }; | 325 | }; |
327 | 326 | ||
@@ -600,15 +599,20 @@ static inline bool acpi_device_always_present(struct acpi_device *adev) | |||
600 | #endif | 599 | #endif |
601 | 600 | ||
602 | #ifdef CONFIG_PM | 601 | #ifdef CONFIG_PM |
602 | void acpi_pm_wakeup_event(struct device *dev); | ||
603 | acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev, | 603 | acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev, |
604 | void (*work_func)(struct work_struct *work)); | 604 | void (*func)(struct acpi_device_wakeup_context *context)); |
605 | acpi_status acpi_remove_pm_notifier(struct acpi_device *adev); | 605 | acpi_status acpi_remove_pm_notifier(struct acpi_device *adev); |
606 | bool acpi_pm_device_can_wakeup(struct device *dev); | ||
606 | int acpi_pm_device_sleep_state(struct device *, int *, int); | 607 | int acpi_pm_device_sleep_state(struct device *, int *, int); |
607 | int acpi_pm_device_run_wake(struct device *, bool); | 608 | int acpi_pm_set_device_wakeup(struct device *dev, bool enable); |
608 | #else | 609 | #else |
610 | static inline void acpi_pm_wakeup_event(struct device *dev) | ||
611 | { | ||
612 | } | ||
609 | static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev, | 613 | static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev, |
610 | struct device *dev, | 614 | struct device *dev, |
611 | void (*work_func)(struct work_struct *work)) | 615 | void (*func)(struct acpi_device_wakeup_context *context)) |
612 | { | 616 | { |
613 | return AE_SUPPORT; | 617 | return AE_SUPPORT; |
614 | } | 618 | } |
@@ -616,6 +620,10 @@ static inline acpi_status acpi_remove_pm_notifier(struct acpi_device *adev) | |||
616 | { | 620 | { |
617 | return AE_SUPPORT; | 621 | return AE_SUPPORT; |
618 | } | 622 | } |
623 | static inline bool acpi_pm_device_can_wakeup(struct device *dev) | ||
624 | { | ||
625 | return false; | ||
626 | } | ||
619 | static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m) | 627 | static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m) |
620 | { | 628 | { |
621 | if (p) | 629 | if (p) |
@@ -624,16 +632,7 @@ static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m) | |||
624 | return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3_COLD) ? | 632 | return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3_COLD) ? |
625 | m : ACPI_STATE_D0; | 633 | m : ACPI_STATE_D0; |
626 | } | 634 | } |
627 | static inline int acpi_pm_device_run_wake(struct device *dev, bool enable) | 635 | static inline int acpi_pm_set_device_wakeup(struct device *dev, bool enable) |
628 | { | ||
629 | return -ENODEV; | ||
630 | } | ||
631 | #endif | ||
632 | |||
633 | #ifdef CONFIG_PM_SLEEP | ||
634 | int acpi_pm_device_sleep_wake(struct device *, bool); | ||
635 | #else | ||
636 | static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable) | ||
637 | { | 636 | { |
638 | return -ENODEV; | 637 | return -ENODEV; |
639 | } | 638 | } |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 8039f9f0ca05..ff200c84240b 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -307,7 +307,6 @@ struct pci_dev { | |||
307 | u8 pm_cap; /* PM capability offset */ | 307 | u8 pm_cap; /* PM capability offset */ |
308 | unsigned int pme_support:5; /* Bitmask of states from which PME# | 308 | unsigned int pme_support:5; /* Bitmask of states from which PME# |
309 | can be generated */ | 309 | can be generated */ |
310 | unsigned int pme_interrupt:1; | ||
311 | unsigned int pme_poll:1; /* Poll device's PME status bit */ | 310 | unsigned int pme_poll:1; /* Poll device's PME status bit */ |
312 | unsigned int d1_support:1; /* Low power state D1 is supported */ | 311 | unsigned int d1_support:1; /* Low power state D1 is supported */ |
313 | unsigned int d2_support:1; /* Low power state D2 is supported */ | 312 | unsigned int d2_support:1; /* Low power state D2 is supported */ |
@@ -1098,8 +1097,7 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state); | |||
1098 | pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state); | 1097 | pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state); |
1099 | bool pci_pme_capable(struct pci_dev *dev, pci_power_t state); | 1098 | bool pci_pme_capable(struct pci_dev *dev, pci_power_t state); |
1100 | void pci_pme_active(struct pci_dev *dev, bool enable); | 1099 | void pci_pme_active(struct pci_dev *dev, bool enable); |
1101 | int __pci_enable_wake(struct pci_dev *dev, pci_power_t state, | 1100 | int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable); |
1102 | bool runtime, bool enable); | ||
1103 | int pci_wake_from_d3(struct pci_dev *dev, bool enable); | 1101 | int pci_wake_from_d3(struct pci_dev *dev, bool enable); |
1104 | int pci_prepare_to_sleep(struct pci_dev *dev); | 1102 | int pci_prepare_to_sleep(struct pci_dev *dev); |
1105 | int pci_back_from_sleep(struct pci_dev *dev); | 1103 | int pci_back_from_sleep(struct pci_dev *dev); |
@@ -1109,12 +1107,6 @@ void pci_pme_wakeup_bus(struct pci_bus *bus); | |||
1109 | void pci_d3cold_enable(struct pci_dev *dev); | 1107 | void pci_d3cold_enable(struct pci_dev *dev); |
1110 | void pci_d3cold_disable(struct pci_dev *dev); | 1108 | void pci_d3cold_disable(struct pci_dev *dev); |
1111 | 1109 | ||
1112 | static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, | ||
1113 | bool enable) | ||
1114 | { | ||
1115 | return __pci_enable_wake(dev, state, false, enable); | ||
1116 | } | ||
1117 | |||
1118 | /* PCI Virtual Channel */ | 1110 | /* PCI Virtual Channel */ |
1119 | int pci_save_vc_state(struct pci_dev *dev); | 1111 | int pci_save_vc_state(struct pci_dev *dev); |
1120 | void pci_restore_vc_state(struct pci_dev *dev); | 1112 | void pci_restore_vc_state(struct pci_dev *dev); |
diff --git a/include/linux/pm.h b/include/linux/pm.h index a0894bc52bb4..b8b4df09fd8f 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
@@ -584,7 +584,6 @@ struct dev_pm_info { | |||
584 | unsigned int idle_notification:1; | 584 | unsigned int idle_notification:1; |
585 | unsigned int request_pending:1; | 585 | unsigned int request_pending:1; |
586 | unsigned int deferred_resume:1; | 586 | unsigned int deferred_resume:1; |
587 | unsigned int run_wake:1; | ||
588 | unsigned int runtime_auto:1; | 587 | unsigned int runtime_auto:1; |
589 | bool ignore_children:1; | 588 | bool ignore_children:1; |
590 | unsigned int no_callbacks:1; | 589 | unsigned int no_callbacks:1; |
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index ca4823e675e2..2efb08a60e63 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h | |||
@@ -76,16 +76,6 @@ static inline void pm_runtime_put_noidle(struct device *dev) | |||
76 | atomic_add_unless(&dev->power.usage_count, -1, 0); | 76 | atomic_add_unless(&dev->power.usage_count, -1, 0); |
77 | } | 77 | } |
78 | 78 | ||
79 | static inline bool device_run_wake(struct device *dev) | ||
80 | { | ||
81 | return dev->power.run_wake; | ||
82 | } | ||
83 | |||
84 | static inline void device_set_run_wake(struct device *dev, bool enable) | ||
85 | { | ||
86 | dev->power.run_wake = enable; | ||
87 | } | ||
88 | |||
89 | static inline bool pm_runtime_suspended(struct device *dev) | 79 | static inline bool pm_runtime_suspended(struct device *dev) |
90 | { | 80 | { |
91 | return dev->power.runtime_status == RPM_SUSPENDED | 81 | return dev->power.runtime_status == RPM_SUSPENDED |
@@ -163,8 +153,6 @@ static inline void pm_runtime_forbid(struct device *dev) {} | |||
163 | static inline void pm_suspend_ignore_children(struct device *dev, bool enable) {} | 153 | static inline void pm_suspend_ignore_children(struct device *dev, bool enable) {} |
164 | static inline void pm_runtime_get_noresume(struct device *dev) {} | 154 | static inline void pm_runtime_get_noresume(struct device *dev) {} |
165 | static inline void pm_runtime_put_noidle(struct device *dev) {} | 155 | static inline void pm_runtime_put_noidle(struct device *dev) {} |
166 | static inline bool device_run_wake(struct device *dev) { return false; } | ||
167 | static inline void device_set_run_wake(struct device *dev, bool enable) {} | ||
168 | static inline bool pm_runtime_suspended(struct device *dev) { return false; } | 156 | static inline bool pm_runtime_suspended(struct device *dev) { return false; } |
169 | static inline bool pm_runtime_active(struct device *dev) { return true; } | 157 | static inline bool pm_runtime_active(struct device *dev) { return true; } |
170 | static inline bool pm_runtime_status_suspended(struct device *dev) { return false; } | 158 | static inline bool pm_runtime_status_suspended(struct device *dev) { return false; } |
diff --git a/include/linux/suspend.h b/include/linux/suspend.h index d9718378a8be..0b1cf32edfd7 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h | |||
@@ -189,6 +189,8 @@ struct platform_suspend_ops { | |||
189 | struct platform_freeze_ops { | 189 | struct platform_freeze_ops { |
190 | int (*begin)(void); | 190 | int (*begin)(void); |
191 | int (*prepare)(void); | 191 | int (*prepare)(void); |
192 | void (*wake)(void); | ||
193 | void (*sync)(void); | ||
192 | void (*restore)(void); | 194 | void (*restore)(void); |
193 | void (*end)(void); | 195 | void (*end)(void); |
194 | }; | 196 | }; |
@@ -428,7 +430,8 @@ extern unsigned int pm_wakeup_irq; | |||
428 | 430 | ||
429 | extern bool pm_wakeup_pending(void); | 431 | extern bool pm_wakeup_pending(void); |
430 | extern void pm_system_wakeup(void); | 432 | extern void pm_system_wakeup(void); |
431 | extern void pm_wakeup_clear(void); | 433 | extern void pm_system_cancel_wakeup(void); |
434 | extern void pm_wakeup_clear(bool reset); | ||
432 | extern void pm_system_irq_wakeup(unsigned int irq_number); | 435 | extern void pm_system_irq_wakeup(unsigned int irq_number); |
433 | extern bool pm_get_wakeup_count(unsigned int *count, bool block); | 436 | extern bool pm_get_wakeup_count(unsigned int *count, bool block); |
434 | extern bool pm_save_wakeup_count(unsigned int count); | 437 | extern bool pm_save_wakeup_count(unsigned int count); |
@@ -478,7 +481,7 @@ static inline int unregister_pm_notifier(struct notifier_block *nb) | |||
478 | 481 | ||
479 | static inline bool pm_wakeup_pending(void) { return false; } | 482 | static inline bool pm_wakeup_pending(void) { return false; } |
480 | static inline void pm_system_wakeup(void) {} | 483 | static inline void pm_system_wakeup(void) {} |
481 | static inline void pm_wakeup_clear(void) {} | 484 | static inline void pm_wakeup_clear(bool reset) {} |
482 | static inline void pm_system_irq_wakeup(unsigned int irq_number) {} | 485 | static inline void pm_system_irq_wakeup(unsigned int irq_number) {} |
483 | 486 | ||
484 | static inline void lock_system_sleep(void) {} | 487 | static inline void lock_system_sleep(void) {} |
diff --git a/kernel/power/process.c b/kernel/power/process.c index c7209f060eeb..78672d324a6e 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c | |||
@@ -132,7 +132,7 @@ int freeze_processes(void) | |||
132 | if (!pm_freezing) | 132 | if (!pm_freezing) |
133 | atomic_inc(&system_freezing_cnt); | 133 | atomic_inc(&system_freezing_cnt); |
134 | 134 | ||
135 | pm_wakeup_clear(); | 135 | pm_wakeup_clear(true); |
136 | pr_info("Freezing user space processes ... "); | 136 | pr_info("Freezing user space processes ... "); |
137 | pm_freezing = true; | 137 | pm_freezing = true; |
138 | error = try_to_freeze_tasks(true); | 138 | error = try_to_freeze_tasks(true); |
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 15e6baef5c73..3ecf275d7e44 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c | |||
@@ -72,6 +72,8 @@ static void freeze_begin(void) | |||
72 | 72 | ||
73 | static void freeze_enter(void) | 73 | static void freeze_enter(void) |
74 | { | 74 | { |
75 | trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_FREEZE, true); | ||
76 | |||
75 | spin_lock_irq(&suspend_freeze_lock); | 77 | spin_lock_irq(&suspend_freeze_lock); |
76 | if (pm_wakeup_pending()) | 78 | if (pm_wakeup_pending()) |
77 | goto out; | 79 | goto out; |
@@ -84,11 +86,9 @@ static void freeze_enter(void) | |||
84 | 86 | ||
85 | /* Push all the CPUs into the idle loop. */ | 87 | /* Push all the CPUs into the idle loop. */ |
86 | wake_up_all_idle_cpus(); | 88 | wake_up_all_idle_cpus(); |
87 | pr_debug("PM: suspend-to-idle\n"); | ||
88 | /* Make the current CPU wait so it can enter the idle loop too. */ | 89 | /* Make the current CPU wait so it can enter the idle loop too. */ |
89 | wait_event(suspend_freeze_wait_head, | 90 | wait_event(suspend_freeze_wait_head, |
90 | suspend_freeze_state == FREEZE_STATE_WAKE); | 91 | suspend_freeze_state == FREEZE_STATE_WAKE); |
91 | pr_debug("PM: resume from suspend-to-idle\n"); | ||
92 | 92 | ||
93 | cpuidle_pause(); | 93 | cpuidle_pause(); |
94 | put_online_cpus(); | 94 | put_online_cpus(); |
@@ -98,6 +98,31 @@ static void freeze_enter(void) | |||
98 | out: | 98 | out: |
99 | suspend_freeze_state = FREEZE_STATE_NONE; | 99 | suspend_freeze_state = FREEZE_STATE_NONE; |
100 | spin_unlock_irq(&suspend_freeze_lock); | 100 | spin_unlock_irq(&suspend_freeze_lock); |
101 | |||
102 | trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_FREEZE, false); | ||
103 | } | ||
104 | |||
105 | static void s2idle_loop(void) | ||
106 | { | ||
107 | pr_debug("PM: suspend-to-idle\n"); | ||
108 | |||
109 | do { | ||
110 | freeze_enter(); | ||
111 | |||
112 | if (freeze_ops && freeze_ops->wake) | ||
113 | freeze_ops->wake(); | ||
114 | |||
115 | dpm_resume_noirq(PMSG_RESUME); | ||
116 | if (freeze_ops && freeze_ops->sync) | ||
117 | freeze_ops->sync(); | ||
118 | |||
119 | if (pm_wakeup_pending()) | ||
120 | break; | ||
121 | |||
122 | pm_wakeup_clear(false); | ||
123 | } while (!dpm_suspend_noirq(PMSG_SUSPEND)); | ||
124 | |||
125 | pr_debug("PM: resume from suspend-to-idle\n"); | ||
101 | } | 126 | } |
102 | 127 | ||
103 | void freeze_wake(void) | 128 | void freeze_wake(void) |
@@ -371,10 +396,8 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) | |||
371 | * all the devices are suspended. | 396 | * all the devices are suspended. |
372 | */ | 397 | */ |
373 | if (state == PM_SUSPEND_FREEZE) { | 398 | if (state == PM_SUSPEND_FREEZE) { |
374 | trace_suspend_resume(TPS("machine_suspend"), state, true); | 399 | s2idle_loop(); |
375 | freeze_enter(); | 400 | goto Platform_early_resume; |
376 | trace_suspend_resume(TPS("machine_suspend"), state, false); | ||
377 | goto Platform_wake; | ||
378 | } | 401 | } |
379 | 402 | ||
380 | error = disable_nonboot_cpus(); | 403 | error = disable_nonboot_cpus(); |