From 4d614ce8ffd757e4c7944bf9b5598b4a250a8a61 Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Wed, 22 Jan 2025 16:55:51 +0800 Subject: drm/amdgpu: add RAS CPER ring buffer And initialize it, this is a pure software ring to store RAS CPER data. v2: change ring size to 0x100000 v2: update the initialization of count_dw of cper ring, it's dword variable v3: skip VM inv eng for cper v3: init/fini when aca enabled Signed-off-by: Tao Zhou Signed-off-by: Xiang Liu Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index a6e28fe3f8d6..665c7b2b6436 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -324,20 +324,27 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, /* always set cond_exec_polling to CONTINUE */ *ring->cond_exe_cpu_addr = 1; - r = amdgpu_fence_driver_start_ring(ring, irq_src, irq_type); - if (r) { - dev_err(adev->dev, "failed initializing fences (%d).\n", r); - return r; - } + if (ring->funcs->type != AMDGPU_RING_TYPE_CPER) { + r = amdgpu_fence_driver_start_ring(ring, irq_src, irq_type); + if (r) { + dev_err(adev->dev, "failed initializing fences (%d).\n", r); + return r; + } - max_ibs_dw = ring->funcs->emit_frame_size + - amdgpu_ring_max_ibs(ring->funcs->type) * ring->funcs->emit_ib_size; - max_ibs_dw = (max_ibs_dw + ring->funcs->align_mask) & ~ring->funcs->align_mask; + max_ibs_dw = ring->funcs->emit_frame_size + + amdgpu_ring_max_ibs(ring->funcs->type) * ring->funcs->emit_ib_size; + max_ibs_dw = (max_ibs_dw + ring->funcs->align_mask) & ~ring->funcs->align_mask; - if (WARN_ON(max_ibs_dw > max_dw)) - max_dw = max_ibs_dw; + if (WARN_ON(max_ibs_dw > max_dw)) + max_dw = max_ibs_dw; - ring->ring_size = roundup_pow_of_two(max_dw * 4 * sched_hw_submission); + ring->ring_size = roundup_pow_of_two(max_dw * 4 * sched_hw_submission); + } else { + ring->ring_size = roundup_pow_of_two(max_dw * 4); + ring->count_dw = (ring->ring_size - 4) >> 2; + /* ring buffer is empty now */ + ring->wptr = *ring->rptr_cpu_addr = 0; + } ring->buf_mask = (ring->ring_size / 4) - 1; ring->ptr_mask = ring->funcs->support_64bit_ptrs ? -- cgit v1.2.3 From 5a1428242952f2c59f184e3ea6e18f3d474c911b Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Wed, 22 Jan 2025 16:57:53 +0800 Subject: drm/amdgpu: read CPER ring via debugfs We read CPER data from read pointer to write pointer without changing the pointers. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 47 ++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 665c7b2b6436..cb92d41e0ae6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -500,6 +500,7 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf, { struct amdgpu_ring *ring = file_inode(f)->i_private; uint32_t value, result, early[3]; + uint64_t p; loff_t i; int r; @@ -523,18 +524,42 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf, } } - while (size) { - if (*pos >= (ring->ring_size + 12)) - return result; + if (ring->funcs->type != AMDGPU_RING_TYPE_CPER) { + while (size) { + if (*pos >= (ring->ring_size + 12)) + return result; - value = ring->ring[(*pos - 12)/4]; - r = put_user(value, (uint32_t *)buf); - if (r) - return r; - buf += 4; - result += 4; - size -= 4; - *pos += 4; + value = ring->ring[(*pos - 12)/4]; + r = put_user(value, (uint32_t *)buf); + if (r) + return r; + buf += 4; + result += 4; + size -= 4; + *pos += 4; + } + } else { + p = early[0]; + if (early[0] <= early[1]) + size = (early[1] - early[0]); + else + size = ring->ring_size - (early[0] - early[1]); + + while (size) { + if (p == early[1]) + return result; + + value = ring->ring[p]; + r = put_user(value, (uint32_t *)buf); + if (r) + return r; + + buf += 4; + result += 4; + size--; + p++; + p &= ring->ptr_mask; + } } return result; -- cgit v1.2.3 From 8652920d2c00243e8a8ca91560a30488d95d9a1b Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Mon, 10 Feb 2025 15:28:37 +0800 Subject: drm/amdgpu: add mutex lock for cper ring Avoid the confliction between read and write of ring buffer. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c | 4 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_cper.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 21 ++++++++++++++++----- 3 files changed, 21 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c index b70cf13aa9c0..57775546e64b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c @@ -440,6 +440,7 @@ void amdgpu_cper_ring_write(struct amdgpu_ring *ring, wptr_old = ring->wptr; + mutex_lock(&ring->adev->cper.ring_lock); while (count) { ent_sz = amdgpu_cper_ring_get_ent_sz(ring, ring->wptr); chunk = umin(ent_sz, count); @@ -468,6 +469,7 @@ void amdgpu_cper_ring_write(struct amdgpu_ring *ring, pos = rptr; } while (!amdgpu_cper_is_hdr(ring, rptr)); } + mutex_unlock(&ring->adev->cper.ring_lock); if (ring->count_dw >= (count >> 2)) ring->count_dw -= (count >> 2); @@ -497,6 +499,8 @@ static int amdgpu_cper_ring_init(struct amdgpu_device *adev) { struct amdgpu_ring *ring = &(adev->cper.ring_buf); + mutex_init(&adev->cper.ring_lock); + ring->adev = NULL; ring->ring_obj = NULL; ring->use_doorbell = false; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.h index add25975d4f6..d35d1ddac7cc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.h @@ -64,6 +64,7 @@ struct amdgpu_cper { void *ring[CPER_MAX_ALLOWED_COUNT]; struct amdgpu_ring ring_buf; + struct mutex ring_lock; }; void amdgpu_cper_entry_fill_hdr(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index cb92d41e0ae6..f53887e2f528 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -510,13 +510,18 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf, result = 0; if (*pos < 12) { + if (ring->funcs->type == AMDGPU_RING_TYPE_CPER) + mutex_lock(&ring->adev->cper.ring_lock); + early[0] = amdgpu_ring_get_rptr(ring) & ring->buf_mask; early[1] = amdgpu_ring_get_wptr(ring) & ring->buf_mask; early[2] = ring->wptr & ring->buf_mask; for (i = *pos / 4; i < 3 && size; i++) { r = put_user(early[i], (uint32_t *)buf); - if (r) - return r; + if (r) { + result = r; + goto out; + } buf += 4; result += 4; size -= 4; @@ -547,12 +552,14 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf, while (size) { if (p == early[1]) - return result; + goto out; value = ring->ring[p]; r = put_user(value, (uint32_t *)buf); - if (r) - return r; + if (r) { + result = r; + goto out; + } buf += 4; result += 4; @@ -562,6 +569,10 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf, } } +out: + if (ring->funcs->type == AMDGPU_RING_TYPE_CPER) + mutex_unlock(&ring->adev->cper.ring_lock); + return result; } -- cgit v1.2.3