drm/amdgpu: add a spinlock to wb allocation
authorAlex Deucher <alexander.deucher@amd.com>
Fri, 19 Apr 2024 22:03:32 +0000 (18:03 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 26 Apr 2024 21:22:40 +0000 (17:22 -0400)
As we use wb slots more dynamically, we need to lock
access to avoid racing on allocation or free.

Reviewed-by: Shaoyun.liu <shaoyunl@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c

index cac0ca6..f87d53e 100644 (file)
@@ -502,6 +502,7 @@ struct amdgpu_wb {
        uint64_t                gpu_addr;
        u32                     num_wb; /* Number of wb slots actually reserved for amdgpu. */
        unsigned long           used[DIV_ROUND_UP(AMDGPU_MAX_WB, BITS_PER_LONG)];
+       spinlock_t              lock;
 };
 
 int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb);
index f8a34db..8692563 100644 (file)
@@ -1482,13 +1482,17 @@ static int amdgpu_device_wb_init(struct amdgpu_device *adev)
  */
 int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb)
 {
-       unsigned long offset = find_first_zero_bit(adev->wb.used, adev->wb.num_wb);
+       unsigned long flags, offset;
 
+       spin_lock_irqsave(&adev->wb.lock, flags);
+       offset = find_first_zero_bit(adev->wb.used, adev->wb.num_wb);
        if (offset < adev->wb.num_wb) {
                __set_bit(offset, adev->wb.used);
+               spin_unlock_irqrestore(&adev->wb.lock, flags);
                *wb = offset << 3; /* convert to dw offset */
                return 0;
        } else {
+               spin_unlock_irqrestore(&adev->wb.lock, flags);
                return -EINVAL;
        }
 }
@@ -1503,9 +1507,13 @@ int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb)
  */
 void amdgpu_device_wb_free(struct amdgpu_device *adev, u32 wb)
 {
+       unsigned long flags;
+
        wb >>= 3;
+       spin_lock_irqsave(&adev->wb.lock, flags);
        if (wb < adev->wb.num_wb)
                __clear_bit(wb, adev->wb.used);
+       spin_unlock_irqrestore(&adev->wb.lock, flags);
 }
 
 /**
@@ -4061,6 +4069,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
        spin_lock_init(&adev->se_cac_idx_lock);
        spin_lock_init(&adev->audio_endpt_idx_lock);
        spin_lock_init(&adev->mm_stats.lock);
+       spin_lock_init(&adev->wb.lock);
 
        INIT_LIST_HEAD(&adev->shadow_list);
        mutex_init(&adev->shadow_list_lock);