diff options
-rw-r--r-- | Documentation/devicetree/bindings/power/power_domain.txt | 2 | ||||
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | drivers/acpi/battery.c | 2 | ||||
-rw-r--r-- | drivers/acpi/button.c | 5 | ||||
-rw-r--r-- | drivers/acpi/device_pm.c | 3 | ||||
-rw-r--r-- | drivers/acpi/sleep.c | 28 | ||||
-rw-r--r-- | drivers/base/power/main.c | 5 | ||||
-rw-r--r-- | drivers/base/power/wakeup.c | 54 | ||||
-rw-r--r-- | drivers/cpuidle/cpuidle.c | 3 | ||||
-rw-r--r-- | drivers/idle/intel_idle.c | 2 | ||||
-rw-r--r-- | drivers/powercap/intel_rapl.c | 1 | ||||
-rw-r--r-- | include/linux/pm_wakeup.h | 25 | ||||
-rw-r--r-- | include/linux/suspend.h | 7 | ||||
-rw-r--r-- | kernel/power/process.c | 2 | ||||
-rw-r--r-- | kernel/power/suspend.c | 29 |
15 files changed, 123 insertions, 46 deletions
diff --git a/Documentation/devicetree/bindings/power/power_domain.txt b/Documentation/devicetree/bindings/power/power_domain.txt index 940707d095cc..14bd9e945ff6 100644 --- a/Documentation/devicetree/bindings/power/power_domain.txt +++ b/Documentation/devicetree/bindings/power/power_domain.txt | |||
@@ -81,7 +81,7 @@ Example 3: | |||
81 | child: power-controller@12341000 { | 81 | child: power-controller@12341000 { |
82 | compatible = "foo,power-controller"; | 82 | compatible = "foo,power-controller"; |
83 | reg = <0x12341000 0x1000>; | 83 | reg = <0x12341000 0x1000>; |
84 | power-domains = <&parent 0>; | 84 | power-domains = <&parent>; |
85 | #power-domain-cells = <0>; | 85 | #power-domain-cells = <0>; |
86 | domain-idle-states = <&DOMAIN_PWR_DN>; | 86 | domain-idle-states = <&DOMAIN_PWR_DN>; |
87 | }; | 87 | }; |
diff --git a/MAINTAINERS b/MAINTAINERS index 5fb2e94dd3e5..0cfa573ecfef 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -5590,6 +5590,7 @@ L: linux-pm@vger.kernel.org | |||
5590 | S: Supported | 5590 | S: Supported |
5591 | F: drivers/base/power/domain*.c | 5591 | F: drivers/base/power/domain*.c |
5592 | F: include/linux/pm_domain.h | 5592 | F: include/linux/pm_domain.h |
5593 | F: Documentation/devicetree/bindings/power/power_domain.txt | ||
5593 | 5594 | ||
5594 | GENERIC UIO DRIVER FOR PCI DEVICES | 5595 | GENERIC UIO DRIVER FOR PCI DEVICES |
5595 | M: "Michael S. Tsirkin" <mst@redhat.com> | 5596 | M: "Michael S. Tsirkin" <mst@redhat.com> |
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index d42eeef9d928..a9a9ab3399d4 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 | pm_wakeup_hard_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 668137e4a069..b7c2a06963d6 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -216,7 +216,7 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state) | |||
216 | } | 216 | } |
217 | 217 | ||
218 | if (state) | 218 | if (state) |
219 | pm_wakeup_event(&device->dev, 0); | 219 | pm_wakeup_hard_event(&device->dev); |
220 | 220 | ||
221 | ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); | 221 | ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); |
222 | if (ret == NOTIFY_DONE) | 222 | if (ret == NOTIFY_DONE) |
@@ -398,7 +398,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) | |||
398 | } else { | 398 | } else { |
399 | int keycode; | 399 | int keycode; |
400 | 400 | ||
401 | pm_wakeup_event(&device->dev, 0); | 401 | pm_wakeup_hard_event(&device->dev); |
402 | if (button->suspended) | 402 | if (button->suspended) |
403 | break; | 403 | break; |
404 | 404 | ||
@@ -530,6 +530,7 @@ static int acpi_button_add(struct acpi_device *device) | |||
530 | lid_device = device; | 530 | lid_device = device; |
531 | } | 531 | } |
532 | 532 | ||
533 | device_init_wakeup(&device->dev, true); | ||
533 | printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); | 534 | printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); |
534 | return 0; | 535 | return 0; |
535 | 536 | ||
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 993fd31394c8..798d5003a039 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 | ||
@@ -399,7 +400,7 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used) | |||
399 | mutex_lock(&acpi_pm_notifier_lock); | 400 | mutex_lock(&acpi_pm_notifier_lock); |
400 | 401 | ||
401 | if (adev->wakeup.flags.notifier_present) { | 402 | if (adev->wakeup.flags.notifier_present) { |
402 | __pm_wakeup_event(adev->wakeup.ws, 0); | 403 | pm_wakeup_ws_event(adev->wakeup.ws, 0, true); |
403 | if (adev->wakeup.context.work.func) | 404 | if (adev->wakeup.context.work.func) |
404 | queue_pm_work(&adev->wakeup.context.work); | 405 | queue_pm_work(&adev->wakeup.context.work); |
405 | } | 406 | } |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index a4327af676fe..e84005d642e6 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -662,14 +662,40 @@ static int acpi_freeze_prepare(void) | |||
662 | acpi_os_wait_events_complete(); | 662 | acpi_os_wait_events_complete(); |
663 | if (acpi_sci_irq_valid()) | 663 | if (acpi_sci_irq_valid()) |
664 | enable_irq_wake(acpi_sci_irq); | 664 | enable_irq_wake(acpi_sci_irq); |
665 | |||
665 | return 0; | 666 | return 0; |
666 | } | 667 | } |
667 | 668 | ||
669 | static void acpi_freeze_wake(void) | ||
670 | { | ||
671 | /* | ||
672 | * If IRQD_WAKEUP_ARMED is not set for the SCI at this point, it means | ||
673 | * that the SCI has triggered while suspended, so cancel the wakeup in | ||
674 | * case it has not been a wakeup event (the GPEs will be checked later). | ||
675 | */ | ||
676 | if (acpi_sci_irq_valid() && | ||
677 | !irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) | ||
678 | pm_system_cancel_wakeup(); | ||
679 | } | ||
680 | |||
681 | static void acpi_freeze_sync(void) | ||
682 | { | ||
683 | /* | ||
684 | * Process all pending events in case there are any wakeup ones. | ||
685 | * | ||
686 | * The EC driver uses the system workqueue, so that one needs to be | ||
687 | * flushed too. | ||
688 | */ | ||
689 | acpi_os_wait_events_complete(); | ||
690 | flush_scheduled_work(); | ||
691 | } | ||
692 | |||
668 | static void acpi_freeze_restore(void) | 693 | static void acpi_freeze_restore(void) |
669 | { | 694 | { |
670 | acpi_disable_wakeup_devices(ACPI_STATE_S0); | 695 | acpi_disable_wakeup_devices(ACPI_STATE_S0); |
671 | if (acpi_sci_irq_valid()) | 696 | if (acpi_sci_irq_valid()) |
672 | disable_irq_wake(acpi_sci_irq); | 697 | disable_irq_wake(acpi_sci_irq); |
698 | |||
673 | acpi_enable_all_runtime_gpes(); | 699 | acpi_enable_all_runtime_gpes(); |
674 | } | 700 | } |
675 | 701 | ||
@@ -681,6 +707,8 @@ static void acpi_freeze_end(void) | |||
681 | static const struct platform_freeze_ops acpi_freeze_ops = { | 707 | static const struct platform_freeze_ops acpi_freeze_ops = { |
682 | .begin = acpi_freeze_begin, | 708 | .begin = acpi_freeze_begin, |
683 | .prepare = acpi_freeze_prepare, | 709 | .prepare = acpi_freeze_prepare, |
710 | .wake = acpi_freeze_wake, | ||
711 | .sync = acpi_freeze_sync, | ||
684 | .restore = acpi_freeze_restore, | 712 | .restore = acpi_freeze_restore, |
685 | .end = acpi_freeze_end, | 713 | .end = acpi_freeze_end, |
686 | }; | 714 | }; |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 9faee1c893e5..e987a6f55d36 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -1091,11 +1091,6 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a | |||
1091 | if (async_error) | 1091 | if (async_error) |
1092 | goto Complete; | 1092 | goto Complete; |
1093 | 1093 | ||
1094 | if (pm_wakeup_pending()) { | ||
1095 | async_error = -EBUSY; | ||
1096 | goto Complete; | ||
1097 | } | ||
1098 | |||
1099 | if (dev->power.syscore || dev->power.direct_complete) | 1094 | if (dev->power.syscore || dev->power.direct_complete) |
1100 | goto Complete; | 1095 | goto Complete; |
1101 | 1096 | ||
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 136854970489..f62082fdd670 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. |
@@ -512,12 +512,13 @@ static bool wakeup_source_not_registered(struct wakeup_source *ws) | |||
512 | /** | 512 | /** |
513 | * wakup_source_activate - Mark given wakeup source as active. | 513 | * wakup_source_activate - Mark given wakeup source as active. |
514 | * @ws: Wakeup source to handle. | 514 | * @ws: Wakeup source to handle. |
515 | * @hard: If set, abort suspends in progress and wake up from suspend-to-idle. | ||
515 | * | 516 | * |
516 | * Update the @ws' statistics and, if @ws has just been activated, notify the PM | 517 | * Update the @ws' statistics and, if @ws has just been activated, notify the PM |
517 | * core of the event by incrementing the counter of of wakeup events being | 518 | * core of the event by incrementing the counter of of wakeup events being |
518 | * processed. | 519 | * processed. |
519 | */ | 520 | */ |
520 | static void wakeup_source_activate(struct wakeup_source *ws) | 521 | static void wakeup_source_activate(struct wakeup_source *ws, bool hard) |
521 | { | 522 | { |
522 | unsigned int cec; | 523 | unsigned int cec; |
523 | 524 | ||
@@ -525,11 +526,8 @@ static void wakeup_source_activate(struct wakeup_source *ws) | |||
525 | "unregistered wakeup source\n")) | 526 | "unregistered wakeup source\n")) |
526 | return; | 527 | return; |
527 | 528 | ||
528 | /* | 529 | if (hard) |
529 | * active wakeup source should bring the system | 530 | pm_system_wakeup(); |
530 | * out of PM_SUSPEND_FREEZE state | ||
531 | */ | ||
532 | freeze_wake(); | ||
533 | 531 | ||
534 | ws->active = true; | 532 | ws->active = true; |
535 | ws->active_count++; | 533 | ws->active_count++; |
@@ -546,8 +544,9 @@ static void wakeup_source_activate(struct wakeup_source *ws) | |||
546 | /** | 544 | /** |
547 | * wakeup_source_report_event - Report wakeup event using the given source. | 545 | * wakeup_source_report_event - Report wakeup event using the given source. |
548 | * @ws: Wakeup source to report the event for. | 546 | * @ws: Wakeup source to report the event for. |
547 | * @hard: If set, abort suspends in progress and wake up from suspend-to-idle. | ||
549 | */ | 548 | */ |
550 | static void wakeup_source_report_event(struct wakeup_source *ws) | 549 | static void wakeup_source_report_event(struct wakeup_source *ws, bool hard) |
551 | { | 550 | { |
552 | ws->event_count++; | 551 | ws->event_count++; |
553 | /* This is racy, but the counter is approximate anyway. */ | 552 | /* This is racy, but the counter is approximate anyway. */ |
@@ -555,7 +554,7 @@ static void wakeup_source_report_event(struct wakeup_source *ws) | |||
555 | ws->wakeup_count++; | 554 | ws->wakeup_count++; |
556 | 555 | ||
557 | if (!ws->active) | 556 | if (!ws->active) |
558 | wakeup_source_activate(ws); | 557 | wakeup_source_activate(ws, hard); |
559 | } | 558 | } |
560 | 559 | ||
561 | /** | 560 | /** |
@@ -573,7 +572,7 @@ void __pm_stay_awake(struct wakeup_source *ws) | |||
573 | 572 | ||
574 | spin_lock_irqsave(&ws->lock, flags); | 573 | spin_lock_irqsave(&ws->lock, flags); |
575 | 574 | ||
576 | wakeup_source_report_event(ws); | 575 | wakeup_source_report_event(ws, false); |
577 | del_timer(&ws->timer); | 576 | del_timer(&ws->timer); |
578 | ws->timer_expires = 0; | 577 | ws->timer_expires = 0; |
579 | 578 | ||
@@ -739,9 +738,10 @@ static void pm_wakeup_timer_fn(unsigned long data) | |||
739 | } | 738 | } |
740 | 739 | ||
741 | /** | 740 | /** |
742 | * __pm_wakeup_event - Notify the PM core of a wakeup event. | 741 | * pm_wakeup_ws_event - Notify the PM core of a wakeup event. |
743 | * @ws: Wakeup source object associated with the event source. | 742 | * @ws: Wakeup source object associated with the event source. |
744 | * @msec: Anticipated event processing time (in milliseconds). | 743 | * @msec: Anticipated event processing time (in milliseconds). |
744 | * @hard: If set, abort suspends in progress and wake up from suspend-to-idle. | ||
745 | * | 745 | * |
746 | * Notify the PM core of a wakeup event whose source is @ws that will take | 746 | * Notify the PM core of a wakeup event whose source is @ws that will take |
747 | * approximately @msec milliseconds to be processed by the kernel. If @ws is | 747 | * approximately @msec milliseconds to be processed by the kernel. If @ws is |
@@ -750,7 +750,7 @@ static void pm_wakeup_timer_fn(unsigned long data) | |||
750 | * | 750 | * |
751 | * It is safe to call this function from interrupt context. | 751 | * It is safe to call this function from interrupt context. |
752 | */ | 752 | */ |
753 | void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) | 753 | void pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard) |
754 | { | 754 | { |
755 | unsigned long flags; | 755 | unsigned long flags; |
756 | unsigned long expires; | 756 | unsigned long expires; |
@@ -760,7 +760,7 @@ void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) | |||
760 | 760 | ||
761 | spin_lock_irqsave(&ws->lock, flags); | 761 | spin_lock_irqsave(&ws->lock, flags); |
762 | 762 | ||
763 | wakeup_source_report_event(ws); | 763 | wakeup_source_report_event(ws, hard); |
764 | 764 | ||
765 | if (!msec) { | 765 | if (!msec) { |
766 | wakeup_source_deactivate(ws); | 766 | wakeup_source_deactivate(ws); |
@@ -779,17 +779,17 @@ void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) | |||
779 | unlock: | 779 | unlock: |
780 | spin_unlock_irqrestore(&ws->lock, flags); | 780 | spin_unlock_irqrestore(&ws->lock, flags); |
781 | } | 781 | } |
782 | EXPORT_SYMBOL_GPL(__pm_wakeup_event); | 782 | EXPORT_SYMBOL_GPL(pm_wakeup_ws_event); |
783 | |||
784 | 783 | ||
785 | /** | 784 | /** |
786 | * pm_wakeup_event - Notify the PM core of a wakeup event. | 785 | * pm_wakeup_event - Notify the PM core of a wakeup event. |
787 | * @dev: Device the wakeup event is related to. | 786 | * @dev: Device the wakeup event is related to. |
788 | * @msec: Anticipated event processing time (in milliseconds). | 787 | * @msec: Anticipated event processing time (in milliseconds). |
788 | * @hard: If set, abort suspends in progress and wake up from suspend-to-idle. | ||
789 | * | 789 | * |
790 | * Call __pm_wakeup_event() for the @dev's wakeup source object. | 790 | * Call pm_wakeup_ws_event() for the @dev's wakeup source object. |
791 | */ | 791 | */ |
792 | void pm_wakeup_event(struct device *dev, unsigned int msec) | 792 | void pm_wakeup_dev_event(struct device *dev, unsigned int msec, bool hard) |
793 | { | 793 | { |
794 | unsigned long flags; | 794 | unsigned long flags; |
795 | 795 | ||
@@ -797,10 +797,10 @@ void pm_wakeup_event(struct device *dev, unsigned int msec) | |||
797 | return; | 797 | return; |
798 | 798 | ||
799 | spin_lock_irqsave(&dev->power.lock, flags); | 799 | spin_lock_irqsave(&dev->power.lock, flags); |
800 | __pm_wakeup_event(dev->power.wakeup, msec); | 800 | pm_wakeup_ws_event(dev->power.wakeup, msec, hard); |
801 | spin_unlock_irqrestore(&dev->power.lock, flags); | 801 | spin_unlock_irqrestore(&dev->power.lock, flags); |
802 | } | 802 | } |
803 | EXPORT_SYMBOL_GPL(pm_wakeup_event); | 803 | EXPORT_SYMBOL_GPL(pm_wakeup_dev_event); |
804 | 804 | ||
805 | void pm_print_active_wakeup_sources(void) | 805 | void pm_print_active_wakeup_sources(void) |
806 | { | 806 | { |
@@ -856,20 +856,26 @@ bool pm_wakeup_pending(void) | |||
856 | pm_print_active_wakeup_sources(); | 856 | pm_print_active_wakeup_sources(); |
857 | } | 857 | } |
858 | 858 | ||
859 | return ret || pm_abort_suspend; | 859 | return ret || atomic_read(&pm_abort_suspend) > 0; |
860 | } | 860 | } |
861 | 861 | ||
862 | void pm_system_wakeup(void) | 862 | void pm_system_wakeup(void) |
863 | { | 863 | { |
864 | pm_abort_suspend = true; | 864 | atomic_inc(&pm_abort_suspend); |
865 | freeze_wake(); | 865 | freeze_wake(); |
866 | } | 866 | } |
867 | EXPORT_SYMBOL_GPL(pm_system_wakeup); | 867 | EXPORT_SYMBOL_GPL(pm_system_wakeup); |
868 | 868 | ||
869 | void pm_wakeup_clear(void) | 869 | void pm_system_cancel_wakeup(void) |
870 | { | ||
871 | atomic_dec(&pm_abort_suspend); | ||
872 | } | ||
873 | |||
874 | void pm_wakeup_clear(bool reset) | ||
870 | { | 875 | { |
871 | pm_abort_suspend = false; | ||
872 | pm_wakeup_irq = 0; | 876 | pm_wakeup_irq = 0; |
877 | if (reset) | ||
878 | atomic_set(&pm_abort_suspend, 0); | ||
873 | } | 879 | } |
874 | 880 | ||
875 | void pm_system_irq_wakeup(unsigned int irq_number) | 881 | void pm_system_irq_wakeup(unsigned int irq_number) |
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 548b90be7685..2706be7ed334 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
@@ -111,7 +111,8 @@ void cpuidle_use_deepest_state(bool enable) | |||
111 | 111 | ||
112 | preempt_disable(); | 112 | preempt_disable(); |
113 | dev = cpuidle_get_device(); | 113 | dev = cpuidle_get_device(); |
114 | dev->use_deepest_state = enable; | 114 | if (dev) |
115 | dev->use_deepest_state = enable; | ||
115 | preempt_enable(); | 116 | preempt_enable(); |
116 | } | 117 | } |
117 | 118 | ||
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 5805b041dd0f..216d7ec88c0c 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -1097,6 +1097,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = { | |||
1097 | ICPU(INTEL_FAM6_XEON_PHI_KNL, idle_cpu_knl), | 1097 | ICPU(INTEL_FAM6_XEON_PHI_KNL, idle_cpu_knl), |
1098 | ICPU(INTEL_FAM6_XEON_PHI_KNM, idle_cpu_knl), | 1098 | ICPU(INTEL_FAM6_XEON_PHI_KNM, idle_cpu_knl), |
1099 | ICPU(INTEL_FAM6_ATOM_GOLDMONT, idle_cpu_bxt), | 1099 | ICPU(INTEL_FAM6_ATOM_GOLDMONT, idle_cpu_bxt), |
1100 | ICPU(INTEL_FAM6_ATOM_GEMINI_LAKE, idle_cpu_bxt), | ||
1100 | ICPU(INTEL_FAM6_ATOM_DENVERTON, idle_cpu_dnv), | 1101 | ICPU(INTEL_FAM6_ATOM_DENVERTON, idle_cpu_dnv), |
1101 | {} | 1102 | {} |
1102 | }; | 1103 | }; |
@@ -1309,6 +1310,7 @@ static void intel_idle_state_table_update(void) | |||
1309 | ivt_idle_state_table_update(); | 1310 | ivt_idle_state_table_update(); |
1310 | break; | 1311 | break; |
1311 | case INTEL_FAM6_ATOM_GOLDMONT: | 1312 | case INTEL_FAM6_ATOM_GOLDMONT: |
1313 | case INTEL_FAM6_ATOM_GEMINI_LAKE: | ||
1312 | bxt_idle_state_table_update(); | 1314 | bxt_idle_state_table_update(); |
1313 | break; | 1315 | break; |
1314 | case INTEL_FAM6_SKYLAKE_DESKTOP: | 1316 | case INTEL_FAM6_SKYLAKE_DESKTOP: |
diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c index 9a25110c4a46..9ddad0815ba9 100644 --- a/drivers/powercap/intel_rapl.c +++ b/drivers/powercap/intel_rapl.c | |||
@@ -1164,6 +1164,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = { | |||
1164 | RAPL_CPU(INTEL_FAM6_ATOM_MERRIFIELD, rapl_defaults_tng), | 1164 | RAPL_CPU(INTEL_FAM6_ATOM_MERRIFIELD, rapl_defaults_tng), |
1165 | RAPL_CPU(INTEL_FAM6_ATOM_MOOREFIELD, rapl_defaults_ann), | 1165 | RAPL_CPU(INTEL_FAM6_ATOM_MOOREFIELD, rapl_defaults_ann), |
1166 | RAPL_CPU(INTEL_FAM6_ATOM_GOLDMONT, rapl_defaults_core), | 1166 | RAPL_CPU(INTEL_FAM6_ATOM_GOLDMONT, rapl_defaults_core), |
1167 | RAPL_CPU(INTEL_FAM6_ATOM_GEMINI_LAKE, rapl_defaults_core), | ||
1167 | RAPL_CPU(INTEL_FAM6_ATOM_DENVERTON, rapl_defaults_core), | 1168 | RAPL_CPU(INTEL_FAM6_ATOM_DENVERTON, rapl_defaults_core), |
1168 | 1169 | ||
1169 | RAPL_CPU(INTEL_FAM6_XEON_PHI_KNL, rapl_defaults_hsw_server), | 1170 | RAPL_CPU(INTEL_FAM6_XEON_PHI_KNL, rapl_defaults_hsw_server), |
diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h index a3447932df1f..4c2cba7ec1d4 100644 --- a/include/linux/pm_wakeup.h +++ b/include/linux/pm_wakeup.h | |||
@@ -106,8 +106,8 @@ extern void __pm_stay_awake(struct wakeup_source *ws); | |||
106 | extern void pm_stay_awake(struct device *dev); | 106 | extern void pm_stay_awake(struct device *dev); |
107 | extern void __pm_relax(struct wakeup_source *ws); | 107 | extern void __pm_relax(struct wakeup_source *ws); |
108 | extern void pm_relax(struct device *dev); | 108 | extern void pm_relax(struct device *dev); |
109 | extern void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec); | 109 | extern void pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard); |
110 | extern void pm_wakeup_event(struct device *dev, unsigned int msec); | 110 | extern void pm_wakeup_dev_event(struct device *dev, unsigned int msec, bool hard); |
111 | 111 | ||
112 | #else /* !CONFIG_PM_SLEEP */ | 112 | #else /* !CONFIG_PM_SLEEP */ |
113 | 113 | ||
@@ -182,9 +182,11 @@ static inline void __pm_relax(struct wakeup_source *ws) {} | |||
182 | 182 | ||
183 | static inline void pm_relax(struct device *dev) {} | 183 | static inline void pm_relax(struct device *dev) {} |
184 | 184 | ||
185 | static inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) {} | 185 | static inline void pm_wakeup_ws_event(struct wakeup_source *ws, |
186 | unsigned int msec, bool hard) {} | ||
186 | 187 | ||
187 | static inline void pm_wakeup_event(struct device *dev, unsigned int msec) {} | 188 | static inline void pm_wakeup_dev_event(struct device *dev, unsigned int msec, |
189 | bool hard) {} | ||
188 | 190 | ||
189 | #endif /* !CONFIG_PM_SLEEP */ | 191 | #endif /* !CONFIG_PM_SLEEP */ |
190 | 192 | ||
@@ -201,4 +203,19 @@ static inline void wakeup_source_trash(struct wakeup_source *ws) | |||
201 | wakeup_source_drop(ws); | 203 | wakeup_source_drop(ws); |
202 | } | 204 | } |
203 | 205 | ||
206 | static inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) | ||
207 | { | ||
208 | return pm_wakeup_ws_event(ws, msec, false); | ||
209 | } | ||
210 | |||
211 | static inline void pm_wakeup_event(struct device *dev, unsigned int msec) | ||
212 | { | ||
213 | return pm_wakeup_dev_event(dev, msec, false); | ||
214 | } | ||
215 | |||
216 | static inline void pm_wakeup_hard_event(struct device *dev) | ||
217 | { | ||
218 | return pm_wakeup_dev_event(dev, 0, true); | ||
219 | } | ||
220 | |||
204 | #endif /* _LINUX_PM_WAKEUP_H */ | 221 | #endif /* _LINUX_PM_WAKEUP_H */ |
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..c0248c74d6d4 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; |
@@ -98,6 +100,27 @@ static void freeze_enter(void) | |||
98 | out: | 100 | out: |
99 | suspend_freeze_state = FREEZE_STATE_NONE; | 101 | suspend_freeze_state = FREEZE_STATE_NONE; |
100 | spin_unlock_irq(&suspend_freeze_lock); | 102 | spin_unlock_irq(&suspend_freeze_lock); |
103 | |||
104 | trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_FREEZE, false); | ||
105 | } | ||
106 | |||
107 | static void s2idle_loop(void) | ||
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)); | ||
101 | } | 124 | } |
102 | 125 | ||
103 | void freeze_wake(void) | 126 | void freeze_wake(void) |
@@ -371,10 +394,8 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) | |||
371 | * all the devices are suspended. | 394 | * all the devices are suspended. |
372 | */ | 395 | */ |
373 | if (state == PM_SUSPEND_FREEZE) { | 396 | if (state == PM_SUSPEND_FREEZE) { |
374 | trace_suspend_resume(TPS("machine_suspend"), state, true); | 397 | s2idle_loop(); |
375 | freeze_enter(); | 398 | goto Platform_early_resume; |
376 | trace_suspend_resume(TPS("machine_suspend"), state, false); | ||
377 | goto Platform_wake; | ||
378 | } | 399 | } |
379 | 400 | ||
380 | error = disable_nonboot_cpus(); | 401 | error = disable_nonboot_cpus(); |