Commit 497d7cee authored by Alex Deucher's avatar Alex Deucher
Browse files

drm/amdgpu: add a spinlock to wb allocation



As we use wb slots more dynamically, we need to lock
access to avoid racing on allocation or free.

Reviewed-by: default avatarShaoyun.liu <shaoyunl@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 754c366e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+10 −1
Original line number Diff line number Diff line
@@ -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);