From: Greg Kroah-Hartman Date: Fri, 10 Apr 2020 11:24:22 +0000 (+0200) Subject: 5.6-stable patches X-Git-Tag: v4.4.219~28 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5d2552a7301a96d1ae40335154e252a86dcc3e78;p=thirdparty%2Fkernel%2Fstable-queue.git 5.6-stable patches added patches: acpi-pm-add-acpi_register_wakeup_handler.patch --- diff --git a/queue-5.6/acpi-pm-add-acpi_register_wakeup_handler.patch b/queue-5.6/acpi-pm-add-acpi_register_wakeup_handler.patch new file mode 100644 index 00000000000..f358c1e8ca8 --- /dev/null +++ b/queue-5.6/acpi-pm-add-acpi_register_wakeup_handler.patch @@ -0,0 +1,187 @@ +From ddfd9dcf270ce23ed1985b66fcfa163920e2e1b8 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 3 Apr 2020 17:48:33 +0200 +Subject: ACPI: PM: Add acpi_[un]register_wakeup_handler() + +From: Hans de Goede + +commit ddfd9dcf270ce23ed1985b66fcfa163920e2e1b8 upstream. + +Since commit fdde0ff8590b ("ACPI: PM: s2idle: Prevent spurious SCIs from +waking up the system") the SCI triggering without there being a wakeup +cause recognized by the ACPI sleep code will no longer wakeup the system. + +This works as intended, but this is a problem for devices where the SCI +is shared with another device which is also a wakeup source. + +In the past these, from the pov of the ACPI sleep code, spurious SCIs +would still cause a wakeup so the wakeup from the device sharing the +interrupt would actually wakeup the system. This now no longer works. + +This is a problem on e.g. Bay Trail-T and Cherry Trail devices where +some peripherals (typically the XHCI controller) can signal a +Power Management Event (PME) to the Power Management Controller (PMC) +to wakeup the system, this uses the same interrupt as the SCI. +These wakeups are handled through a special INT0002 ACPI device which +checks for events in the GPE0a_STS for this and takes care of acking +the PME so that the shared interrupt stops triggering. + +The change to the ACPI sleep code to ignore the spurious SCI, causes +the system to no longer wakeup on these PME events. To make things +worse this means that the INT0002 device driver interrupt handler will +no longer run, causing the PME to not get cleared and resulting in the +system hanging. Trying to wakeup the system after such a PME through e.g. +the power button no longer works. + +Add an acpi_register_wakeup_handler() function which registers +a handler to be called from acpi_s2idle_wake() and when the handler +returns true, return true from acpi_s2idle_wake(). + +The INT0002 driver will use this mechanism to check the GPE0a_STS +register from acpi_s2idle_wake() and to tell the system to wakeup +if a PME is signaled in the register. + +Fixes: fdde0ff8590b ("ACPI: PM: s2idle: Prevent spurious SCIs from waking up the system") +Cc: 5.4+ # 5.4+ +Signed-off-by: Hans de Goede +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/acpi/sleep.c | 4 ++ + drivers/acpi/sleep.h | 1 + drivers/acpi/wakeup.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/acpi.h | 5 +++ + 4 files changed, 91 insertions(+) + +--- a/drivers/acpi/sleep.c ++++ b/drivers/acpi/sleep.c +@@ -1012,6 +1012,10 @@ static bool acpi_s2idle_wake(void) + if (acpi_any_fixed_event_status_set()) + return true; + ++ /* Check wakeups from drivers sharing the SCI. */ ++ if (acpi_check_wakeup_handlers()) ++ return true; ++ + /* + * If there are no EC events to process and at least one of the + * other enabled GPEs is active, the wakeup is regarded as a +--- a/drivers/acpi/sleep.h ++++ b/drivers/acpi/sleep.h +@@ -2,6 +2,7 @@ + + extern void acpi_enable_wakeup_devices(u8 sleep_state); + extern void acpi_disable_wakeup_devices(u8 sleep_state); ++extern bool acpi_check_wakeup_handlers(void); + + extern struct list_head acpi_wakeup_device_list; + extern struct mutex acpi_device_lock; +--- a/drivers/acpi/wakeup.c ++++ b/drivers/acpi/wakeup.c +@@ -12,6 +12,15 @@ + #include "internal.h" + #include "sleep.h" + ++struct acpi_wakeup_handler { ++ struct list_head list_node; ++ bool (*wakeup)(void *context); ++ void *context; ++}; ++ ++static LIST_HEAD(acpi_wakeup_handler_head); ++static DEFINE_MUTEX(acpi_wakeup_handler_mutex); ++ + /* + * We didn't lock acpi_device_lock in the file, because it invokes oops in + * suspend/resume and isn't really required as this is called in S-state. At +@@ -96,3 +105,75 @@ int __init acpi_wakeup_device_init(void) + mutex_unlock(&acpi_device_lock); + return 0; + } ++ ++/** ++ * acpi_register_wakeup_handler - Register wakeup handler ++ * @wake_irq: The IRQ through which the device may receive wakeups ++ * @wakeup: Wakeup-handler to call when the SCI has triggered a wakeup ++ * @context: Context to pass to the handler when calling it ++ * ++ * Drivers which may share an IRQ with the SCI can use this to register ++ * a handler which returns true when the device they are managing wants ++ * to trigger a wakeup. ++ */ ++int acpi_register_wakeup_handler(int wake_irq, bool (*wakeup)(void *context), ++ void *context) ++{ ++ struct acpi_wakeup_handler *handler; ++ ++ /* ++ * If the device is not sharing its IRQ with the SCI, there is no ++ * need to register the handler. ++ */ ++ if (!acpi_sci_irq_valid() || wake_irq != acpi_sci_irq) ++ return 0; ++ ++ handler = kmalloc(sizeof(*handler), GFP_KERNEL); ++ if (!handler) ++ return -ENOMEM; ++ ++ handler->wakeup = wakeup; ++ handler->context = context; ++ ++ mutex_lock(&acpi_wakeup_handler_mutex); ++ list_add(&handler->list_node, &acpi_wakeup_handler_head); ++ mutex_unlock(&acpi_wakeup_handler_mutex); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(acpi_register_wakeup_handler); ++ ++/** ++ * acpi_unregister_wakeup_handler - Unregister wakeup handler ++ * @wakeup: Wakeup-handler passed to acpi_register_wakeup_handler() ++ * @context: Context passed to acpi_register_wakeup_handler() ++ */ ++void acpi_unregister_wakeup_handler(bool (*wakeup)(void *context), ++ void *context) ++{ ++ struct acpi_wakeup_handler *handler; ++ ++ mutex_lock(&acpi_wakeup_handler_mutex); ++ list_for_each_entry(handler, &acpi_wakeup_handler_head, list_node) { ++ if (handler->wakeup == wakeup && handler->context == context) { ++ list_del(&handler->list_node); ++ kfree(handler); ++ break; ++ } ++ } ++ mutex_unlock(&acpi_wakeup_handler_mutex); ++} ++EXPORT_SYMBOL_GPL(acpi_unregister_wakeup_handler); ++ ++bool acpi_check_wakeup_handlers(void) ++{ ++ struct acpi_wakeup_handler *handler; ++ ++ /* No need to lock, nothing else is running when we're called. */ ++ list_for_each_entry(handler, &acpi_wakeup_handler_head, list_node) { ++ if (handler->wakeup(handler->context)) ++ return true; ++ } ++ ++ return false; ++} +--- a/include/linux/acpi.h ++++ b/include/linux/acpi.h +@@ -488,6 +488,11 @@ void __init acpi_nvs_nosave_s3(void); + void __init acpi_sleep_no_blacklist(void); + #endif /* CONFIG_PM_SLEEP */ + ++int acpi_register_wakeup_handler( ++ int wake_irq, bool (*wakeup)(void *context), void *context); ++void acpi_unregister_wakeup_handler( ++ bool (*wakeup)(void *context), void *context); ++ + struct acpi_osc_context { + char *uuid_str; /* UUID string */ + int rev; diff --git a/queue-5.6/series b/queue-5.6/series index 17581a4bcb2..75a3e01a0fc 100644 --- a/queue-5.6/series +++ b/queue-5.6/series @@ -19,6 +19,7 @@ usb-dwc3-gadget-wrap-around-when-skip-trbs.patch slub-improve-bit-diffusion-for-freelist-ptr-obfuscation.patch tools-accounting-getdelays.c-fix-netlink-attribute-length.patch hwrng-imx-rngc-fix-an-error-path.patch +acpi-pm-add-acpi_register_wakeup_handler.patch platform-x86-intel_int0002_vgpio-use-acpi_register_wakeup_handler.patch asoc-tas2562-fixed-incorrect-amp_level-setting.patch asoc-jz4740-i2s-fix-divider-written-at-incorrect-offset-in-register.patch