[FIX] Linux S3 suspend #2 freeze on AMD Navi 10 (RX 5700 / W5700)

TL;DR:
On AMD Navi-10 (RDNA1) GPUs, two PCIe subfunctions (GPU-USB and AUX/I²C) have broken or resume-sensitive runtime power management. Disabling runtime PM and wakeups for only those subfunctions via a single udev rule fixes the classic “Suspend #2 freeze” on Linux S3 (deep sleep).


Intended audience & scope

This post is written for experienced Linux users, distribution maintainers,
and kernel / driver developers who are familiar with suspend/resume,
PCIe devices, udev rules, and runtime power management.

It documents a reproducible suspend/resume failure mode on AMD Navi-10 (RDNA1) GPUs
and a minimal, targeted workaround that restores reliable S3 (deep) suspend.

This is not a general end-user tuning guide and not a generic AMD or Linux fix.
The intention is twofold:

  1. Help affected users achieve a stable suspend/resume today.
  2. Provide enough technical context that this behavior could eventually be addressed
    via a proper kernel-side fix or quirk, if deemed appropriate.

If you are not comfortable modifying system configuration files or reasoning about
power-management behavior, this guide may not be for you.


Background

Many Linux users with AMD Navi-10 GPUs report the same long-standing issue:
– First suspend → resume works
– Second suspend → hard freeze / black screen / no input

The problem persists across:
– kernel updates
– distributions
– BIOS/UEFI tuning

This guide documents a minimal, reproducible, and persistent fix.


Symptoms

Commonly observed symptoms include:
– Freeze on the second suspend cycle (S3 / deep)
– System requires hard power-off
– Errors or warnings around suspend/resume, e.g.:
xhci_hcd … init fail, -19 (ENODEV)
i2c-designware-pci … timeout
EDID checksum invalid
DM_MST: Differing MST start


Affected hardware

Confirmed affected GPUs:
AMD Navi 10 (RDNA1)
– Radeon RX 5700 / RX 5700 XT
– Radeon Pro W5700

Likely not affected:
– RDNA2 / RDNA3 (RX 6000 / RX 7000)
– systems without S3 / deep sleep


Who this applies to (important)

This guide is intended for users who:
– run Linux (any modern distribution)
– use an AMD Navi 10 (RDNA1) GPU
– use S3 / deep sleep (not s2idle)
– experience the classic pattern:
– first suspend → resume works
– second suspend → hard freeze

If this matches your system, this fix is very likely relevant.


Who this does NOT apply to

This is not a general AMD or Linux suspend fix.

It likely does not apply if you:
– use RDNA2 / RDNA3 GPUs
– run Windows
– use s2idle only (no S3)
– do not experience suspend instability
– use laptops with very different power / ACPI topologies

Please do not apply this blindly if your system does not match the criteria above.

You can verify your GPU with:


lspci -nn | grep VGA


Root cause (technical summary)

Navi-10 GPUs expose multiple PCIe subfunctions, not just the main GPU:

Function Purpose Status
GPU core graphics OK
HDMI/DP audio audio OK
GPU USB (xHCI) USB controller broken
AUX / I²C sideband DP AUX / EDID / MST resume-sensitive

Key findings:
– The GPU-USB (xHCI) function enters an irrecoverable runtime-PM error state
– The AUX / I²C function frequently times out during suspend/resume
– Runtime PM + wakeups on these subfunctions break the second S3 cycle

This is a hardware / firmware edge case, not a misconfiguration.


Why BIOS / ACPI tuning does not help

  • ACPI tables are valid
  • S3 (deep) works correctly
  • CPU generation (Zen2 / Zen3) is not the cause

The failure happens after resume, inside PCIe runtime power transitions of GPU subfunctions.


The solution (minimal & persistent)

We do not attempt to fix broken hardware.

Instead, we isolate the problematic subfunctions:
– disable runtime autosuspend
– disable wakeups

This prevents them from interfering with S3, without affecting global power management.


The fix: one udev rule

Create the following file:

/etc/udev/rules.d/99-amd-navi10-gpu-pm-fix.rules

With this content:
“`

<h1>AMD Navi 10 GPU – fix broken runtime PM / wakeups (S3 stability)</h1>

<h1>GPU USB (xHCI) – broken under Linux</h1>

<p>ACTION=="add|change", SUBSYSTEM=="pci", ATTR{vendor}=="0x1002", ATTR{device}=="0x7316", TEST=="power/control", ATTR{power/control}="on"
ACTION=="add|change", SUBSYSTEM=="pci", ATTR{vendor}=="0x1002", ATTR{device}=="0x7316", RUN+="/bin/sh -c 'echo disabled > /sys/bus/pci/devices/%k/power/wakeup || true'"

<h1>AUX / I2C sideband – keep active, no wakeups</h1>

ACTION=="add|change", SUBSYSTEM=="pci", ATTR{vendor}=="0x1002", ATTR{device}=="0x7314", TEST=="power/control", ATTR{power/control}="on"
ACTION=="add|change", SUBSYSTEM=="pci", ATTR{vendor}=="0x1002", ATTR{device}=="0x7314", RUN+="/bin/sh -c 'echo disabled > /sys/bus/pci/devices/%k/power/wakeup || true'"
“`

Reload udev rules:

sudo udevadm control --reload-rules
sudo udevadm trigger --subsystem-match=pci --action=add
sudo udevadm trigger --subsystem-match=pci --action=change

Reboot once.


How to verify

After reboot, check:

cat /sys/bus/pci/devices/*/power/control | grep on

Or explicitly (bus numbers may differ):

cat /sys/bus/pci/devices/0000:XX:YY.2/power/control
cat /sys/bus/pci/devices/0000:XX:YY.2/power/wakeup

Expected:

on
disabled

Then test:
– Suspend → resume
– Suspend → resume again

If the system survives two consecutive suspends, the issue is resolved.


Safety notes

  • This does not disable suspend, ASPM, or power saving globally
  • Only two known-broken GPU subfunctions are kept in D0
  • The rule matches PCI vendor/device IDs, not bus numbers
  • Fully reversible: delete the rule file and reboot

Conclusion

This fix:
– avoids kernel parameters
– avoids ACPI hacks
– avoids disabling S3
– touches only broken Navi-10 subfunctions

It has proven stable across reboots and repeated suspend cycles.

If this helped you, consider sharing it — this issue has existed for years.

Leave a Reply