From: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
To: "Alex Deucher" <alexander.deucher@amd.com>,
"Christian König" <christian.koenig@amd.com>,
"David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>
Cc: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>,
<amd-gfx@lists.freedesktop.org>,
<dri-devel@lists.freedesktop.org>, <linux-kernel@vger.kernel.org>
Subject: [PATCH v3 3/6] drm/amdgpu: save ring content before resetting the device
Date: Tue, 3 Mar 2026 17:18:16 +0100 [thread overview]
Message-ID: <20260303161824.7765-3-pierre-eric.pelloux-prayer@amd.com> (raw)
In-Reply-To: <20260303161824.7765-1-pierre-eric.pelloux-prayer@amd.com>
Otherwise the content might not be relevant.
When a coredump is generated the rings with outstanding fences
are saved and then printed to the final devcoredump from the
worker thread.
Since this requires memory allocation, the ring capture might
be missing from the generated devcoredump.
Signed-off-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
.../gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c | 82 +++++++++++++++----
.../gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h | 12 +++
2 files changed, 78 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
index 0c7fc3800f17..58b2e764dd7c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
@@ -207,7 +207,9 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
struct drm_print_iterator iter;
struct amdgpu_vm_fault_info *fault_info;
struct amdgpu_ip_block *ip_block;
- int ver;
+ struct amdgpu_ring *ring;
+ int ver, i, j;
+ u32 ring_idx, off;
iter.data = buffer;
iter.offset = 0;
@@ -297,23 +299,25 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
/* Add ring buffer information */
drm_printf(&p, "Ring buffer information\n");
- for (int i = 0; i < coredump->adev->num_rings; i++) {
- int j = 0;
- struct amdgpu_ring *ring = coredump->adev->rings[i];
+ if (coredump->num_rings) {
+ for (i = 0; i < coredump->num_rings; i++) {
+ ring_idx = coredump->rings[i].ring_index;
+ ring = coredump->adev->rings[ring_idx];
+ off = coredump->rings[i].offset;
- drm_printf(&p, "ring name: %s\n", ring->name);
- drm_printf(&p, "Rptr: 0x%llx Wptr: 0x%llx RB mask: %x\n",
- amdgpu_ring_get_rptr(ring),
- amdgpu_ring_get_wptr(ring),
- ring->buf_mask);
- drm_printf(&p, "Ring size in dwords: %d\n",
- ring->ring_size / 4);
- drm_printf(&p, "Ring contents\n");
- drm_printf(&p, "Offset \t Value\n");
+ drm_printf(&p, "ring name: %s\n", ring->name);
+ drm_printf(&p, "Rptr: 0x%llx Wptr: 0x%llx RB mask: %x\n",
+ coredump->rings[i].rptr,
+ coredump->rings[i].wptr,
+ ring->buf_mask);
+ drm_printf(&p, "Ring size in dwords: %d\n",
+ ring->ring_size / 4);
+ drm_printf(&p, "Ring contents\n");
+ drm_printf(&p, "Offset \t Value\n");
- while (j < ring->ring_size) {
- drm_printf(&p, "0x%x \t 0x%x\n", j, ring->ring[j / 4]);
- j += 4;
+ for (j = 0; j < ring->ring_size; j += 4)
+ drm_printf(&p, "0x%x \t 0x%x\n", j,
+ coredump->rings_dw[off + j / 4]);
}
}
@@ -353,6 +357,8 @@ static void amdgpu_devcoredump_free(void *data)
struct amdgpu_coredump_info *coredump = data;
kvfree(coredump->formatted);
+ kvfree(coredump->rings);
+ kvfree(coredump->rings_dw);
kvfree(data);
}
@@ -390,6 +396,9 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
struct drm_device *dev = adev_to_drm(adev);
struct amdgpu_coredump_info *coredump;
struct drm_sched_job *s_job;
+ u64 total_ring_size, ring_count;
+ struct amdgpu_ring *ring;
+ int i, off, idx;
/* No need to generate a new coredump if there's one in progress already. */
if (work_pending(&adev->coredump_work))
@@ -417,6 +426,47 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
coredump->ring = to_amdgpu_ring(s_job->sched);
}
+ /* Dump ring content if memory allocation succeeds. */
+ ring_count = 0;
+ total_ring_size = 0;
+ for (i = 0; i < adev->num_rings; i++) {
+ ring = adev->rings[i];
+
+ /* Only dump rings with unsignalled fences. */
+ if (atomic_read(&ring->fence_drv.last_seq) == ring->fence_drv.sync_seq &&
+ coredump->ring != ring)
+ continue;
+
+ total_ring_size += ring->ring_size;
+ ring_count++;
+ }
+ coredump->rings_dw = kzalloc(total_ring_size, GFP_NOWAIT);
+ coredump->rings = kcalloc(ring_count, sizeof(struct amdgpu_coredump_ring), GFP_NOWAIT);
+ if (coredump->rings && coredump->rings_dw) {
+ for (i = 0, off = 0, idx = 0; i < adev->num_rings; i++) {
+ ring = adev->rings[i];
+
+ if (atomic_read(&ring->fence_drv.last_seq) == ring->fence_drv.sync_seq &&
+ coredump->ring != ring)
+ continue;
+
+ coredump->rings[idx].ring_index = ring->idx;
+ coredump->rings[idx].rptr = amdgpu_ring_get_rptr(ring);
+ coredump->rings[idx].wptr = amdgpu_ring_get_wptr(ring);
+ coredump->rings[idx].offset = off;
+
+ memcpy(&coredump->rings_dw[off], ring->ring, ring->ring_size);
+ off += ring->ring_size;
+ idx++;
+ }
+ coredump->num_rings = idx;
+ } else {
+ kvfree(coredump->rings_dw);
+ kvfree(coredump->rings);
+ coredump->rings_dw = NULL;
+ coredump->rings = NULL;
+ }
+
coredump->adev = adev;
ktime_get_ts64(&coredump->reset_time);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h
index b3582d0b4ca4..5d6c58abf589 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h
@@ -31,6 +31,13 @@
#define AMDGPU_COREDUMP_VERSION "1"
+struct amdgpu_coredump_ring {
+ u64 rptr;
+ u64 wptr;
+ u32 ring_index;
+ u32 offset;
+};
+
struct amdgpu_coredump_info {
struct amdgpu_device *adev;
struct amdgpu_task_info reset_task_info;
@@ -39,6 +46,11 @@ struct amdgpu_coredump_info {
bool skip_vram_check;
bool reset_vram_lost;
struct amdgpu_ring *ring;
+
+ struct amdgpu_coredump_ring *rings;
+ u32 *rings_dw;
+ u32 num_rings;
+
/* Readable form of coredevdump, generate once to speed up
* reading it (see drm_coredump_printer's documentation).
*/
--
2.43.0
next prev parent reply other threads:[~2026-03-03 16:20 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-03 16:18 [PATCH v3 1/6] drm/amdgpu: include ip discovery data in devcoredump Pierre-Eric Pelloux-Prayer
2026-03-03 16:18 ` [PATCH v3 2/6] drm/amdgpu: move devcoredump generation to a worker Pierre-Eric Pelloux-Prayer
2026-03-04 7:51 ` Christian König
2026-03-03 16:18 ` Pierre-Eric Pelloux-Prayer [this message]
2026-03-03 16:18 ` [PATCH v3 4/6] drm/amdgpu: extract amdgpu_vm_lock_by_pasid from amdgpu_vm_handle_fault Pierre-Eric Pelloux-Prayer
2026-03-03 16:18 ` [PATCH v3 5/6] drm/amdgpu: store ib info for devcoredump Pierre-Eric Pelloux-Prayer
2026-03-03 16:18 ` [PATCH v3 6/6] drm/amdgpu: dump job ibs in the devcoredump Pierre-Eric Pelloux-Prayer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260303161824.7765-3-pierre-eric.pelloux-prayer@amd.com \
--to=pierre-eric.pelloux-prayer@amd.com \
--cc=airlied@gmail.com \
--cc=alexander.deucher@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=christian.koenig@amd.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=linux-kernel@vger.kernel.org \
--cc=simona@ffwll.ch \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®