Users have reported the inability to properly suspend on
Lenovo Yoga Slim 7 Gen 8 14APU8 and Lenovo YogaAir 14s APU8
Analyzing the problem there are two issues where HID devices connected
over I2C cause spurious wakeup events or high power consumption.
One of the HID devices isn't configured as a wakeup source so the APU
if the interrupt fires over suspend it will wake the APU from a hardware
sleep state but will not return control to the OS.
The second HID device is configured as a wakeup source and continually
fires both at runtime and suspend.
This series mitigates the impact from both of these devices.
Mario Limonciello (2):
HID: i2c-hid: Add IDEA5002 to i2c_hid_acpi_blacklist[]
pinctrl: amd: Mask non-wake source pins with interrupt enabled at
suspend
drivers/hid/i2c-hid/i2c-hid-acpi.c | 5 +++++
drivers/pinctrl/pinctrl-amd.c | 9 +++++++++
drivers/pinctrl/pinctrl-amd.h | 5 +++++
3 files changed, 19 insertions(+)
--
2.34.1
If a pin isn't marked as a wake source processing any interrupts is
just going to destroy battery life. The APU may wake up from a hardware
sleep state to process the interrupt but not return control to the OS.
Mask interrupt for all non-wake source pins at suspend. They'll be
re-enabled at resume.
Reported-and-tested-by: Marcus Aram <[email protected]>
Reported-and-tested-by: Mark Herbert <[email protected]>
Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2812
Signed-off-by: Mario Limonciello <[email protected]>
---
drivers/pinctrl/pinctrl-amd.c | 9 +++++++++
drivers/pinctrl/pinctrl-amd.h | 5 +++++
2 files changed, 14 insertions(+)
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index fb58acb843d9..03ecb3d1aaf6 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -923,6 +923,15 @@ static int amd_gpio_suspend(struct device *dev)
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
gpio_dev->saved_regs[i] = readl(gpio_dev->base + pin * 4) & ~PIN_IRQ_PENDING;
+
+ /* mask any interrupts not intended to be a wake source */
+ if (!(gpio_dev->saved_regs[i] & WAKE_SOURCE)) {
+ writel(gpio_dev->saved_regs[i] & ~BIT(INTERRUPT_MASK_OFF),
+ gpio_dev->base + pin * 4);
+ pm_pr_dbg("Disabling GPIO #%d interrupt for suspend.\n",
+ pin);
+ }
+
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
}
diff --git a/drivers/pinctrl/pinctrl-amd.h b/drivers/pinctrl/pinctrl-amd.h
index 34c5c3e71fb2..cf59089f2776 100644
--- a/drivers/pinctrl/pinctrl-amd.h
+++ b/drivers/pinctrl/pinctrl-amd.h
@@ -80,6 +80,11 @@
#define FUNCTION_MASK GENMASK(1, 0)
#define FUNCTION_INVALID GENMASK(7, 0)
+#define WAKE_SOURCE (BIT(WAKE_CNTRL_OFF_S0I3) | \
+ BIT(WAKE_CNTRL_OFF_S3) | \
+ BIT(WAKE_CNTRL_OFF_S4) | \
+ BIT(WAKECNTRL_Z_OFF))
+
struct amd_function {
const char *name;
const char * const groups[NSELECTS];
--
2.34.1
Users have reported problems with recent Lenovo laptops that contain
an IDEA5002 I2C HID device. Reports include fans turning on and
running even at idle and spurious wakeups from suspend.
Presumably in the Windows ecosystem there is an application that
uses the HID device. Maybe that puts it into a lower power state so
it doesn't cause spurious events.
This device doesn't serve any functional purpose in Linux as nothing
interacts with it so blacklist it from being probed. This will
prevent the GPIO driver from setting up the GPIO and the spurious
interrupts and wake events will not occur.
Cc: [email protected] # 6.1
Reported-and-tested-by: Marcus Aram <[email protected]>
Reported-and-tested-by: Mark Herbert <[email protected]>
Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/2812
Signed-off-by: Mario Limonciello <[email protected]>
---
drivers/hid/i2c-hid/i2c-hid-acpi.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/hid/i2c-hid/i2c-hid-acpi.c b/drivers/hid/i2c-hid/i2c-hid-acpi.c
index ac918a9ea8d3..1b49243adb16 100644
--- a/drivers/hid/i2c-hid/i2c-hid-acpi.c
+++ b/drivers/hid/i2c-hid/i2c-hid-acpi.c
@@ -40,6 +40,11 @@ static const struct acpi_device_id i2c_hid_acpi_blacklist[] = {
* ICN8505 controller, has a _CID of PNP0C50 but is not HID compatible.
*/
{ "CHPN0001" },
+ /*
+ * The IDEA5002 ACPI device causes high interrupt usage and spurious
+ * wakeups from suspend.
+ */
+ { "IDEA5002" },
{ }
};
--
2.34.1
On Sun, Dec 3, 2023 at 4:25 AM Mario Limonciello
<[email protected]> wrote:
> If a pin isn't marked as a wake source processing any interrupts is
> just going to destroy battery life. The APU may wake up from a hardware
> sleep state to process the interrupt but not return control to the OS.
>
> Mask interrupt for all non-wake source pins at suspend. They'll be
> re-enabled at resume.
>
> Reported-and-tested-by: Marcus Aram <[email protected]>
> Reported-and-tested-by: Mark Herbert <[email protected]>
> Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2812
> Signed-off-by: Mario Limonciello <[email protected]>
I applied this patch (2/2) to the pin control tree for fixes.
Yours,
Linus Walleij
On Sat, 2 Dec 2023, Mario Limonciello wrote:
> Users have reported problems with recent Lenovo laptops that contain
> an IDEA5002 I2C HID device. Reports include fans turning on and
> running even at idle and spurious wakeups from suspend.
>
> Presumably in the Windows ecosystem there is an application that
> uses the HID device. Maybe that puts it into a lower power state so
> it doesn't cause spurious events.
>
> This device doesn't serve any functional purpose in Linux as nothing
> interacts with it so blacklist it from being probed. This will
> prevent the GPIO driver from setting up the GPIO and the spurious
> interrupts and wake events will not occur.
>
> Cc: [email protected] # 6.1
> Reported-and-tested-by: Marcus Aram <[email protected]>
> Reported-and-tested-by: Mark Herbert <[email protected]>
> Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/2812
> Signed-off-by: Mario Limonciello <[email protected]>
> ---
> drivers/hid/i2c-hid/i2c-hid-acpi.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/drivers/hid/i2c-hid/i2c-hid-acpi.c b/drivers/hid/i2c-hid/i2c-hid-acpi.c
> index ac918a9ea8d3..1b49243adb16 100644
> --- a/drivers/hid/i2c-hid/i2c-hid-acpi.c
> +++ b/drivers/hid/i2c-hid/i2c-hid-acpi.c
> @@ -40,6 +40,11 @@ static const struct acpi_device_id i2c_hid_acpi_blacklist[] = {
> * ICN8505 controller, has a _CID of PNP0C50 but is not HID compatible.
> */
> { "CHPN0001" },
> + /*
> + * The IDEA5002 ACPI device causes high interrupt usage and spurious
> + * wakeups from suspend.
> + */
> + { "IDEA5002" },
Applied to hid.git#for-6.7/upstream-fixes. Thanks,
--
Jiri Kosina
SUSE Labs