Re: pinctrl: amd: spurious immediate resume from S3/s2idle via BIOS-armed wake GPIO with no ACPI owner (Lenovo Legion Pro 5 16ARX8)

From: Mario Limonciello

Date: Wed Jun 10 2026 - 16:03:02 EST


First off -

How did you get into an S3 path? These systems that ship with only Modern Standby / s2idle normally shouldn't be able to get into S3.

╰─❯ cat /sys/power/mem_sleep
[s2idle]

Have you modified the firmware in some way to try to enable an unvalidated path?

I have some more questions about your methodology below because when debugging a kernel issue an LLM can sometimes make WILD assumptions that are totally a house of cards.

On 6/10/26 14:32, Lenart Kos wrote:
## Summary

On the Lenovo Legion Pro 5 16ARX8, suspending (S3 *or* s2idle) with an external
display connected resumes the machine after ~1 second. The wake is delivered by
the AMD GPIO controller (`pinctrl_amd`, IRQ 7) from GPIO pin **#4**
(and pin #2 for
the USB‑C/DP path), which the **BIOS has armed as an S0i3/S3 wake
source directly
in the FCH GPIO register**, with **no ACPI description**
(`_AEI`/`GpioInt`/`_PRW`)
anywhere in the DSDT or the 16 SSDTs. Because there is no ACPI owner,
none of the
existing override mechanisms (`gpiolib_acpi.ignore_wake=`, device
`power/wakeup`)
can reach it, and `IO_STRICT_DEVMEM` blocks any userspace register
write. The pin
is an external‑display HPD line, so the edge produced while the GPU
powers down on
the way into sleep immediately wakes the system.

## Affected system

```
DMI sys_vendor LENOVO
DMI product_name 82WM
DMI product_version Legion Pro 5 16ARX8
DMI board_name LNVNB161216
BIOS LPCN62WW (2025-06-17) # latest available; does NOT fix this
SoC AMD Ryzen 7 7745HX (Raphael), GPIO ctrl AMDI0030 @ 0xFED81500
GPU NVIDIA RTX 4060 Mobile (HDMI) + AMD Raphael iGPU (USB-C DP)
Kernel 6.17+ through 7.0.x (reproduced on Fedora 43/44)
```

## Symptom / evidence

Failed-suspend kernel log (verbose PM):
```
PM: suspend entry (deep)
...
amd_gpio AMDI0030:00: ... Clearing debounce for GPIO #2 during suspend.
amd_gpio AMDI0030:00: ... Clearing debounce for GPIO #4 during suspend.
amd_gpio AMDI0030:00: ... Disabling GPIO #89 interrupt for suspend. #
not a wake src
ACPI: PM: Preparing to enter system sleep state S3
Timekeeping suspended for 1.384 seconds
PM: Triggering wakeup from IRQ 7 # IRQ 7 = pinctrl_amd
...
GPIO 4 is active: 0x30057c00 # bit 14 (WAKE_CNTRL_S3) + bit 29 (wake latched)
```
`/sys/power/pm_wakeup_irq` = `7`.

`/sys/kernel/debug/gpio` (relevant rows) shows pins #2 and #4 armed for S0i3+S3
wake with their interrupt enabled, while #89 has no wake bits:
```
#2 😛| ↓ | edge |⏰|⏰| | | ... 0x147ae0
#4 😛| b | edge |⏰|⏰| | | ... 0x57ce0 <- both-edge HPD, S0i3+S3 wake set

How did you determine this is an HPD line? Is that a pure guess? Or did you look at a schematic/trace etc?

#89 😛| ↓ | level| | | | | ... 0x151b00 <- no wake bits (red herring)
```

## Root cause

1. The external‑display HPD lines are routed to SoC GPIO #2 (USB‑C/DP) and #4
(HDMI/dGPU).

How do you know?

2. The BIOS sets `WAKE_CNTRL_S0I3`/`WAKE_CNTRL_S3` (bits 13/14) on
those pins in the
FCH GPIO register block and **never describes them in ACPI** — decompiling the
DSDT and all 16 SSDTs yields **zero** `GpioInt`/`GpioIo`/`_AEI` resources.
3. `pinctrl_amd` correctly preserves hardware-armed wake pins across
suspend, so the
HPD edge generated during the suspend transition wakes the system immediately.

This is effectively an unvalidated firmware S3 path (the platform ships as
Modern-Standby-only); but note **both** the S0i3 and S3 wake bits are set, so
s2idle is affected too.

So how did you get into S3?


## Why existing mechanisms don't help

- `/proc/acpi/wakeup`, PCI/ACPI `power/wakeup` — wrong layer; this is
not a PCIe PME.
Disabling wakeup on the GPP bridges / GPU has no effect (verified).
- `gpiolib_acpi.ignore_wake=` / `ignore_interrupt=` — only match
**ACPI-declared**
GPIO events; this pin has no ACPI declaration, so they cannot target it.
- `/dev/mem` register write — blocked by `CONFIG_IO_STRICT_DEVMEM=y`
(the region is
claimed by pinctrl_amd).

There is currently **no way, in-tree, to disarm a bare (non-ACPI) firmware-armed
pinctrl-amd wake pin.** That is the gap.

## Suggested fix (maintainers' choice)

A working out-of-tree reference implementation (clears bits 13/14/15
on pins #2/#4
at probe and on `PM_SUSPEND_PREPARE`) is here:
**https://github.com/Lenart12/legion-nowake** — please feel free to reuse.

Why not use /dev/gpiochipX devices to change GPIOs?


Possible in-tree directions:
1. **DMI-matched quirk in `pinctrl-amd`** that clears the S-state
wake-enable bits
for the affected pins at probe (smallest change; precedent exists for AMD GPIO
wake quirks).
2. **A generic override** for bare pins, e.g. a
`pinctrl_amd.ignore_wake=<pin,...>`
module parameter, analogous to `gpiolib_acpi.ignore_wake=` but for
hardware-armed
pins without ACPI events. This would help the broader class of AMD laptops that
hit firmware-armed spurious wakes.

## Reproduction

1. AMD laptop where a display HPD is wired to a GPIO the BIOS arms for wake.
2. Connect an external monitor, `systemctl suspend`.
3. Observe resume after ~1s; `pm_wakeup_irq` = the `pinctrl_amd` IRQ;
the offending
pin shows `wake latched` in the post-resume `GPIO N is active` log.

On the presumption that this is correct about being an HPD pin doesn't this actually point at a GPU driver bug?


## Public discussion / full diagnostics

Fedora Discussion (complete diagnostic walkthrough, ACPI dumps, gpio table):
https://discussion.fedoraproject.org/t/immediate-wake-from-s3-sleep-when-hdmi-is-connected-irq-7-pinctrl-amd

## Attachments to include when filing

- `acpidump` output (or note: DSDT + all SSDTs contain no GpioInt/_AEI).
- Full verbose-PM `dmesg` of one failed suspend (`pm_debug_messages=1`).
- `sudo cat /sys/kernel/debug/gpio`.
- `cat /sys/class/dmi/id/{sys_vendor,product_name,product_version,board_name,bios_version}`.

Where is the kernel bugzilla that you attached all these artifacts?