summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/power/power_domain.txt2
-rw-r--r--MAINTAINERS1
-rw-r--r--drivers/acpi/battery.c2
-rw-r--r--drivers/acpi/button.c5
-rw-r--r--drivers/acpi/device_pm.c3
-rw-r--r--drivers/acpi/sleep.c28
-rw-r--r--drivers/base/power/main.c5
-rw-r--r--drivers/base/power/wakeup.c54
-rw-r--r--drivers/cpuidle/cpuidle.c3
-rw-r--r--drivers/idle/intel_idle.c2
-rw-r--r--drivers/powercap/intel_rapl.c1
-rw-r--r--include/linux/pm_wakeup.h25
-rw-r--r--include/linux/suspend.h7
-rw-r--r--kernel/power/process.c2
-rw-r--r--kernel/power/suspend.c29
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
5590S: Supported 5590S: Supported
5591F: drivers/base/power/domain*.c 5591F: drivers/base/power/domain*.c
5592F: include/linux/pm_domain.h 5592F: include/linux/pm_domain.h
5593F: Documentation/devicetree/bindings/power/power_domain.txt
5593 5594
5594GENERIC UIO DRIVER FOR PCI DEVICES 5595GENERIC UIO DRIVER FOR PCI DEVICES
5595M: "Michael S. Tsirkin" <mst@redhat.com> 5596M: "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
669static 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
681static 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
668static void acpi_freeze_restore(void) 693static 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)
681static const struct platform_freeze_ops acpi_freeze_ops = { 707static 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. */
29unsigned int pm_wakeup_irq __read_mostly; 29unsigned 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. */
32static bool pm_abort_suspend __read_mostly; 32static 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 */
520static void wakeup_source_activate(struct wakeup_source *ws) 521static 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 */
550static void wakeup_source_report_event(struct wakeup_source *ws) 549static 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 */
753void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) 753void 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}
782EXPORT_SYMBOL_GPL(__pm_wakeup_event); 782EXPORT_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 */
792void pm_wakeup_event(struct device *dev, unsigned int msec) 792void 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}
803EXPORT_SYMBOL_GPL(pm_wakeup_event); 803EXPORT_SYMBOL_GPL(pm_wakeup_dev_event);
804 804
805void pm_print_active_wakeup_sources(void) 805void 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
862void pm_system_wakeup(void) 862void 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}
867EXPORT_SYMBOL_GPL(pm_system_wakeup); 867EXPORT_SYMBOL_GPL(pm_system_wakeup);
868 868
869void pm_wakeup_clear(void) 869void pm_system_cancel_wakeup(void)
870{
871 atomic_dec(&pm_abort_suspend);
872}
873
874void 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
875void pm_system_irq_wakeup(unsigned int irq_number) 881void 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);
106extern void pm_stay_awake(struct device *dev); 106extern void pm_stay_awake(struct device *dev);
107extern void __pm_relax(struct wakeup_source *ws); 107extern void __pm_relax(struct wakeup_source *ws);
108extern void pm_relax(struct device *dev); 108extern void pm_relax(struct device *dev);
109extern void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec); 109extern void pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard);
110extern void pm_wakeup_event(struct device *dev, unsigned int msec); 110extern 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
183static inline void pm_relax(struct device *dev) {} 183static inline void pm_relax(struct device *dev) {}
184 184
185static inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) {} 185static inline void pm_wakeup_ws_event(struct wakeup_source *ws,
186 unsigned int msec, bool hard) {}
186 187
187static inline void pm_wakeup_event(struct device *dev, unsigned int msec) {} 188static 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
206static inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
207{
208 return pm_wakeup_ws_event(ws, msec, false);
209}
210
211static inline void pm_wakeup_event(struct device *dev, unsigned int msec)
212{
213 return pm_wakeup_dev_event(dev, msec, false);
214}
215
216static 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 {
189struct platform_freeze_ops { 189struct 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
429extern bool pm_wakeup_pending(void); 431extern bool pm_wakeup_pending(void);
430extern void pm_system_wakeup(void); 432extern void pm_system_wakeup(void);
431extern void pm_wakeup_clear(void); 433extern void pm_system_cancel_wakeup(void);
434extern void pm_wakeup_clear(bool reset);
432extern void pm_system_irq_wakeup(unsigned int irq_number); 435extern void pm_system_irq_wakeup(unsigned int irq_number);
433extern bool pm_get_wakeup_count(unsigned int *count, bool block); 436extern bool pm_get_wakeup_count(unsigned int *count, bool block);
434extern bool pm_save_wakeup_count(unsigned int count); 437extern bool pm_save_wakeup_count(unsigned int count);
@@ -478,7 +481,7 @@ static inline int unregister_pm_notifier(struct notifier_block *nb)
478 481
479static inline bool pm_wakeup_pending(void) { return false; } 482static inline bool pm_wakeup_pending(void) { return false; }
480static inline void pm_system_wakeup(void) {} 483static inline void pm_system_wakeup(void) {}
481static inline void pm_wakeup_clear(void) {} 484static inline void pm_wakeup_clear(bool reset) {}
482static inline void pm_system_irq_wakeup(unsigned int irq_number) {} 485static inline void pm_system_irq_wakeup(unsigned int irq_number) {}
483 486
484static inline void lock_system_sleep(void) {} 487static 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
73static void freeze_enter(void) 73static 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
107static 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
103void freeze_wake(void) 126void 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();