Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amdgpu: support mem copy for LSDMA

Support memory to memory linear copy in PIO mode for LSDMA.

Signed-off-by: Likun Gao <Likun.Gao@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Likun Gao and committed by
Alex Deucher
f932ffbb 1b491330

+75
+26
drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.c
··· 23 23 24 24 #include "amdgpu.h" 25 25 #include "amdgpu_lsdma.h" 26 + 27 + #define AMDGPU_LSDMA_MAX_SIZE 0x2000000ULL 28 + 29 + int amdgpu_lsdma_copy_mem(struct amdgpu_device *adev, 30 + uint64_t src_addr, 31 + uint64_t dst_addr, 32 + uint64_t mem_size) 33 + { 34 + int ret; 35 + 36 + if (mem_size == 0) 37 + return -EINVAL; 38 + 39 + while (mem_size > 0) { 40 + uint64_t current_copy_size = min(mem_size, AMDGPU_LSDMA_MAX_SIZE); 41 + 42 + ret = adev->lsdma.funcs->copy_mem(adev, src_addr, dst_addr, current_copy_size); 43 + if (ret) 44 + return ret; 45 + src_addr += current_copy_size; 46 + dst_addr += current_copy_size; 47 + mem_size -= current_copy_size; 48 + } 49 + 50 + return 0; 51 + }
+5
drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.h
··· 29 29 }; 30 30 31 31 struct amdgpu_lsdma_funcs { 32 + int (*copy_mem)(struct amdgpu_device *adev, uint64_t src_addr, 33 + uint64_t dst_addr, uint64_t size); 32 34 }; 35 + 36 + int amdgpu_lsdma_copy_mem(struct amdgpu_device *adev, uint64_t src_addr, 37 + uint64_t dst_addr, uint64_t mem_size); 33 38 34 39 #endif
+44
drivers/gpu/drm/amd/amdgpu/lsdma_v6_0.c
··· 29 29 #include "lsdma/lsdma_6_0_0_offset.h" 30 30 #include "lsdma/lsdma_6_0_0_sh_mask.h" 31 31 32 + static int lsdma_v6_0_copy_mem(struct amdgpu_device *adev, 33 + uint64_t src_addr, 34 + uint64_t dst_addr, 35 + uint64_t size) 36 + { 37 + uint32_t usec_timeout = 5000; /* wait for 5ms */ 38 + uint32_t tmp, expect_val; 39 + int i; 40 + 41 + WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_SRC_ADDR_LO, lower_32_bits(src_addr)); 42 + WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_SRC_ADDR_HI, upper_32_bits(src_addr)); 43 + 44 + WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_DST_ADDR_LO, lower_32_bits(dst_addr)); 45 + WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_DST_ADDR_HI, upper_32_bits(dst_addr)); 46 + 47 + WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_CONTROL, 0x0); 48 + 49 + tmp = RREG32_SOC15(LSDMA, 0, regLSDMA_PIO_COMMAND); 50 + tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, BYTE_COUNT, size); 51 + tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, SRC_LOCATION, 0); 52 + tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, DST_LOCATION, 0); 53 + tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, SRC_ADDR_INC, 0); 54 + tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, DST_ADDR_INC, 0); 55 + tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, OVERLAP_DISABLE, 0); 56 + tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, CONSTANT_FILL, 0); 57 + WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_COMMAND, tmp); 58 + 59 + expect_val = LSDMA_PIO_STATUS__PIO_IDLE_MASK | LSDMA_PIO_STATUS__PIO_FIFO_EMPTY_MASK; 60 + for (i = 0; i < usec_timeout; i++) { 61 + tmp = RREG32_SOC15(LSDMA, 0, regLSDMA_PIO_STATUS); 62 + if ((tmp & expect_val) == expect_val) 63 + break; 64 + udelay(1); 65 + } 66 + 67 + if (i >= usec_timeout) { 68 + dev_err(adev->dev, "LSDMA PIO failed to copy memory!\n"); 69 + return -ETIMEDOUT; 70 + } 71 + 72 + return 0; 73 + } 74 + 32 75 const struct amdgpu_lsdma_funcs lsdma_v6_0_funcs = { 76 + .copy_mem = lsdma_v6_0_copy_mem 33 77 };