drm/amdgpu: add mutex lock for cper ring
authorTao Zhou <tao.zhou1@amd.com>
Mon, 10 Feb 2025 07:28:37 +0000 (15:28 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 17 Feb 2025 19:09:30 +0000 (14:09 -0500)
Avoid the confliction between read and write of ring buffer.

Signed-off-by: Tao Zhou <tao.zhou1@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c
drivers/gpu/drm/amd/amdgpu/amdgpu_cper.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c

index b70cf13aa9c0a23577c2f27b55bcb4bd9908e860..57775546e64befdee5d217bb004f5e2d67d65be9 100644 (file)
@@ -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;
index add25975d4f6fe51683bd49012caea5a4f6193f9..d35d1ddac7ccf01b327757d3a5bffa54d20ed9d7 100644 (file)
@@ -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,
index cb92d41e0ae6f02b7ac2b565861f951942167f49..f53887e2f52873189357b3d0d8a13bb63fa7001c 100644 (file)
@@ -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;
 }