Message ID | 20200123210242.53367-1-hdegoede@redhat.com |
---|---|
State | New |
Headers | show |
Series | [RFC,v2] x86: Select HARDIRQS_SW_RESEND on x86 | expand |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index c1cbfc7b3ae8..8f8128047b49 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -118,6 +118,7 @@ config X86 select GENERIC_IRQ_PROBE select GENERIC_IRQ_RESERVATION_MODE select GENERIC_IRQ_SHOW + select HARDIRQS_SW_RESEND select GENERIC_PENDING_IRQ if SMP select GENERIC_SMP_IDLE_THREAD select GENERIC_STRNCPY_FROM_USER
Modern x86 laptops are starting to use GPIO pins as interrupts more and more, e.g. touchpads and touchscreens have almost all moved away from PS/2 and USB to using I2C with a GPIO pin as interrupt. Modern x86 laptops also have almost all moved to using s2idle instead of using the system S3 ACPI power state to suspend. The Intel and AMD pinctrl drivers do not define irq_retrigger handlers for the irqchips they register, this is causing edge triggered interrupts which happen while suspended using s2idle to get lost. One specific example of this is the lid switch on some devices, lid switches used to be handled by the embedded-controller, but now the lid open/closed sensor is sometimes directly connected to a GPIO pin. On most devices the ACPI code for this looks like this: Method (_E00, ...) { Notify (LID0, 0x80) // Status Change } Where _E00 is an ACPI event handler for changes on both edges of the GPIO connected to the lid sensor, this event handler is then combined with an _LID method which directly reads the pin. When the device is resumed by opening the lid, the GPIO interrupt will wake the system, but because the pinctrl irqchip doesn't have an irq_retrigger handler, the Notify will not happen. This is not a problem in the case the _LID method directly reads the GPIO, because the drivers/acpi/button.c code will call _LID on resume anyways. But some devices have an event handler for the GPIO connected to the lid sensor which looks like this: Method (_E00, ...) { if (LID_GPIO == One) LIDS = One else LIDS = Zero Notify (LID0, 0x80) // Status Change } And the _LID method returns the cached LIDS value, since on open we do not re-run the edge-interrupt handler when we re-enable IRQS on resume (because of the missing irq_retrigger handler), _LID now will keep reporting closed, as LIDS was never changed to reflect the open status, this causes userspace to re-resume the laptop again shortly after opening the lid. The Intel GPIO controllers do not allow implementing irq_retrigger without emulating it in software, at which point we are better of just using the generic HARDIRQS_SW_RESEND mechanism rather then re-implementing software emulation for this separately in aprox. 14 different pinctrl drivers. This commit selects HARDIRQS_SW_RESEND solving the problem of edge-triggered GPIO interrupts not being re-triggered on resume when they were triggered during suspend (s2idle) and/or when they were the cause of the wakeup. Signed-off-by: Hans de Goede <hdegoede@redhat.com> --- I'm sending this out as a RFC since I'm not %100 sure this is the best solution and it seems like a somewhat big change to make. Also maybe we should add a Cc: stable@vger.kernel.org ??? This seems like somewhat a big change for that but it does solve some real issues... --- Changes in v2: -v2 is really a resend because I forgot to add the pinctrl people to the Cc -While at it also fix some typos in the commit message --- arch/x86/Kconfig | 1 + 1 file changed, 1 insertion(+)