Re: [PATCH] drm/amdgpu: Allocate coredump ring buffers per ring
Alex Deucher <[email protected]> Wed, 29 Jul 2026 09:44:10 -0400
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <CADnq5_PsLg1UhxAO2bJdKJNUpbXqkhD_UrK7CsUfPem+oPYhhA@mail.gmail.com> |
On Wed, Jul 29, 2026 at 7:43 AM Lijo Lazar <[email protected]> wrote: > > Allocate each ring buffer separately. A single allocation summing all > ring sizes can exceed the page allocator's MAX_ORDER limit and fail; > per-ring buffers stay small enough to satisfy. The existing allocation > style doesn't capture any ring data if the huge allocation fails. > Splitting into multiple allocations helps to capture as much data as > possible for the core dump. > > A failed ring is left with a NULL buffer and skipped when formatting. > > Fixes: eea85914d15b ("drm/amdgpu: save ring content before resetting the device") > Signed-off-by: Lijo Lazar <[email protected]> > Assisted-by: Claude Code Reviewed-by: Alex Deucher <[email protected]> > --- > .../gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c | 50 ++++++++++--------- > .../gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h | 3 +- > 2 files changed, 27 insertions(+), 26 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c > index 4dfea36997d4..87e15e39eb30 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c > @@ -343,7 +343,7 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf > struct amdgpu_ip_block *ip_block; > struct amdgpu_ring *ring; > int ver, i, j; > - u32 ring_idx, off; > + u32 ring_idx; > bool sizing_pass; > > sizing_pass = buffer == NULL; > @@ -443,7 +443,6 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf > 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", > @@ -452,12 +451,18 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf > ring->buf_mask); > drm_printf(&p, "Ring size in dwords: %d\n", > ring->ring_size / 4); > + > + if (!coredump->rings[i].ring_dw) { > + drm_printf(&p, "Ring contents unavailable\n"); > + continue; > + } > + > drm_printf(&p, "Ring contents\n"); > drm_printf(&p, "Offset \t Value\n"); > > 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]); > + coredump->rings[i].ring_dw[j / 4]); > } > } > > @@ -498,10 +503,12 @@ amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count, > static void amdgpu_devcoredump_free(void *data) > { > struct amdgpu_coredump_info *coredump = data; > + u32 i; > > kvfree(coredump->formatted); > + for (i = 0; i < coredump->num_rings; i++) > + kvfree(coredump->rings[i].ring_dw); > kvfree(coredump->rings); > - kvfree(coredump->rings_dw); > kvfree(data); > } > > @@ -543,9 +550,9 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check, > struct amdgpu_coredump_info *coredump; > size_t size = sizeof(*coredump); > struct drm_sched_job *s_job; > - u64 total_ring_size, ring_count; > + u64 ring_count; > struct amdgpu_ring *ring; > - int i, off, idx; > + int i, idx; > > /* No need to generate a new coredump if there's one in progress already. */ > if (work_busy(&adev->coredump_work)) > @@ -585,7 +592,6 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check, > > /* 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]; > > @@ -594,38 +600,34 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check, > coredump->ring != ring) > continue; > > - total_ring_size += ring->ring_size; > ring_count++; > } > - if (ring_count) { > - coredump->rings_dw = kvzalloc(total_ring_size, GFP_NOWAIT); > + if (ring_count) > coredump->rings = kvcalloc(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 && idx < ring_count; i++) { > + if (coredump->rings) { > + for (i = 0, idx = 0; i < adev->num_rings && idx < ring_count; i++) { > + struct amdgpu_coredump_ring *cdump_ring; > + > 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; > + cdump_ring = &coredump->rings[idx]; > + > + cdump_ring->ring_dw = kvzalloc(ring->ring_size, GFP_NOWAIT); > + if (cdump_ring->ring_dw) > + memcpy(cdump_ring->ring_dw, ring->ring, ring->ring_size); > > - memcpy(&coredump->rings_dw[off], ring->ring, ring->ring_size); > - off += ring->ring_size / 4; > + cdump_ring->ring_index = ring->idx; > + cdump_ring->rptr = amdgpu_ring_get_rptr(ring); > + cdump_ring->wptr = amdgpu_ring_get_wptr(ring); > idx++; > } > coredump->num_rings = idx; > - } else { > - kvfree(coredump->rings_dw); > - kvfree(coredump->rings); > - coredump->rings_dw = NULL; > - coredump->rings = NULL; > } > > coredump->adev = adev; > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h > index 63f27337c09a..cb874d8c3394 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h > @@ -34,8 +34,8 @@ > struct amdgpu_coredump_ring { > u64 rptr; > u64 wptr; > + u32 *ring_dw; > u32 ring_index; > - u32 offset; > }; > > struct amdgpu_coredump_ib_info { > @@ -53,7 +53,6 @@ struct amdgpu_coredump_info { > struct amdgpu_ring *ring; > > struct amdgpu_coredump_ring *rings; > - u32 *rings_dw; > u32 num_rings; > > /* Readable form of coredevdump, generate once to speed up > -- > 2.49.0 >