Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+22 -77
+1 -1
drivers/acpi/battery.c
··· 776 776 if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) || 777 777 (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) && 778 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 781 return result; 782 782 }
+2 -3
drivers/acpi/button.c
··· 216 216 } 217 217 218 218 if (state) 219 - pm_wakeup_hard_event(&device->dev); 219 + pm_wakeup_event(&device->dev, 0); 220 220 221 221 ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); 222 222 if (ret == NOTIFY_DONE) ··· 398 398 } else { 399 399 int keycode; 400 400 401 - pm_wakeup_hard_event(&device->dev); 401 + pm_wakeup_event(&device->dev, 0); 402 402 if (button->suspended) 403 403 break; 404 404 ··· 530 530 lid_device = device; 531 531 } 532 532 533 - device_init_wakeup(&device->dev, true); 534 533 printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); 535 534 return 0; 536 535
+1 -2
drivers/acpi/device_pm.c
··· 24 24 #include <linux/pm_qos.h> 25 25 #include <linux/pm_domain.h> 26 26 #include <linux/pm_runtime.h> 27 - #include <linux/suspend.h> 28 27 29 28 #include "internal.h" 30 29 ··· 399 400 mutex_lock(&acpi_pm_notifier_lock); 400 401 401 402 if (adev->wakeup.flags.notifier_present) { 402 - pm_wakeup_ws_event(adev->wakeup.ws, 0, true); 403 + __pm_wakeup_event(adev->wakeup.ws, 0); 403 404 if (adev->wakeup.context.work.func) 404 405 queue_pm_work(&adev->wakeup.context.work); 405 406 }
-28
drivers/acpi/sleep.c
··· 662 662 acpi_os_wait_events_complete(); 663 663 if (acpi_sci_irq_valid()) 664 664 enable_irq_wake(acpi_sci_irq); 665 - 666 665 return 0; 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 666 } 692 667 693 668 static void acpi_freeze_restore(void) ··· 670 695 acpi_disable_wakeup_devices(ACPI_STATE_S0); 671 696 if (acpi_sci_irq_valid()) 672 697 disable_irq_wake(acpi_sci_irq); 673 - 674 698 acpi_enable_all_runtime_gpes(); 675 699 } 676 700 ··· 681 707 static const struct platform_freeze_ops acpi_freeze_ops = { 682 708 .begin = acpi_freeze_begin, 683 709 .prepare = acpi_freeze_prepare, 684 - .wake = acpi_freeze_wake, 685 - .sync = acpi_freeze_sync, 686 710 .restore = acpi_freeze_restore, 687 711 .end = acpi_freeze_end, 688 712 };
+5
drivers/base/power/main.c
··· 1091 1091 if (async_error) 1092 1092 goto Complete; 1093 1093 1094 + if (pm_wakeup_pending()) { 1095 + async_error = -EBUSY; 1096 + goto Complete; 1097 + } 1098 + 1094 1099 if (dev->power.syscore || dev->power.direct_complete) 1095 1100 goto Complete; 1096 1101
+6 -12
drivers/base/power/wakeup.c
··· 28 28 /* First wakeup IRQ seen by the kernel in the last cycle. */ 29 29 unsigned int pm_wakeup_irq __read_mostly; 30 30 31 - /* If greater than 0 and the system is suspending, terminate the suspend. */ 32 - static atomic_t pm_abort_suspend __read_mostly; 31 + /* If set and the system is suspending, terminate the suspend. */ 32 + static bool pm_abort_suspend __read_mostly; 33 33 34 34 /* 35 35 * Combined counters of registered wakeup events and wakeup events in progress. ··· 855 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 861 861 void pm_system_wakeup(void) 862 862 { 863 - atomic_inc(&pm_abort_suspend); 863 + pm_abort_suspend = true; 864 864 freeze_wake(); 865 865 } 866 866 EXPORT_SYMBOL_GPL(pm_system_wakeup); 867 867 868 - void pm_system_cancel_wakeup(void) 868 + void pm_wakeup_clear(void) 869 869 { 870 - atomic_dec(&pm_abort_suspend); 871 - } 872 - 873 - void pm_wakeup_clear(bool reset) 874 - { 870 + pm_abort_suspend = false; 875 871 pm_wakeup_irq = 0; 876 - if (reset) 877 - atomic_set(&pm_abort_suspend, 0); 878 872 } 879 873 880 874 void pm_system_irq_wakeup(unsigned int irq_number)
+2 -5
include/linux/suspend.h
··· 189 189 struct platform_freeze_ops { 190 190 int (*begin)(void); 191 191 int (*prepare)(void); 192 - void (*wake)(void); 193 - void (*sync)(void); 194 192 void (*restore)(void); 195 193 void (*end)(void); 196 194 }; ··· 428 430 429 431 extern bool pm_wakeup_pending(void); 430 432 extern void pm_system_wakeup(void); 431 - extern void pm_system_cancel_wakeup(void); 432 - extern void pm_wakeup_clear(bool reset); 433 + extern void pm_wakeup_clear(void); 433 434 extern void pm_system_irq_wakeup(unsigned int irq_number); 434 435 extern bool pm_get_wakeup_count(unsigned int *count, bool block); 435 436 extern bool pm_save_wakeup_count(unsigned int count); ··· 478 481 479 482 static inline bool pm_wakeup_pending(void) { return false; } 480 483 static inline void pm_system_wakeup(void) {} 481 - static inline void pm_wakeup_clear(bool reset) {} 484 + static inline void pm_wakeup_clear(void) {} 482 485 static inline void pm_system_irq_wakeup(unsigned int irq_number) {} 483 486 484 487 static inline void lock_system_sleep(void) {}
+1 -1
kernel/power/process.c
··· 132 132 if (!pm_freezing) 133 133 atomic_inc(&system_freezing_cnt); 134 134 135 - pm_wakeup_clear(true); 135 + pm_wakeup_clear(); 136 136 pr_info("Freezing user space processes ... "); 137 137 pm_freezing = true; 138 138 error = try_to_freeze_tasks(true);
+4 -25
kernel/power/suspend.c
··· 72 72 73 73 static void freeze_enter(void) 74 74 { 75 - trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_FREEZE, true); 76 - 77 75 spin_lock_irq(&suspend_freeze_lock); 78 76 if (pm_wakeup_pending()) 79 77 goto out; ··· 98 100 out: 99 101 suspend_freeze_state = FREEZE_STATE_NONE; 100 102 spin_unlock_irq(&suspend_freeze_lock); 101 - 102 - trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_FREEZE, false); 103 - } 104 - 105 - static void s2idle_loop(void) 106 - { 107 - do { 108 - freeze_enter(); 109 - 110 - if (freeze_ops && freeze_ops->wake) 111 - freeze_ops->wake(); 112 - 113 - dpm_resume_noirq(PMSG_RESUME); 114 - if (freeze_ops && freeze_ops->sync) 115 - freeze_ops->sync(); 116 - 117 - if (pm_wakeup_pending()) 118 - break; 119 - 120 - pm_wakeup_clear(false); 121 - } while (!dpm_suspend_noirq(PMSG_SUSPEND)); 122 103 } 123 104 124 105 void freeze_wake(void) ··· 371 394 * all the devices are suspended. 372 395 */ 373 396 if (state == PM_SUSPEND_FREEZE) { 374 - s2idle_loop(); 375 - goto Platform_early_resume; 397 + trace_suspend_resume(TPS("machine_suspend"), state, true); 398 + freeze_enter(); 399 + trace_suspend_resume(TPS("machine_suspend"), state, false); 400 + goto Platform_wake; 376 401 } 377 402 378 403 error = disable_nonboot_cpus();