summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-09-17 03:35:35 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-09-17 03:35:35 -0400
commit1b531e55c52bbe2927e2c3490d47c82113d303e7 (patch)
tree9e0f3cc50d552165fc146057e6bea87db31d47c1
parent78c0f050847cac4c43dbfc1916a63d1557c74ac0 (diff)
parentb90ff3554aa3e123bb7e6d08789f6fd92d86ddde (diff)
Merge suspend-to-idle rework material for v5.4.
* pm-s2idle-rework: (21 commits) ACPI: PM: s2idle: Always set up EC GPE for system wakeup ACPI: PM: s2idle: Avoid rearming SCI for wakeup unnecessarily PM: suspend: Fix platform_suspend_prepare_noirq() intel-hid: Disable button array during suspend-to-idle intel-hid: intel-vbtn: Avoid leaking wakeup_mode set ACPI: PM: s2idle: Execute LPS0 _DSM functions with suspended devices ACPI: EC: PM: Make acpi_ec_dispatch_gpe() print debug message ACPI: EC: PM: Consolidate some code depending on PM_SLEEP ACPI: PM: s2idle: Eliminate acpi_sleep_no_ec_events() ACPI: PM: s2idle: Switch EC over to polling during "noirq" suspend ACPI: PM: s2idle: Add acpi.sleep_no_lps0 module parameter ACPI: PM: s2idle: Rearrange lps0_device_attach() ACPI: PM: Set up EC GPE for system wakeup from drivers that need it PM: sleep: Drop dpm_noirq_begin() and dpm_noirq_end() PM: sleep: Integrate suspend-to-idle with generig suspend flow PM: sleep: Simplify suspend-to-idle control flow ACPI: PM: Set s2idle_wakeup earlier and clear it later PM: sleep: Fix possible overflow in pm_system_cancel_wakeup() ACPI: EC: Return bool from acpi_ec_dispatch_gpe() ACPICA: Return u32 from acpi_dispatch_gpe() ...
-rw-r--r--drivers/acpi/acpica/evxfgpe.c6
-rw-r--r--drivers/acpi/ec.c57
-rw-r--r--drivers/acpi/internal.h6
-rw-r--r--drivers/acpi/sleep.c165
-rw-r--r--drivers/base/power/main.c35
-rw-r--r--drivers/base/power/wakeup.c2
-rw-r--r--drivers/platform/x86/intel-hid.c36
-rw-r--r--drivers/platform/x86/intel-vbtn.c20
-rw-r--r--include/acpi/acpixf.h8
-rw-r--r--include/linux/acpi.h4
-rw-r--r--include/linux/interrupt.h1
-rw-r--r--include/linux/pm.h4
-rw-r--r--include/linux/suspend.h4
-rw-r--r--kernel/irq/pm.c20
-rw-r--r--kernel/power/suspend.c65
15 files changed, 243 insertions, 190 deletions
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c
index 710488ec59e9..04a40d563dd6 100644
--- a/drivers/acpi/acpica/evxfgpe.c
+++ b/drivers/acpi/acpica/evxfgpe.c
@@ -644,17 +644,17 @@ ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
644 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 644 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
645 * gpe_number - GPE level within the GPE block 645 * gpe_number - GPE level within the GPE block
646 * 646 *
647 * RETURN: None 647 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
648 * 648 *
649 * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function 649 * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function
650 * (e.g. EC) or method (e.g. _Lxx/_Exx) handler. 650 * (e.g. EC) or method (e.g. _Lxx/_Exx) handler.
651 * 651 *
652 ******************************************************************************/ 652 ******************************************************************************/
653void acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number) 653u32 acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number)
654{ 654{
655 ACPI_FUNCTION_TRACE(acpi_dispatch_gpe); 655 ACPI_FUNCTION_TRACE(acpi_dispatch_gpe);
656 656
657 acpi_ev_detect_gpe(gpe_device, NULL, gpe_number); 657 return acpi_ev_detect_gpe(gpe_device, NULL, gpe_number);
658} 658}
659 659
660ACPI_EXPORT_SYMBOL(acpi_dispatch_gpe) 660ACPI_EXPORT_SYMBOL(acpi_dispatch_gpe)
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index c33756ed3304..da1e5c5ce150 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -25,6 +25,7 @@
25#include <linux/list.h> 25#include <linux/list.h>
26#include <linux/spinlock.h> 26#include <linux/spinlock.h>
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/suspend.h>
28#include <linux/acpi.h> 29#include <linux/acpi.h>
29#include <linux/dmi.h> 30#include <linux/dmi.h>
30#include <asm/io.h> 31#include <asm/io.h>
@@ -1048,24 +1049,6 @@ void acpi_ec_unblock_transactions(void)
1048 acpi_ec_start(first_ec, true); 1049 acpi_ec_start(first_ec, true);
1049} 1050}
1050 1051
1051void acpi_ec_mark_gpe_for_wake(void)
1052{
1053 if (first_ec && !ec_no_wakeup)
1054 acpi_mark_gpe_for_wake(NULL, first_ec->gpe);
1055}
1056
1057void acpi_ec_set_gpe_wake_mask(u8 action)
1058{
1059 if (first_ec && !ec_no_wakeup)
1060 acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action);
1061}
1062
1063void acpi_ec_dispatch_gpe(void)
1064{
1065 if (first_ec)
1066 acpi_dispatch_gpe(NULL, first_ec->gpe);
1067}
1068
1069/* -------------------------------------------------------------------------- 1052/* --------------------------------------------------------------------------
1070 Event Management 1053 Event Management
1071 -------------------------------------------------------------------------- */ 1054 -------------------------------------------------------------------------- */
@@ -1931,7 +1914,7 @@ static int acpi_ec_suspend(struct device *dev)
1931 struct acpi_ec *ec = 1914 struct acpi_ec *ec =
1932 acpi_driver_data(to_acpi_device(dev)); 1915 acpi_driver_data(to_acpi_device(dev));
1933 1916
1934 if (acpi_sleep_no_ec_events() && ec_freeze_events) 1917 if (!pm_suspend_no_platform() && ec_freeze_events)
1935 acpi_ec_disable_event(ec); 1918 acpi_ec_disable_event(ec);
1936 return 0; 1919 return 0;
1937} 1920}
@@ -1948,8 +1931,7 @@ static int acpi_ec_suspend_noirq(struct device *dev)
1948 ec->reference_count >= 1) 1931 ec->reference_count >= 1)
1949 acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE); 1932 acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE);
1950 1933
1951 if (acpi_sleep_no_ec_events()) 1934 acpi_ec_enter_noirq(ec);
1952 acpi_ec_enter_noirq(ec);
1953 1935
1954 return 0; 1936 return 0;
1955} 1937}
@@ -1958,8 +1940,7 @@ static int acpi_ec_resume_noirq(struct device *dev)
1958{ 1940{
1959 struct acpi_ec *ec = acpi_driver_data(to_acpi_device(dev)); 1941 struct acpi_ec *ec = acpi_driver_data(to_acpi_device(dev));
1960 1942
1961 if (acpi_sleep_no_ec_events()) 1943 acpi_ec_leave_noirq(ec);
1962 acpi_ec_leave_noirq(ec);
1963 1944
1964 if (ec_no_wakeup && test_bit(EC_FLAGS_STARTED, &ec->flags) && 1945 if (ec_no_wakeup && test_bit(EC_FLAGS_STARTED, &ec->flags) &&
1965 ec->reference_count >= 1) 1946 ec->reference_count >= 1)
@@ -1976,7 +1957,35 @@ static int acpi_ec_resume(struct device *dev)
1976 acpi_ec_enable_event(ec); 1957 acpi_ec_enable_event(ec);
1977 return 0; 1958 return 0;
1978} 1959}
1979#endif 1960
1961void acpi_ec_mark_gpe_for_wake(void)
1962{
1963 if (first_ec && !ec_no_wakeup)
1964 acpi_mark_gpe_for_wake(NULL, first_ec->gpe);
1965}
1966EXPORT_SYMBOL_GPL(acpi_ec_mark_gpe_for_wake);
1967
1968void acpi_ec_set_gpe_wake_mask(u8 action)
1969{
1970 if (pm_suspend_no_platform() && first_ec && !ec_no_wakeup)
1971 acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action);
1972}
1973
1974bool acpi_ec_dispatch_gpe(void)
1975{
1976 u32 ret;
1977
1978 if (!first_ec)
1979 return false;
1980
1981 ret = acpi_dispatch_gpe(NULL, first_ec->gpe);
1982 if (ret == ACPI_INTERRUPT_HANDLED) {
1983 pm_pr_dbg("EC GPE dispatched\n");
1984 return true;
1985 }
1986 return false;
1987}
1988#endif /* CONFIG_PM_SLEEP */
1980 1989
1981static const struct dev_pm_ops acpi_ec_pm = { 1990static const struct dev_pm_ops acpi_ec_pm = {
1982 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(acpi_ec_suspend_noirq, acpi_ec_resume_noirq) 1991 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(acpi_ec_suspend_noirq, acpi_ec_resume_noirq)
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index f4c2fe6be4f2..afe6636f9ad3 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -194,9 +194,6 @@ void acpi_ec_ecdt_probe(void);
194void acpi_ec_dsdt_probe(void); 194void acpi_ec_dsdt_probe(void);
195void acpi_ec_block_transactions(void); 195void acpi_ec_block_transactions(void);
196void acpi_ec_unblock_transactions(void); 196void acpi_ec_unblock_transactions(void);
197void acpi_ec_mark_gpe_for_wake(void);
198void acpi_ec_set_gpe_wake_mask(u8 action);
199void acpi_ec_dispatch_gpe(void);
200int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, 197int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
201 acpi_handle handle, acpi_ec_query_func func, 198 acpi_handle handle, acpi_ec_query_func func,
202 void *data); 199 void *data);
@@ -204,6 +201,7 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit);
204 201
205#ifdef CONFIG_PM_SLEEP 202#ifdef CONFIG_PM_SLEEP
206void acpi_ec_flush_work(void); 203void acpi_ec_flush_work(void);
204bool acpi_ec_dispatch_gpe(void);
207#endif 205#endif
208 206
209 207
@@ -212,11 +210,9 @@ void acpi_ec_flush_work(void);
212 -------------------------------------------------------------------------- */ 210 -------------------------------------------------------------------------- */
213#ifdef CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT 211#ifdef CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT
214extern bool acpi_s2idle_wakeup(void); 212extern bool acpi_s2idle_wakeup(void);
215extern bool acpi_sleep_no_ec_events(void);
216extern int acpi_sleep_init(void); 213extern int acpi_sleep_init(void);
217#else 214#else
218static inline bool acpi_s2idle_wakeup(void) { return false; } 215static inline bool acpi_s2idle_wakeup(void) { return false; }
219static inline bool acpi_sleep_no_ec_events(void) { return true; }
220static inline int acpi_sleep_init(void) { return -ENXIO; } 216static inline int acpi_sleep_init(void) { return -ENXIO; }
221#endif 217#endif
222 218
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index f0fe7c15d657..9fa77d72ef27 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -89,6 +89,10 @@ bool acpi_sleep_state_supported(u8 sleep_state)
89} 89}
90 90
91#ifdef CONFIG_ACPI_SLEEP 91#ifdef CONFIG_ACPI_SLEEP
92static bool sleep_no_lps0 __read_mostly;
93module_param(sleep_no_lps0, bool, 0644);
94MODULE_PARM_DESC(sleep_no_lps0, "Do not use the special LPS0 device interface");
95
92static u32 acpi_target_sleep_state = ACPI_STATE_S0; 96static u32 acpi_target_sleep_state = ACPI_STATE_S0;
93 97
94u32 acpi_target_system_state(void) 98u32 acpi_target_system_state(void)
@@ -158,11 +162,11 @@ static int __init init_nvs_nosave(const struct dmi_system_id *d)
158 return 0; 162 return 0;
159} 163}
160 164
161static bool acpi_sleep_no_lps0; 165static bool acpi_sleep_default_s3;
162 166
163static int __init init_no_lps0(const struct dmi_system_id *d) 167static int __init init_default_s3(const struct dmi_system_id *d)
164{ 168{
165 acpi_sleep_no_lps0 = true; 169 acpi_sleep_default_s3 = true;
166 return 0; 170 return 0;
167} 171}
168 172
@@ -363,7 +367,7 @@ static const struct dmi_system_id acpisleep_dmi_table[] __initconst = {
363 * S0 Idle firmware interface. 367 * S0 Idle firmware interface.
364 */ 368 */
365 { 369 {
366 .callback = init_no_lps0, 370 .callback = init_default_s3,
367 .ident = "Dell XPS13 9360", 371 .ident = "Dell XPS13 9360",
368 .matches = { 372 .matches = {
369 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 373 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
@@ -376,7 +380,7 @@ static const struct dmi_system_id acpisleep_dmi_table[] __initconst = {
376 * https://bugzilla.kernel.org/show_bug.cgi?id=199057). 380 * https://bugzilla.kernel.org/show_bug.cgi?id=199057).
377 */ 381 */
378 { 382 {
379 .callback = init_no_lps0, 383 .callback = init_default_s3,
380 .ident = "ThinkPad X1 Tablet(2016)", 384 .ident = "ThinkPad X1 Tablet(2016)",
381 .matches = { 385 .matches = {
382 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 386 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
@@ -524,8 +528,9 @@ static void acpi_pm_end(void)
524 acpi_sleep_tts_switch(acpi_target_sleep_state); 528 acpi_sleep_tts_switch(acpi_target_sleep_state);
525} 529}
526#else /* !CONFIG_ACPI_SLEEP */ 530#else /* !CONFIG_ACPI_SLEEP */
531#define sleep_no_lps0 (1)
527#define acpi_target_sleep_state ACPI_STATE_S0 532#define acpi_target_sleep_state ACPI_STATE_S0
528#define acpi_sleep_no_lps0 (false) 533#define acpi_sleep_default_s3 (1)
529static inline void acpi_sleep_dmi_check(void) {} 534static inline void acpi_sleep_dmi_check(void) {}
530#endif /* CONFIG_ACPI_SLEEP */ 535#endif /* CONFIG_ACPI_SLEEP */
531 536
@@ -691,7 +696,6 @@ static const struct platform_suspend_ops acpi_suspend_ops_old = {
691 .recover = acpi_pm_finish, 696 .recover = acpi_pm_finish,
692}; 697};
693 698
694static bool s2idle_in_progress;
695static bool s2idle_wakeup; 699static bool s2idle_wakeup;
696 700
697/* 701/*
@@ -904,42 +908,43 @@ static int lps0_device_attach(struct acpi_device *adev,
904 if (lps0_device_handle) 908 if (lps0_device_handle)
905 return 0; 909 return 0;
906 910
907 if (acpi_sleep_no_lps0) {
908 acpi_handle_info(adev->handle,
909 "Low Power S0 Idle interface disabled\n");
910 return 0;
911 }
912
913 if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) 911 if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0))
914 return 0; 912 return 0;
915 913
916 guid_parse(ACPI_LPS0_DSM_UUID, &lps0_dsm_guid); 914 guid_parse(ACPI_LPS0_DSM_UUID, &lps0_dsm_guid);
917 /* Check if the _DSM is present and as expected. */ 915 /* Check if the _DSM is present and as expected. */
918 out_obj = acpi_evaluate_dsm(adev->handle, &lps0_dsm_guid, 1, 0, NULL); 916 out_obj = acpi_evaluate_dsm(adev->handle, &lps0_dsm_guid, 1, 0, NULL);
919 if (out_obj && out_obj->type == ACPI_TYPE_BUFFER) { 917 if (!out_obj || out_obj->type != ACPI_TYPE_BUFFER) {
920 char bitmask = *(char *)out_obj->buffer.pointer;
921
922 lps0_dsm_func_mask = bitmask;
923 lps0_device_handle = adev->handle;
924 /*
925 * Use suspend-to-idle by default if the default
926 * suspend mode was not set from the command line.
927 */
928 if (mem_sleep_default > PM_SUSPEND_MEM)
929 mem_sleep_current = PM_SUSPEND_TO_IDLE;
930
931 acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n",
932 bitmask);
933
934 acpi_ec_mark_gpe_for_wake();
935 } else {
936 acpi_handle_debug(adev->handle, 918 acpi_handle_debug(adev->handle,
937 "_DSM function 0 evaluation failed\n"); 919 "_DSM function 0 evaluation failed\n");
920 return 0;
938 } 921 }
922
923 lps0_dsm_func_mask = *(char *)out_obj->buffer.pointer;
924
939 ACPI_FREE(out_obj); 925 ACPI_FREE(out_obj);
940 926
927 acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n",
928 lps0_dsm_func_mask);
929
930 lps0_device_handle = adev->handle;
931
941 lpi_device_get_constraints(); 932 lpi_device_get_constraints();
942 933
934 /*
935 * Use suspend-to-idle by default if the default suspend mode was not
936 * set from the command line.
937 */
938 if (mem_sleep_default > PM_SUSPEND_MEM && !acpi_sleep_default_s3)
939 mem_sleep_current = PM_SUSPEND_TO_IDLE;
940
941 /*
942 * Some LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U, require the
943 * EC GPE to be enabled while suspended for certain wakeup devices to
944 * work, so mark it as wakeup-capable.
945 */
946 acpi_ec_mark_gpe_for_wake();
947
943 return 0; 948 return 0;
944} 949}
945 950
@@ -951,98 +956,110 @@ static struct acpi_scan_handler lps0_handler = {
951static int acpi_s2idle_begin(void) 956static int acpi_s2idle_begin(void)
952{ 957{
953 acpi_scan_lock_acquire(); 958 acpi_scan_lock_acquire();
954 s2idle_in_progress = true;
955 return 0; 959 return 0;
956} 960}
957 961
958static int acpi_s2idle_prepare(void) 962static int acpi_s2idle_prepare(void)
959{ 963{
960 if (lps0_device_handle) { 964 if (acpi_sci_irq_valid()) {
961 acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF); 965 enable_irq_wake(acpi_sci_irq);
962 acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY);
963
964 acpi_ec_set_gpe_wake_mask(ACPI_GPE_ENABLE); 966 acpi_ec_set_gpe_wake_mask(ACPI_GPE_ENABLE);
965 } 967 }
966 968
967 if (acpi_sci_irq_valid())
968 enable_irq_wake(acpi_sci_irq);
969
970 acpi_enable_wakeup_devices(ACPI_STATE_S0); 969 acpi_enable_wakeup_devices(ACPI_STATE_S0);
971 970
972 /* Change the configuration of GPEs to avoid spurious wakeup. */ 971 /* Change the configuration of GPEs to avoid spurious wakeup. */
973 acpi_enable_all_wakeup_gpes(); 972 acpi_enable_all_wakeup_gpes();
974 acpi_os_wait_events_complete(); 973 acpi_os_wait_events_complete();
974
975 s2idle_wakeup = true;
975 return 0; 976 return 0;
976} 977}
977 978
978static void acpi_s2idle_wake(void) 979static int acpi_s2idle_prepare_late(void)
979{ 980{
980 if (!lps0_device_handle) 981 if (!lps0_device_handle || sleep_no_lps0)
981 return; 982 return 0;
982 983
983 if (pm_debug_messages_on) 984 if (pm_debug_messages_on)
984 lpi_check_constraints(); 985 lpi_check_constraints();
985 986
987 acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF);
988 acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY);
989
990 return 0;
991}
992
993static void acpi_s2idle_wake(void)
994{
995 /*
996 * If IRQD_WAKEUP_ARMED is set for the SCI at this point, the SCI has
997 * not triggered while suspended, so bail out.
998 */
999 if (!acpi_sci_irq_valid() ||
1000 irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq)))
1001 return;
1002
986 /* 1003 /*
987 * If IRQD_WAKEUP_ARMED is not set for the SCI at this point, it means 1004 * If there are EC events to process, the wakeup may be a spurious one
988 * that the SCI has triggered while suspended, so cancel the wakeup in 1005 * coming from the EC.
989 * case it has not been a wakeup event (the GPEs will be checked later).
990 */ 1006 */
991 if (acpi_sci_irq_valid() && 1007 if (acpi_ec_dispatch_gpe()) {
992 !irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) { 1008 /*
1009 * Cancel the wakeup and process all pending events in case
1010 * there are any wakeup ones in there.
1011 *
1012 * Note that if any non-EC GPEs are active at this point, the
1013 * SCI will retrigger after the rearming below, so no events
1014 * should be missed by canceling the wakeup here.
1015 */
993 pm_system_cancel_wakeup(); 1016 pm_system_cancel_wakeup();
994 s2idle_wakeup = true;
995 /* 1017 /*
996 * On some platforms with the LPS0 _DSM device noirq resume 1018 * The EC driver uses the system workqueue and an additional
997 * takes too much time for EC wakeup events to survive, so look 1019 * special one, so those need to be flushed too.
998 * for them now.
999 */ 1020 */
1000 acpi_ec_dispatch_gpe(); 1021 acpi_os_wait_events_complete(); /* synchronize EC GPE processing */
1022 acpi_ec_flush_work();
1023 acpi_os_wait_events_complete(); /* synchronize Notify handling */
1024
1025 rearm_wake_irq(acpi_sci_irq);
1001 } 1026 }
1002} 1027}
1003 1028
1004static void acpi_s2idle_sync(void) 1029static void acpi_s2idle_restore_early(void)
1005{ 1030{
1006 /* 1031 if (!lps0_device_handle || sleep_no_lps0)
1007 * Process all pending events in case there are any wakeup ones. 1032 return;
1008 * 1033
1009 * The EC driver uses the system workqueue and an additional special 1034 acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT);
1010 * one, so those need to be flushed too. 1035 acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON);
1011 */
1012 acpi_os_wait_events_complete(); /* synchronize SCI IRQ handling */
1013 acpi_ec_flush_work();
1014 acpi_os_wait_events_complete(); /* synchronize Notify handling */
1015 s2idle_wakeup = false;
1016} 1036}
1017 1037
1018static void acpi_s2idle_restore(void) 1038static void acpi_s2idle_restore(void)
1019{ 1039{
1040 s2idle_wakeup = false;
1041
1020 acpi_enable_all_runtime_gpes(); 1042 acpi_enable_all_runtime_gpes();
1021 1043
1022 acpi_disable_wakeup_devices(ACPI_STATE_S0); 1044 acpi_disable_wakeup_devices(ACPI_STATE_S0);
1023 1045
1024 if (acpi_sci_irq_valid()) 1046 if (acpi_sci_irq_valid()) {
1025 disable_irq_wake(acpi_sci_irq);
1026
1027 if (lps0_device_handle) {
1028 acpi_ec_set_gpe_wake_mask(ACPI_GPE_DISABLE); 1047 acpi_ec_set_gpe_wake_mask(ACPI_GPE_DISABLE);
1029 1048 disable_irq_wake(acpi_sci_irq);
1030 acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT);
1031 acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON);
1032 } 1049 }
1033} 1050}
1034 1051
1035static void acpi_s2idle_end(void) 1052static void acpi_s2idle_end(void)
1036{ 1053{
1037 s2idle_in_progress = false;
1038 acpi_scan_lock_release(); 1054 acpi_scan_lock_release();
1039} 1055}
1040 1056
1041static const struct platform_s2idle_ops acpi_s2idle_ops = { 1057static const struct platform_s2idle_ops acpi_s2idle_ops = {
1042 .begin = acpi_s2idle_begin, 1058 .begin = acpi_s2idle_begin,
1043 .prepare = acpi_s2idle_prepare, 1059 .prepare = acpi_s2idle_prepare,
1060 .prepare_late = acpi_s2idle_prepare_late,
1044 .wake = acpi_s2idle_wake, 1061 .wake = acpi_s2idle_wake,
1045 .sync = acpi_s2idle_sync, 1062 .restore_early = acpi_s2idle_restore_early,
1046 .restore = acpi_s2idle_restore, 1063 .restore = acpi_s2idle_restore,
1047 .end = acpi_s2idle_end, 1064 .end = acpi_s2idle_end,
1048}; 1065};
@@ -1063,7 +1080,6 @@ static void acpi_sleep_suspend_setup(void)
1063} 1080}
1064 1081
1065#else /* !CONFIG_SUSPEND */ 1082#else /* !CONFIG_SUSPEND */
1066#define s2idle_in_progress (false)
1067#define s2idle_wakeup (false) 1083#define s2idle_wakeup (false)
1068#define lps0_device_handle (NULL) 1084#define lps0_device_handle (NULL)
1069static inline void acpi_sleep_suspend_setup(void) {} 1085static inline void acpi_sleep_suspend_setup(void) {}
@@ -1074,11 +1090,6 @@ bool acpi_s2idle_wakeup(void)
1074 return s2idle_wakeup; 1090 return s2idle_wakeup;
1075} 1091}
1076 1092
1077bool acpi_sleep_no_ec_events(void)
1078{
1079 return !s2idle_in_progress || !lps0_device_handle;
1080}
1081
1082#ifdef CONFIG_PM_SLEEP 1093#ifdef CONFIG_PM_SLEEP
1083static u32 saved_bm_rld; 1094static u32 saved_bm_rld;
1084 1095
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 7fb2c39bc725..134a8af51511 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -716,7 +716,7 @@ static void async_resume_noirq(void *data, async_cookie_t cookie)
716 put_device(dev); 716 put_device(dev);
717} 717}
718 718
719void dpm_noirq_resume_devices(pm_message_t state) 719static void dpm_noirq_resume_devices(pm_message_t state)
720{ 720{
721 struct device *dev; 721 struct device *dev;
722 ktime_t starttime = ktime_get(); 722 ktime_t starttime = ktime_get();
@@ -760,13 +760,6 @@ void dpm_noirq_resume_devices(pm_message_t state)
760 trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, false); 760 trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, false);
761} 761}
762 762
763void dpm_noirq_end(void)
764{
765 resume_device_irqs();
766 device_wakeup_disarm_wake_irqs();
767 cpuidle_resume();
768}
769
770/** 763/**
771 * dpm_resume_noirq - Execute "noirq resume" callbacks for all devices. 764 * dpm_resume_noirq - Execute "noirq resume" callbacks for all devices.
772 * @state: PM transition of the system being carried out. 765 * @state: PM transition of the system being carried out.
@@ -777,7 +770,11 @@ void dpm_noirq_end(void)
777void dpm_resume_noirq(pm_message_t state) 770void dpm_resume_noirq(pm_message_t state)
778{ 771{
779 dpm_noirq_resume_devices(state); 772 dpm_noirq_resume_devices(state);
780 dpm_noirq_end(); 773
774 resume_device_irqs();
775 device_wakeup_disarm_wake_irqs();
776
777 cpuidle_resume();
781} 778}
782 779
783static pm_callback_t dpm_subsys_resume_early_cb(struct device *dev, 780static pm_callback_t dpm_subsys_resume_early_cb(struct device *dev,
@@ -1291,11 +1288,6 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a
1291 if (async_error) 1288 if (async_error)
1292 goto Complete; 1289 goto Complete;
1293 1290
1294 if (pm_wakeup_pending()) {
1295 async_error = -EBUSY;
1296 goto Complete;
1297 }
1298
1299 if (dev->power.syscore || dev->power.direct_complete) 1291 if (dev->power.syscore || dev->power.direct_complete)
1300 goto Complete; 1292 goto Complete;
1301 1293
@@ -1362,14 +1354,7 @@ static int device_suspend_noirq(struct device *dev)
1362 return __device_suspend_noirq(dev, pm_transition, false); 1354 return __device_suspend_noirq(dev, pm_transition, false);
1363} 1355}
1364 1356
1365void dpm_noirq_begin(void) 1357static int dpm_noirq_suspend_devices(pm_message_t state)
1366{
1367 cpuidle_pause();
1368 device_wakeup_arm_wake_irqs();
1369 suspend_device_irqs();
1370}
1371
1372int dpm_noirq_suspend_devices(pm_message_t state)
1373{ 1358{
1374 ktime_t starttime = ktime_get(); 1359 ktime_t starttime = ktime_get();
1375 int error = 0; 1360 int error = 0;
@@ -1426,7 +1411,11 @@ int dpm_suspend_noirq(pm_message_t state)
1426{ 1411{
1427 int ret; 1412 int ret;
1428 1413
1429 dpm_noirq_begin(); 1414 cpuidle_pause();
1415
1416 device_wakeup_arm_wake_irqs();
1417 suspend_device_irqs();
1418
1430 ret = dpm_noirq_suspend_devices(state); 1419 ret = dpm_noirq_suspend_devices(state);
1431 if (ret) 1420 if (ret)
1432 dpm_resume_noirq(resume_event(state)); 1421 dpm_resume_noirq(resume_event(state));
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index e58b070985b1..5817b51d2b15 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -879,7 +879,7 @@ EXPORT_SYMBOL_GPL(pm_system_wakeup);
879 879
880void pm_system_cancel_wakeup(void) 880void pm_system_cancel_wakeup(void)
881{ 881{
882 atomic_dec(&pm_abort_suspend); 882 atomic_dec_if_positive(&pm_abort_suspend);
883} 883}
884 884
885void pm_wakeup_clear(bool reset) 885void pm_wakeup_clear(bool reset)
diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c
index bc0d55a59015..ef6d4bd77b1a 100644
--- a/drivers/platform/x86/intel-hid.c
+++ b/drivers/platform/x86/intel-hid.c
@@ -253,35 +253,45 @@ static void intel_button_array_enable(struct device *device, bool enable)
253 253
254static int intel_hid_pm_prepare(struct device *device) 254static int intel_hid_pm_prepare(struct device *device)
255{ 255{
256 struct intel_hid_priv *priv = dev_get_drvdata(device); 256 if (device_may_wakeup(device)) {
257 struct intel_hid_priv *priv = dev_get_drvdata(device);
257 258
258 priv->wakeup_mode = true; 259 priv->wakeup_mode = true;
260 }
259 return 0; 261 return 0;
260} 262}
261 263
264static void intel_hid_pm_complete(struct device *device)
265{
266 struct intel_hid_priv *priv = dev_get_drvdata(device);
267
268 priv->wakeup_mode = false;
269}
270
262static int intel_hid_pl_suspend_handler(struct device *device) 271static int intel_hid_pl_suspend_handler(struct device *device)
263{ 272{
264 if (pm_suspend_via_firmware()) { 273 intel_button_array_enable(device, false);
274
275 if (!pm_suspend_no_platform())
265 intel_hid_set_enable(device, false); 276 intel_hid_set_enable(device, false);
266 intel_button_array_enable(device, false); 277
267 }
268 return 0; 278 return 0;
269} 279}
270 280
271static int intel_hid_pl_resume_handler(struct device *device) 281static int intel_hid_pl_resume_handler(struct device *device)
272{ 282{
273 struct intel_hid_priv *priv = dev_get_drvdata(device); 283 intel_hid_pm_complete(device);
274 284
275 priv->wakeup_mode = false; 285 if (!pm_suspend_no_platform())
276 if (pm_resume_via_firmware()) {
277 intel_hid_set_enable(device, true); 286 intel_hid_set_enable(device, true);
278 intel_button_array_enable(device, true); 287
279 } 288 intel_button_array_enable(device, true);
280 return 0; 289 return 0;
281} 290}
282 291
283static const struct dev_pm_ops intel_hid_pl_pm_ops = { 292static const struct dev_pm_ops intel_hid_pl_pm_ops = {
284 .prepare = intel_hid_pm_prepare, 293 .prepare = intel_hid_pm_prepare,
294 .complete = intel_hid_pm_complete,
285 .freeze = intel_hid_pl_suspend_handler, 295 .freeze = intel_hid_pl_suspend_handler,
286 .thaw = intel_hid_pl_resume_handler, 296 .thaw = intel_hid_pl_resume_handler,
287 .restore = intel_hid_pl_resume_handler, 297 .restore = intel_hid_pl_resume_handler,
@@ -491,6 +501,12 @@ static int intel_hid_probe(struct platform_device *device)
491 } 501 }
492 502
493 device_init_wakeup(&device->dev, true); 503 device_init_wakeup(&device->dev, true);
504 /*
505 * In order for system wakeup to work, the EC GPE has to be marked as
506 * a wakeup one, so do that here (this setting will persist, but it has
507 * no effect until the wakeup mask is set for the EC GPE).
508 */
509 acpi_ec_mark_gpe_for_wake();
494 return 0; 510 return 0;
495 511
496err_remove_notify: 512err_remove_notify:
diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c
index a0d0cecff55f..b74932307d69 100644
--- a/drivers/platform/x86/intel-vbtn.c
+++ b/drivers/platform/x86/intel-vbtn.c
@@ -176,6 +176,12 @@ static int intel_vbtn_probe(struct platform_device *device)
176 return -EBUSY; 176 return -EBUSY;
177 177
178 device_init_wakeup(&device->dev, true); 178 device_init_wakeup(&device->dev, true);
179 /*
180 * In order for system wakeup to work, the EC GPE has to be marked as
181 * a wakeup one, so do that here (this setting will persist, but it has
182 * no effect until the wakeup mask is set for the EC GPE).
183 */
184 acpi_ec_mark_gpe_for_wake();
179 return 0; 185 return 0;
180} 186}
181 187
@@ -195,22 +201,30 @@ static int intel_vbtn_remove(struct platform_device *device)
195 201
196static int intel_vbtn_pm_prepare(struct device *dev) 202static int intel_vbtn_pm_prepare(struct device *dev)
197{ 203{
198 struct intel_vbtn_priv *priv = dev_get_drvdata(dev); 204 if (device_may_wakeup(dev)) {
205 struct intel_vbtn_priv *priv = dev_get_drvdata(dev);
199 206
200 priv->wakeup_mode = true; 207 priv->wakeup_mode = true;
208 }
201 return 0; 209 return 0;
202} 210}
203 211
204static int intel_vbtn_pm_resume(struct device *dev) 212static void intel_vbtn_pm_complete(struct device *dev)
205{ 213{
206 struct intel_vbtn_priv *priv = dev_get_drvdata(dev); 214 struct intel_vbtn_priv *priv = dev_get_drvdata(dev);
207 215
208 priv->wakeup_mode = false; 216 priv->wakeup_mode = false;
217}
218
219static int intel_vbtn_pm_resume(struct device *dev)
220{
221 intel_vbtn_pm_complete(dev);
209 return 0; 222 return 0;
210} 223}
211 224
212static const struct dev_pm_ops intel_vbtn_pm_ops = { 225static const struct dev_pm_ops intel_vbtn_pm_ops = {
213 .prepare = intel_vbtn_pm_prepare, 226 .prepare = intel_vbtn_pm_prepare,
227 .complete = intel_vbtn_pm_complete,
214 .resume = intel_vbtn_pm_resume, 228 .resume = intel_vbtn_pm_resume,
215 .restore = intel_vbtn_pm_resume, 229 .restore = intel_vbtn_pm_resume,
216 .thaw = intel_vbtn_pm_resume, 230 .thaw = intel_vbtn_pm_resume,
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 3845c8fcc94e..4ed603a3b448 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -297,6 +297,9 @@ ACPI_GLOBAL(u8, acpi_gbl_system_awake_and_running);
297#define ACPI_HW_DEPENDENT_RETURN_OK(prototype) \ 297#define ACPI_HW_DEPENDENT_RETURN_OK(prototype) \
298 ACPI_EXTERNAL_RETURN_OK(prototype) 298 ACPI_EXTERNAL_RETURN_OK(prototype)
299 299
300#define ACPI_HW_DEPENDENT_RETURN_UINT32(prototype) \
301 ACPI_EXTERNAL_RETURN_UINT32(prototype)
302
300#define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \ 303#define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \
301 ACPI_EXTERNAL_RETURN_VOID(prototype) 304 ACPI_EXTERNAL_RETURN_VOID(prototype)
302 305
@@ -307,6 +310,9 @@ ACPI_GLOBAL(u8, acpi_gbl_system_awake_and_running);
307#define ACPI_HW_DEPENDENT_RETURN_OK(prototype) \ 310#define ACPI_HW_DEPENDENT_RETURN_OK(prototype) \
308 static ACPI_INLINE prototype {return(AE_OK);} 311 static ACPI_INLINE prototype {return(AE_OK);}
309 312
313#define ACPI_HW_DEPENDENT_RETURN_UINT32(prototype) \
314 static ACPI_INLINE prototype {return(0);}
315
310#define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \ 316#define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \
311 static ACPI_INLINE prototype {return;} 317 static ACPI_INLINE prototype {return;}
312 318
@@ -738,7 +744,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
738 u32 gpe_number, 744 u32 gpe_number,
739 acpi_event_status 745 acpi_event_status
740 *event_status)) 746 *event_status))
741ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number)) 747ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number))
742ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void)) 748ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void))
743ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void)) 749ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void))
744ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void)) 750ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void))
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 9426b9aaed86..e65a4c5bbeae 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -931,6 +931,8 @@ int acpi_subsys_suspend_noirq(struct device *dev);
931int acpi_subsys_suspend(struct device *dev); 931int acpi_subsys_suspend(struct device *dev);
932int acpi_subsys_freeze(struct device *dev); 932int acpi_subsys_freeze(struct device *dev);
933int acpi_subsys_poweroff(struct device *dev); 933int acpi_subsys_poweroff(struct device *dev);
934void acpi_ec_mark_gpe_for_wake(void);
935void acpi_ec_set_gpe_wake_mask(u8 action);
934#else 936#else
935static inline int acpi_subsys_prepare(struct device *dev) { return 0; } 937static inline int acpi_subsys_prepare(struct device *dev) { return 0; }
936static inline void acpi_subsys_complete(struct device *dev) {} 938static inline void acpi_subsys_complete(struct device *dev) {}
@@ -939,6 +941,8 @@ static inline int acpi_subsys_suspend_noirq(struct device *dev) { return 0; }
939static inline int acpi_subsys_suspend(struct device *dev) { return 0; } 941static inline int acpi_subsys_suspend(struct device *dev) { return 0; }
940static inline int acpi_subsys_freeze(struct device *dev) { return 0; } 942static inline int acpi_subsys_freeze(struct device *dev) { return 0; }
941static inline int acpi_subsys_poweroff(struct device *dev) { return 0; } 943static inline int acpi_subsys_poweroff(struct device *dev) { return 0; }
944static inline void acpi_ec_mark_gpe_for_wake(void) {}
945static inline void acpi_ec_set_gpe_wake_mask(u8 action) {}
942#endif 946#endif
943 947
944#ifdef CONFIG_ACPI 948#ifdef CONFIG_ACPI
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 5b8328a99b2a..0e9cdb3efda7 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -238,6 +238,7 @@ extern void teardown_percpu_nmi(unsigned int irq);
238/* The following three functions are for the core kernel use only. */ 238/* The following three functions are for the core kernel use only. */
239extern void suspend_device_irqs(void); 239extern void suspend_device_irqs(void);
240extern void resume_device_irqs(void); 240extern void resume_device_irqs(void);
241extern void rearm_wake_irq(unsigned int irq);
241 242
242/** 243/**
243 * struct irq_affinity_notify - context for notification of IRQ affinity changes 244 * struct irq_affinity_notify - context for notification of IRQ affinity changes
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 3619a870eaa4..4c441be03079 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -712,8 +712,6 @@ struct dev_pm_domain {
712extern void device_pm_lock(void); 712extern void device_pm_lock(void);
713extern void dpm_resume_start(pm_message_t state); 713extern void dpm_resume_start(pm_message_t state);
714extern void dpm_resume_end(pm_message_t state); 714extern void dpm_resume_end(pm_message_t state);
715extern void dpm_noirq_resume_devices(pm_message_t state);
716extern void dpm_noirq_end(void);
717extern void dpm_resume_noirq(pm_message_t state); 715extern void dpm_resume_noirq(pm_message_t state);
718extern void dpm_resume_early(pm_message_t state); 716extern void dpm_resume_early(pm_message_t state);
719extern void dpm_resume(pm_message_t state); 717extern void dpm_resume(pm_message_t state);
@@ -722,8 +720,6 @@ extern void dpm_complete(pm_message_t state);
722extern void device_pm_unlock(void); 720extern void device_pm_unlock(void);
723extern int dpm_suspend_end(pm_message_t state); 721extern int dpm_suspend_end(pm_message_t state);
724extern int dpm_suspend_start(pm_message_t state); 722extern int dpm_suspend_start(pm_message_t state);
725extern void dpm_noirq_begin(void);
726extern int dpm_noirq_suspend_devices(pm_message_t state);
727extern int dpm_suspend_noirq(pm_message_t state); 723extern int dpm_suspend_noirq(pm_message_t state);
728extern int dpm_suspend_late(pm_message_t state); 724extern int dpm_suspend_late(pm_message_t state);
729extern int dpm_suspend(pm_message_t state); 725extern int dpm_suspend(pm_message_t state);
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 9c0ad1a3a727..6fc8843f1c9e 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -190,8 +190,9 @@ struct platform_suspend_ops {
190struct platform_s2idle_ops { 190struct platform_s2idle_ops {
191 int (*begin)(void); 191 int (*begin)(void);
192 int (*prepare)(void); 192 int (*prepare)(void);
193 int (*prepare_late)(void);
193 void (*wake)(void); 194 void (*wake)(void);
194 void (*sync)(void); 195 void (*restore_early)(void);
195 void (*restore)(void); 196 void (*restore)(void);
196 void (*end)(void); 197 void (*end)(void);
197}; 198};
@@ -336,6 +337,7 @@ static inline void pm_set_suspend_via_firmware(void) {}
336static inline void pm_set_resume_via_firmware(void) {} 337static inline void pm_set_resume_via_firmware(void) {}
337static inline bool pm_suspend_via_firmware(void) { return false; } 338static inline bool pm_suspend_via_firmware(void) { return false; }
338static inline bool pm_resume_via_firmware(void) { return false; } 339static inline bool pm_resume_via_firmware(void) { return false; }
340static inline bool pm_suspend_no_platform(void) { return false; }
339static inline bool pm_suspend_default_s2idle(void) { return false; } 341static inline bool pm_suspend_default_s2idle(void) { return false; }
340 342
341static inline void suspend_set_ops(const struct platform_suspend_ops *ops) {} 343static inline void suspend_set_ops(const struct platform_suspend_ops *ops) {}
diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c
index d6961d3c6f9e..8f557fa1f4fe 100644
--- a/kernel/irq/pm.c
+++ b/kernel/irq/pm.c
@@ -177,6 +177,26 @@ static void resume_irqs(bool want_early)
177} 177}
178 178
179/** 179/**
180 * rearm_wake_irq - rearm a wakeup interrupt line after signaling wakeup
181 * @irq: Interrupt to rearm
182 */
183void rearm_wake_irq(unsigned int irq)
184{
185 unsigned long flags;
186 struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
187
188 if (!desc || !(desc->istate & IRQS_SUSPENDED) ||
189 !irqd_is_wakeup_set(&desc->irq_data))
190 return;
191
192 desc->istate &= ~IRQS_SUSPENDED;
193 irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED);
194 __enable_irq(desc);
195
196 irq_put_desc_busunlock(desc, flags);
197}
198
199/**
180 * irq_pm_syscore_ops - enable interrupt lines early 200 * irq_pm_syscore_ops - enable interrupt lines early
181 * 201 *
182 * Enable all interrupt lines with %IRQF_EARLY_RESUME set. 202 * Enable all interrupt lines with %IRQF_EARLY_RESUME set.
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index c874a7026e24..f3b7239f1892 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -121,43 +121,25 @@ static void s2idle_loop(void)
121{ 121{
122 pm_pr_dbg("suspend-to-idle\n"); 122 pm_pr_dbg("suspend-to-idle\n");
123 123
124 /*
125 * Suspend-to-idle equals:
126 * frozen processes + suspended devices + idle processors.
127 * Thus s2idle_enter() should be called right after all devices have
128 * been suspended.
129 *
130 * Wakeups during the noirq suspend of devices may be spurious, so try
131 * to avoid them upfront.
132 */
124 for (;;) { 133 for (;;) {
125 int error; 134 if (s2idle_ops && s2idle_ops->wake)
126
127 dpm_noirq_begin();
128
129 /*
130 * Suspend-to-idle equals
131 * frozen processes + suspended devices + idle processors.
132 * Thus s2idle_enter() should be called right after
133 * all devices have been suspended.
134 *
135 * Wakeups during the noirq suspend of devices may be spurious,
136 * so prevent them from terminating the loop right away.
137 */
138 error = dpm_noirq_suspend_devices(PMSG_SUSPEND);
139 if (!error)
140 s2idle_enter();
141 else if (error == -EBUSY && pm_wakeup_pending())
142 error = 0;
143
144 if (!error && s2idle_ops && s2idle_ops->wake)
145 s2idle_ops->wake(); 135 s2idle_ops->wake();
146 136
147 dpm_noirq_resume_devices(PMSG_RESUME);
148
149 dpm_noirq_end();
150
151 if (error)
152 break;
153
154 if (s2idle_ops && s2idle_ops->sync)
155 s2idle_ops->sync();
156
157 if (pm_wakeup_pending()) 137 if (pm_wakeup_pending())
158 break; 138 break;
159 139
160 pm_wakeup_clear(false); 140 pm_wakeup_clear(false);
141
142 s2idle_enter();
161 } 143 }
162 144
163 pm_pr_dbg("resume from suspend-to-idle\n"); 145 pm_pr_dbg("resume from suspend-to-idle\n");
@@ -271,14 +253,21 @@ static int platform_suspend_prepare_late(suspend_state_t state)
271 253
272static int platform_suspend_prepare_noirq(suspend_state_t state) 254static int platform_suspend_prepare_noirq(suspend_state_t state)
273{ 255{
274 return state != PM_SUSPEND_TO_IDLE && suspend_ops->prepare_late ? 256 if (state == PM_SUSPEND_TO_IDLE)
275 suspend_ops->prepare_late() : 0; 257 return s2idle_ops && s2idle_ops->prepare_late ?
258 s2idle_ops->prepare_late() : 0;
259
260 return suspend_ops->prepare_late ? suspend_ops->prepare_late() : 0;
276} 261}
277 262
278static void platform_resume_noirq(suspend_state_t state) 263static void platform_resume_noirq(suspend_state_t state)
279{ 264{
280 if (state != PM_SUSPEND_TO_IDLE && suspend_ops->wake) 265 if (state == PM_SUSPEND_TO_IDLE) {
266 if (s2idle_ops && s2idle_ops->restore_early)
267 s2idle_ops->restore_early();
268 } else if (suspend_ops->wake) {
281 suspend_ops->wake(); 269 suspend_ops->wake();
270 }
282} 271}
283 272
284static void platform_resume_early(suspend_state_t state) 273static void platform_resume_early(suspend_state_t state)
@@ -415,11 +404,6 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
415 if (error) 404 if (error)
416 goto Devices_early_resume; 405 goto Devices_early_resume;
417 406
418 if (state == PM_SUSPEND_TO_IDLE && pm_test_level != TEST_PLATFORM) {
419 s2idle_loop();
420 goto Platform_early_resume;
421 }
422
423 error = dpm_suspend_noirq(PMSG_SUSPEND); 407 error = dpm_suspend_noirq(PMSG_SUSPEND);
424 if (error) { 408 if (error) {
425 pr_err("noirq suspend of devices failed\n"); 409 pr_err("noirq suspend of devices failed\n");
@@ -432,6 +416,11 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
432 if (suspend_test(TEST_PLATFORM)) 416 if (suspend_test(TEST_PLATFORM))
433 goto Platform_wake; 417 goto Platform_wake;
434 418
419 if (state == PM_SUSPEND_TO_IDLE) {
420 s2idle_loop();
421 goto Platform_wake;
422 }
423
435 error = suspend_disable_secondary_cpus(); 424 error = suspend_disable_secondary_cpus();
436 if (error || suspend_test(TEST_CPUS)) 425 if (error || suspend_test(TEST_CPUS))
437 goto Enable_cpus; 426 goto Enable_cpus;