Skip to content

Commit eea8591

Browse files
peppsacalexdeucher
authored andcommitted
drm/amdgpu: save ring content before resetting the device
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> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent 48c33af commit eea8591

2 files changed

Lines changed: 80 additions & 18 deletions

File tree

drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,9 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
214214
struct drm_print_iterator iter;
215215
struct amdgpu_vm_fault_info *fault_info;
216216
struct amdgpu_ip_block *ip_block;
217-
int ver;
217+
struct amdgpu_ring *ring;
218+
int ver, i, j;
219+
u32 ring_idx, off;
218220

219221
iter.data = buffer;
220222
iter.offset = 0;
@@ -303,23 +305,25 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
303305

304306
/* Add ring buffer information */
305307
drm_printf(&p, "Ring buffer information\n");
306-
for (int i = 0; i < coredump->adev->num_rings; i++) {
307-
int j = 0;
308-
struct amdgpu_ring *ring = coredump->adev->rings[i];
309-
310-
drm_printf(&p, "ring name: %s\n", ring->name);
311-
drm_printf(&p, "Rptr: 0x%llx Wptr: 0x%llx RB mask: %x\n",
312-
amdgpu_ring_get_rptr(ring),
313-
amdgpu_ring_get_wptr(ring),
314-
ring->buf_mask);
315-
drm_printf(&p, "Ring size in dwords: %d\n",
316-
ring->ring_size / 4);
317-
drm_printf(&p, "Ring contents\n");
318-
drm_printf(&p, "Offset \t Value\n");
319-
320-
while (j < ring->ring_size) {
321-
drm_printf(&p, "0x%x \t 0x%x\n", j, ring->ring[j / 4]);
322-
j += 4;
308+
if (coredump->num_rings) {
309+
for (i = 0; i < coredump->num_rings; i++) {
310+
ring_idx = coredump->rings[i].ring_index;
311+
ring = coredump->adev->rings[ring_idx];
312+
off = coredump->rings[i].offset;
313+
314+
drm_printf(&p, "ring name: %s\n", ring->name);
315+
drm_printf(&p, "Rptr: 0x%llx Wptr: 0x%llx RB mask: %x\n",
316+
coredump->rings[i].rptr,
317+
coredump->rings[i].wptr,
318+
ring->buf_mask);
319+
drm_printf(&p, "Ring size in dwords: %d\n",
320+
ring->ring_size / 4);
321+
drm_printf(&p, "Ring contents\n");
322+
drm_printf(&p, "Offset \t Value\n");
323+
324+
for (j = 0; j < ring->ring_size; j += 4)
325+
drm_printf(&p, "0x%x \t 0x%x\n", j,
326+
coredump->rings_dw[off + j / 4]);
323327
}
324328
}
325329

@@ -359,6 +363,8 @@ static void amdgpu_devcoredump_free(void *data)
359363
struct amdgpu_coredump_info *coredump = data;
360364

361365
kvfree(coredump->formatted);
366+
kvfree(coredump->rings);
367+
kvfree(coredump->rings_dw);
362368
kvfree(data);
363369
}
364370

@@ -396,6 +402,9 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
396402
struct drm_device *dev = adev_to_drm(adev);
397403
struct amdgpu_coredump_info *coredump;
398404
struct drm_sched_job *s_job;
405+
u64 total_ring_size, ring_count;
406+
struct amdgpu_ring *ring;
407+
int i, off, idx;
399408

400409
/* No need to generate a new coredump if there's one in progress already. */
401410
if (work_pending(&adev->coredump_work))
@@ -423,6 +432,47 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
423432
coredump->ring = to_amdgpu_ring(s_job->sched);
424433
}
425434

435+
/* Dump ring content if memory allocation succeeds. */
436+
ring_count = 0;
437+
total_ring_size = 0;
438+
for (i = 0; i < adev->num_rings; i++) {
439+
ring = adev->rings[i];
440+
441+
/* Only dump rings with unsignalled fences. */
442+
if (atomic_read(&ring->fence_drv.last_seq) == ring->fence_drv.sync_seq &&
443+
coredump->ring != ring)
444+
continue;
445+
446+
total_ring_size += ring->ring_size;
447+
ring_count++;
448+
}
449+
coredump->rings_dw = kzalloc(total_ring_size, GFP_NOWAIT);
450+
coredump->rings = kcalloc(ring_count, sizeof(struct amdgpu_coredump_ring), GFP_NOWAIT);
451+
if (coredump->rings && coredump->rings_dw) {
452+
for (i = 0, off = 0, idx = 0; i < adev->num_rings; i++) {
453+
ring = adev->rings[i];
454+
455+
if (atomic_read(&ring->fence_drv.last_seq) == ring->fence_drv.sync_seq &&
456+
coredump->ring != ring)
457+
continue;
458+
459+
coredump->rings[idx].ring_index = ring->idx;
460+
coredump->rings[idx].rptr = amdgpu_ring_get_rptr(ring);
461+
coredump->rings[idx].wptr = amdgpu_ring_get_wptr(ring);
462+
coredump->rings[idx].offset = off;
463+
464+
memcpy(&coredump->rings_dw[off], ring->ring, ring->ring_size);
465+
off += ring->ring_size;
466+
idx++;
467+
}
468+
coredump->num_rings = idx;
469+
} else {
470+
kvfree(coredump->rings_dw);
471+
kvfree(coredump->rings);
472+
coredump->rings_dw = NULL;
473+
coredump->rings = NULL;
474+
}
475+
426476
coredump->adev = adev;
427477

428478
ktime_get_ts64(&coredump->reset_time);

drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@
3131

3232
#define AMDGPU_COREDUMP_VERSION "1"
3333

34+
struct amdgpu_coredump_ring {
35+
u64 rptr;
36+
u64 wptr;
37+
u32 ring_index;
38+
u32 offset;
39+
};
40+
3441
struct amdgpu_coredump_info {
3542
struct amdgpu_device *adev;
3643
struct amdgpu_task_info reset_task_info;
@@ -39,6 +46,11 @@ struct amdgpu_coredump_info {
3946
bool skip_vram_check;
4047
bool reset_vram_lost;
4148
struct amdgpu_ring *ring;
49+
50+
struct amdgpu_coredump_ring *rings;
51+
u32 *rings_dw;
52+
u32 num_rings;
53+
4254
/* Readable form of coredevdump, generate once to speed up
4355
* reading it (see drm_coredump_printer's documentation).
4456
*/

0 commit comments

Comments
 (0)