[PATCH] drm/amd/display: fix EPERM reading amdgpu_dm_dmub_fw_state

Lars Nieradzik <[email protected]> Sat, 8 Aug 2026 19:09:26 +0200
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
dmub_fw_state_show() returns seq_write()'s value directly. On overflow
seq_write() returns a literal -1 rather than a meaningful error code, and
seq_read_iter() treats any negative return from ->show() as fatal, so it
breaks out before reaching the grow-and-retry further down the same loop:

		err = m->op->show(m, p);
		if (err < 0)		// hard error
			break;
		if (unlikely(err))	// ->show() says "skip it"
			m->count = 0;
		if (unlikely(!m->count)) { // empty record
			p = m->op->next(m, p, &m->index);
			continue;
		}
		if (!seq_has_overflowed(m)) // got it
			goto Fill;
		// need a bigger buffer
		m->op->stop(m, p);
		kvfree(m->buf);
		m->count = 0;
		m->buf = seq_buf_alloc(m->size <<= 1);

The DMUB_WINDOW_6_FW_STATE region is much larger than the initial one-page
seq_file buffer, so seq_write() always overflows on the first pass. The -1
breaks the loop before seq_has_overflowed() is ever tested, and since -1 is
-EPERM userspace sees:

  # cat /sys/kernel/debug/dri/0/amdgpu_dm_dmub_fw_state
  cat: ...: Operation not permitted

That reads as a permissions problem even though the file is 0644 and
the read is performed as root, so the file has been unusable since it
was added.

The adjacent dmub_tracebuffer_show() shows the correct pattern: it
emits via seq_printf() and returns 0, letting seq_has_overflowed()
drive the retry. On a Ryzen 9 8945HS (Phoenix, DCN 3.1.4) that sibling
returns 224332 bytes from the same debugfs directory, so the growth
loop handles output of this magnitude without difficulty.

Return 0 and let the seq_file core detect the overflow.

Fixes: 2364076772b1 ("drm/amd/display: Add DMUB firmware state debugfs")
Assisted-by: Claude:claude-opus-5
Signed-off-by: Lars Nieradzik <[email protected]>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index c4b2fc690fd7..ea4cae7d140f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -989,7 +989,9 @@ static int dmub_fw_state_show(struct seq_file *m, void *data)
 
 	state_size = fb_info->fb[DMUB_WINDOW_6_FW_STATE].size;
 
-	return seq_write(m, state_base, state_size);
+	seq_write(m, state_base, state_size);
+
+	return 0;
 }
 
 /* replay_capability_show() - show eDP panel replay capability

base-commit: c4f76bf5e107bcda6e496f1c4060c55af091fa79
-- 
2.55.0