summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-06-06 18:57:37 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-06-06 18:57:37 -0400
commitf3b7eaae1b35eb8077610eb7c7db042c9b0645e1 (patch)
tree40cf431ba24ff06e8f2f9a55b056707660b1421a
parent0bae5fd3330be0517fba697e6b228601d421fade (diff)
Revert "ACPI / sleep: Ignore spurious SCI wakeups from suspend-to-idle"
Revert commit eed4d47efe95 (ACPI / sleep: Ignore spurious SCI wakeups from suspend-to-idle) as it turned out to be premature and triggered a number of different issues on various systems. That includes, but is not limited to, premature suspend-to-RAM aborts on Dell XPS 13 (9343) reported by Dominik. The issue the commit in question attempted to address is real and will need to be taken care of going forward, but evidently more work is needed for this purpose. Reported-by: Dominik Brodowski <linux@dominikbrodowski.net> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-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.c18
-rw-r--r--include/linux/suspend.h7
-rw-r--r--kernel/power/process.c2
-rw-r--r--kernel/power/suspend.c29
9 files changed, 22 insertions, 77 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 83ab17e4a795..4ef1e4624b2b 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -776,7 +776,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume)
776 if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) || 776 if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
777 (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) && 777 (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
778 (battery->capacity_now <= battery->alarm))) 778 (battery->capacity_now <= battery->alarm)))
779 pm_wakeup_hard_event(&battery->device->dev); 779 pm_wakeup_event(&battery->device->dev, 0);
780 780
781 return result; 781 return result;
782} 782}
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index b7c2a06963d6..668137e4a069 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_hard_event(&device->dev); 219 pm_wakeup_event(&device->dev, 0);
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_hard_event(&device->dev); 401 pm_wakeup_event(&device->dev, 0);
402 if (button->suspended) 402 if (button->suspended)
403 break; 403 break;
404 404
@@ -530,7 +530,6 @@ 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);
534 printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); 533 printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
535 return 0; 534 return 0;
536 535
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index 798d5003a039..993fd31394c8 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -24,7 +24,6 @@
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>
28 27
29#include "internal.h" 28#include "internal.h"
30 29
@@ -400,7 +399,7 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
400 mutex_lock(&acpi_pm_notifier_lock); 399 mutex_lock(&acpi_pm_notifier_lock);
401 400
402 if (adev->wakeup.flags.notifier_present) { 401 if (adev->wakeup.flags.notifier_present) {
403 pm_wakeup_ws_event(adev->wakeup.ws, 0, true); 402 __pm_wakeup_event(adev->wakeup.ws, 0);
404 if (adev->wakeup.context.work.func) 403 if (adev->wakeup.context.work.func)
405 queue_pm_work(&adev->wakeup.context.work); 404 queue_pm_work(&adev->wakeup.context.work);
406 } 405 }
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index e84005d642e6..a4327af676fe 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -662,40 +662,14 @@ 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
666 return 0; 665 return 0;
667} 666}
668 667
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
693static void acpi_freeze_restore(void) 668static void acpi_freeze_restore(void)
694{ 669{
695 acpi_disable_wakeup_devices(ACPI_STATE_S0); 670 acpi_disable_wakeup_devices(ACPI_STATE_S0);
696 if (acpi_sci_irq_valid()) 671 if (acpi_sci_irq_valid())
697 disable_irq_wake(acpi_sci_irq); 672 disable_irq_wake(acpi_sci_irq);
698
699 acpi_enable_all_runtime_gpes(); 673 acpi_enable_all_runtime_gpes();
700} 674}
701 675
@@ -707,8 +681,6 @@ static void acpi_freeze_end(void)
707static const struct platform_freeze_ops acpi_freeze_ops = { 681static const struct platform_freeze_ops acpi_freeze_ops = {
708 .begin = acpi_freeze_begin, 682 .begin = acpi_freeze_begin,
709 .prepare = acpi_freeze_prepare, 683 .prepare = acpi_freeze_prepare,
710 .wake = acpi_freeze_wake,
711 .sync = acpi_freeze_sync,
712 .restore = acpi_freeze_restore, 684 .restore = acpi_freeze_restore,
713 .end = acpi_freeze_end, 685 .end = acpi_freeze_end,
714}; 686};
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index e987a6f55d36..9faee1c893e5 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -1091,6 +1091,11 @@ 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
1094 if (dev->power.syscore || dev->power.direct_complete) 1099 if (dev->power.syscore || dev->power.direct_complete)
1095 goto Complete; 1100 goto Complete;
1096 1101
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 9c36b27996fc..c313b600d356 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 greater than 0 and the system is suspending, terminate the suspend. */ 31/* If set and the system is suspending, terminate the suspend. */
32static atomic_t pm_abort_suspend __read_mostly; 32static bool 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.
@@ -855,26 +855,20 @@ bool pm_wakeup_pending(void)
855 pm_print_active_wakeup_sources(); 855 pm_print_active_wakeup_sources();
856 } 856 }
857 857
858 return ret || atomic_read(&pm_abort_suspend) > 0; 858 return ret || pm_abort_suspend;
859} 859}
860 860
861void pm_system_wakeup(void) 861void pm_system_wakeup(void)
862{ 862{
863 atomic_inc(&pm_abort_suspend); 863 pm_abort_suspend = true;
864 freeze_wake(); 864 freeze_wake();
865} 865}
866EXPORT_SYMBOL_GPL(pm_system_wakeup); 866EXPORT_SYMBOL_GPL(pm_system_wakeup);
867 867
868void pm_system_cancel_wakeup(void) 868void pm_wakeup_clear(void)
869{
870 atomic_dec(&pm_abort_suspend);
871}
872
873void pm_wakeup_clear(bool reset)
874{ 869{
870 pm_abort_suspend = false;
875 pm_wakeup_irq = 0; 871 pm_wakeup_irq = 0;
876 if (reset)
877 atomic_set(&pm_abort_suspend, 0);
878} 872}
879 873
880void pm_system_irq_wakeup(unsigned int irq_number) 874void pm_system_irq_wakeup(unsigned int irq_number)
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 0b1cf32edfd7..d9718378a8be 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -189,8 +189,6 @@ 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);
194 void (*restore)(void); 192 void (*restore)(void);
195 void (*end)(void); 193 void (*end)(void);
196}; 194};
@@ -430,8 +428,7 @@ extern unsigned int pm_wakeup_irq;
430 428
431extern bool pm_wakeup_pending(void); 429extern bool pm_wakeup_pending(void);
432extern void pm_system_wakeup(void); 430extern void pm_system_wakeup(void);
433extern void pm_system_cancel_wakeup(void); 431extern void pm_wakeup_clear(void);
434extern void pm_wakeup_clear(bool reset);
435extern void pm_system_irq_wakeup(unsigned int irq_number); 432extern void pm_system_irq_wakeup(unsigned int irq_number);
436extern bool pm_get_wakeup_count(unsigned int *count, bool block); 433extern bool pm_get_wakeup_count(unsigned int *count, bool block);
437extern bool pm_save_wakeup_count(unsigned int count); 434extern bool pm_save_wakeup_count(unsigned int count);
@@ -481,7 +478,7 @@ static inline int unregister_pm_notifier(struct notifier_block *nb)
481 478
482static inline bool pm_wakeup_pending(void) { return false; } 479static inline bool pm_wakeup_pending(void) { return false; }
483static inline void pm_system_wakeup(void) {} 480static inline void pm_system_wakeup(void) {}
484static inline void pm_wakeup_clear(bool reset) {} 481static inline void pm_wakeup_clear(void) {}
485static inline void pm_system_irq_wakeup(unsigned int irq_number) {} 482static inline void pm_system_irq_wakeup(unsigned int irq_number) {}
486 483
487static inline void lock_system_sleep(void) {} 484static inline void lock_system_sleep(void) {}
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 78672d324a6e..c7209f060eeb 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(true); 135 pm_wakeup_clear();
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 c0248c74d6d4..15e6baef5c73 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -72,8 +72,6 @@ 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
77 spin_lock_irq(&suspend_freeze_lock); 75 spin_lock_irq(&suspend_freeze_lock);
78 if (pm_wakeup_pending()) 76 if (pm_wakeup_pending())
79 goto out; 77 goto out;
@@ -100,27 +98,6 @@ static void freeze_enter(void)
100 out: 98 out:
101 suspend_freeze_state = FREEZE_STATE_NONE; 99 suspend_freeze_state = FREEZE_STATE_NONE;
102 spin_unlock_irq(&suspend_freeze_lock); 100 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));
124} 101}
125 102
126void freeze_wake(void) 103void freeze_wake(void)
@@ -394,8 +371,10 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
394 * all the devices are suspended. 371 * all the devices are suspended.
395 */ 372 */
396 if (state == PM_SUSPEND_FREEZE) { 373 if (state == PM_SUSPEND_FREEZE) {
397 s2idle_loop(); 374 trace_suspend_resume(TPS("machine_suspend"), state, true);
398 goto Platform_early_resume; 375 freeze_enter();
376 trace_suspend_resume(TPS("machine_suspend"), state, false);
377 goto Platform_wake;
399 } 378 }
400 379
401 error = disable_nonboot_cpus(); 380 error = disable_nonboot_cpus();