[PATCH 1/2] drm/amdgpu: LSDMA supports multiple threads

Alex Deucher <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
From: Philip Yang <[email protected]>

Add mutex to serialize LSDMA PIO copy and fill operations for
concurrent access from multiple threads.

A mutex is used rather than a spinlock because the underlying
lsdma_v7_1_wait_pio_status() polls with udelay(), which can
busy-wait for up to usec_timeout microseconds.

It is optional to call mutex_destroy for clarity and debug
correctness, it is no-op for release build, leave it as lsdma
block no ip callback funcs to call mutex_destroy.

Signed-off-by: Philip Yang <[email protected]>
Reviewed-by: Felix Kuehling <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c |  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.c  | 20 ++++++++++++++------
 drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.h  |  1 +
 3 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index b61c641b5be4f..1503bbf473c49 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -3849,6 +3849,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
 	spin_lock_init(&adev->mm_stats.lock);
 	spin_lock_init(&adev->virt.rlcg_reg_lock);
 	spin_lock_init(&adev->wb.lock);
+	mutex_init(&adev->lsdma.lock);
 
 	INIT_LIST_HEAD(&adev->reset_list);
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.c
index 4d1d4994ea3fe..05bc281216bfc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.c
@@ -48,23 +48,27 @@ int amdgpu_lsdma_copy_mem(struct amdgpu_device *adev,
 			  uint64_t dst_addr,
 			  uint64_t mem_size)
 {
-	int ret;
+	int ret = 0;
 
 	if (mem_size == 0)
 		return -EINVAL;
 
+	mutex_lock(&adev->lsdma.lock);
+
 	while (mem_size > 0) {
 		uint64_t current_copy_size = min(mem_size, AMDGPU_LSDMA_MAX_SIZE);
 
 		ret = adev->lsdma.funcs->copy_mem(adev, src_addr, dst_addr, current_copy_size);
 		if (ret)
-			return ret;
+			goto out_unlock;
 		src_addr += current_copy_size;
 		dst_addr += current_copy_size;
 		mem_size -= current_copy_size;
 	}
 
-	return 0;
+out_unlock:
+	mutex_unlock(&adev->lsdma.lock);
+	return ret;
 }
 
 int amdgpu_lsdma_fill_mem(struct amdgpu_device *adev,
@@ -72,20 +76,24 @@ int amdgpu_lsdma_fill_mem(struct amdgpu_device *adev,
 			  uint32_t data,
 			  uint64_t mem_size)
 {
-	int ret;
+	int ret = 0;
 
 	if (mem_size == 0)
 		return -EINVAL;
 
+	mutex_lock(&adev->lsdma.lock);
+
 	while (mem_size > 0) {
 		uint64_t current_fill_size = min(mem_size, AMDGPU_LSDMA_MAX_SIZE);
 
 		ret = adev->lsdma.funcs->fill_mem(adev, dst_addr, data, current_fill_size);
 		if (ret)
-			return ret;
+			goto out_unlock;
 		dst_addr += current_fill_size;
 		mem_size -= current_fill_size;
 	}
 
-	return 0;
+out_unlock:
+	mutex_unlock(&adev->lsdma.lock);
+	return ret;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.h
index c61ba58c5ee0d..e9a0237efd80b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.h
@@ -25,6 +25,7 @@
 #define __AMDGPU_LSDMA_H__
 
 struct amdgpu_lsdma {
+	struct mutex lock;
 	const struct amdgpu_lsdma_funcs      *funcs;
 };
 
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.