Skip to content

amdgpu: Fix raphael support - #478

Open
lbartoletti wants to merge 3 commits into
freebsd:masterfrom
lbartoletti:amdgpu-raphael-gfxoff
Open

amdgpu: Fix raphael support#478
lbartoletti wants to merge 3 commits into
freebsd:masterfrom
lbartoletti:amdgpu-raphael-gfxoff

Conversation

@lbartoletti

Copy link
Copy Markdown
Member

Disclosure: this branch was produced largely by an AI assistant (Claude).

I want to be upfront about this PR. It's the first time I'm sending work where I can't personally vouch.
I described the symptoms, ran the test cycles (make, reboot, laucnh sessions), and fed dmesg back; the analysis and the patches are the assistant's.
I can't personally vouch for the reasoning in every commit, so I've left the messages unedited — rewrite, squash, or re-author as you see fit.
What I can vouch for: I've daily-driven a Wayland session on this branch for several days (audio, screen sharing, 3D all work).

Resume (generated by Claude Code):

On a Ryzen 9 7900X Raphael iGPU (1002:164e, GC 10.3.6) under FreeBSD 16-CURRENT / drm-kmod master (LinuxKPI 6.12), the driver loaded fine but the gfx ring hung on the first Mesa/radv submission and entered a reset loop. This branch fixes that — sway runs on the iGPU, no ring gfx_0.0.0 timeout.

Three small FreeBSD-guarded patches:

  1. disable GFXOFF on Raphael — SMU GFXOFF wake doesn't work under LinuxKPI; clears PP_GFXOFF_MASK for IP_VERSION(10,3,6), mirroring Navi10. Fixes the idle reset loop.
  2. enable native atomics for gfx9+ APUs — the FreeBSD branch set have_atomics_support = false unconditionally, bypassing the gfx9+ APU case Linux already handles. Mirrors "drm/amdgpu: set gfx9 onwards APU atomics support to be true".
  3. keep CP/MEC polling the wptr — the doorbell doesn't wake the CP/MEC once a queue goes idle, so submissions stall. Polls the wptr from memory instead. This is a workaround, not a root-cause fix (the doorbell-wake gap likely lives in NBIO aperture routing while idle).

Since I can't guarantee the work and you'll likely need to take the code over, I'm glad to run every test you need on the hardware. Thanks

Fixes: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=268394
maybe #330 ?

The Raphael APU gfx ring (gfx_0.0.0) stalls shortly after init and
enters a GPU reset loop when GFXOFF is enabled: the GFX engine is
power-gated on idle and the SMU wake handshake does not work under
LinuxKPI, so the ring times out (signaled seq < emitted seq).

Clear PP_GFXOFF_MASK for IP_VERSION(10, 3, 6) in
gfx_v10_0_check_gfxoff_flag(), mirroring the existing Navi10 handling.
Guarded with __FreeBSD__ as this is a FreeBSD/LinuxKPI-specific quirk.

This removes the idle gfx ring timeout; a separate ring stall under
sustained GFX load remains under investigation.
amdgpu_device_init() unconditionally set have_atomics_support = false on
FreeBSD, bypassing the gfx9+ APU case the __linux__ path already handles.
APUs from gfx9 onward do not rely on PCIe atomics; they use an internal
path with native atomics support. With the flag left false, the userspace
GFX submission path stalls: kernel submissions complete but the first
Mesa/radv submission hangs the gfx_0.0.0 ring (signaled seq < emitted seq),
followed by a GPU reset loop under any real load (e.g. a Wayland session).

Mirror the __linux__ APU handling: set have_atomics_support = true for
IP_VERSION(GC) > 9.0.0 APUs, otherwise keep the previous false default.

Fixes the Raphael (gfx 10.3.6) gfx ring timeout under GPU load.
On Raphael (gfx 10.3.6) under FreeBSD/LinuxKPI, GPU-scheduler submissions
made after the engines go idle were never fetched: the gfx ring timed out
with signaled seq < emitted seq and no VM protection fault, the CP rptr
frozen at the kernel->userspace boundary. The first ~14 boot-time
submissions complete (the CP still polls the write pointer during the
post-idle window), then the CP stops polling and waits for a doorbell ring
that never wakes it on this APU under LinuxKPI. Anything doorbell-driven
afterwards (KIQ, the async gfx queue, every Mesa frame) stalls.

The doorbell mapping itself is correct (VM_MEMATTR_DEVICE / UC, single
64-bit store) and the writes reach BAR 2; the problem is purely the
idle CP/MEC not acting on them. Sidestep the doorbell wake by keeping the
engines polling the queue write pointer from memory: point the GFX-pipe
wptr poll at the gfx ring's wptr writeback, max out CP_RB_WPTR_POLL_CNTL
IDLE_POLL_COUNT, and enable CP_PQ_WPTR_POLL_CNTL for the MEC (each queue's
poll address is already programmed in its MQD).

With this, a Wayland (sway) session runs on the iGPU; the gfx ring no
longer times out.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant