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

drm/amdgpu: support fill mem for LSDMA

Support constant data filling 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
d9b9aaae f932ffbb

+92 -16
+40
drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.c
··· 26 26 27 27 #define AMDGPU_LSDMA_MAX_SIZE 0x2000000ULL 28 28 29 + int amdgpu_lsdma_wait_for(struct amdgpu_device *adev, 30 + uint32_t reg_index, uint32_t reg_val, 31 + uint32_t mask) 32 + { 33 + uint32_t val; 34 + int i; 35 + 36 + for (i = 0; i < adev->usec_timeout; i++) { 37 + val = RREG32(reg_index); 38 + if ((val & mask) == reg_val) 39 + return 0; 40 + udelay(1); 41 + } 42 + 43 + return -ETIME; 44 + } 45 + 29 46 int amdgpu_lsdma_copy_mem(struct amdgpu_device *adev, 30 47 uint64_t src_addr, 31 48 uint64_t dst_addr, ··· 62 45 src_addr += current_copy_size; 63 46 dst_addr += current_copy_size; 64 47 mem_size -= current_copy_size; 48 + } 49 + 50 + return 0; 51 + } 52 + 53 + int amdgpu_lsdma_fill_mem(struct amdgpu_device *adev, 54 + uint64_t dst_addr, 55 + uint32_t data, 56 + uint64_t mem_size) 57 + { 58 + int ret; 59 + 60 + if (mem_size == 0) 61 + return -EINVAL; 62 + 63 + while (mem_size > 0) { 64 + uint64_t current_fill_size = min(mem_size, AMDGPU_LSDMA_MAX_SIZE); 65 + 66 + ret = adev->lsdma.funcs->fill_mem(adev, dst_addr, data, current_fill_size); 67 + if (ret) 68 + return ret; 69 + dst_addr += current_fill_size; 70 + mem_size -= current_fill_size; 65 71 } 66 72 67 73 return 0;
+6
drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.h
··· 31 31 struct amdgpu_lsdma_funcs { 32 32 int (*copy_mem)(struct amdgpu_device *adev, uint64_t src_addr, 33 33 uint64_t dst_addr, uint64_t size); 34 + int (*fill_mem)(struct amdgpu_device *adev, uint64_t dst_addr, 35 + uint32_t data, uint64_t size); 34 36 }; 35 37 36 38 int amdgpu_lsdma_copy_mem(struct amdgpu_device *adev, uint64_t src_addr, 37 39 uint64_t dst_addr, uint64_t mem_size); 40 + int amdgpu_lsdma_fill_mem(struct amdgpu_device *adev, uint64_t dst_addr, 41 + uint32_t data, uint64_t mem_size); 42 + int amdgpu_lsdma_wait_for(struct amdgpu_device *adev, uint32_t reg_index, 43 + uint32_t reg_val, uint32_t mask); 38 44 39 45 #endif
+46 -16
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_wait_pio_status(struct amdgpu_device *adev) 33 + { 34 + return amdgpu_lsdma_wait_for(adev, SOC15_REG_OFFSET(LSDMA, 0, regLSDMA_PIO_STATUS), 35 + LSDMA_PIO_STATUS__PIO_IDLE_MASK | LSDMA_PIO_STATUS__PIO_FIFO_EMPTY_MASK, 36 + LSDMA_PIO_STATUS__PIO_IDLE_MASK | LSDMA_PIO_STATUS__PIO_FIFO_EMPTY_MASK); 37 + } 38 + 32 39 static int lsdma_v6_0_copy_mem(struct amdgpu_device *adev, 33 40 uint64_t src_addr, 34 41 uint64_t dst_addr, 35 42 uint64_t size) 36 43 { 37 - uint32_t usec_timeout = 5000; /* wait for 5ms */ 38 - uint32_t tmp, expect_val; 39 - int i; 44 + int ret; 45 + uint32_t tmp; 40 46 41 47 WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_SRC_ADDR_LO, lower_32_bits(src_addr)); 42 48 WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_SRC_ADDR_HI, upper_32_bits(src_addr)); ··· 62 56 tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, CONSTANT_FILL, 0); 63 57 WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_COMMAND, tmp); 64 58 65 - expect_val = LSDMA_PIO_STATUS__PIO_IDLE_MASK | LSDMA_PIO_STATUS__PIO_FIFO_EMPTY_MASK; 66 - for (i = 0; i < usec_timeout; i++) { 67 - tmp = RREG32_SOC15(LSDMA, 0, regLSDMA_PIO_STATUS); 68 - if ((tmp & expect_val) == expect_val) 69 - break; 70 - udelay(1); 71 - } 72 - 73 - if (i >= usec_timeout) { 59 + ret = lsdma_v6_0_wait_pio_status(adev); 60 + if (ret) 74 61 dev_err(adev->dev, "LSDMA PIO failed to copy memory!\n"); 75 - return -ETIMEDOUT; 76 - } 77 62 78 - return 0; 63 + return ret; 64 + } 65 + 66 + static int lsdma_v6_0_fill_mem(struct amdgpu_device *adev, 67 + uint64_t dst_addr, 68 + uint32_t data, 69 + uint64_t size) 70 + { 71 + int ret; 72 + uint32_t tmp; 73 + 74 + WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_CONSTFILL_DATA, data); 75 + 76 + WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_DST_ADDR_LO, lower_32_bits(dst_addr)); 77 + WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_DST_ADDR_HI, upper_32_bits(dst_addr)); 78 + 79 + WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_CONTROL, 0x0); 80 + 81 + tmp = RREG32_SOC15(LSDMA, 0, regLSDMA_PIO_COMMAND); 82 + tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, BYTE_COUNT, size); 83 + tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, SRC_LOCATION, 0); 84 + tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, DST_LOCATION, 0); 85 + tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, SRC_ADDR_INC, 0); 86 + tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, DST_ADDR_INC, 0); 87 + tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, OVERLAP_DISABLE, 0); 88 + tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, CONSTANT_FILL, 1); 89 + WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_COMMAND, tmp); 90 + 91 + ret = lsdma_v6_0_wait_pio_status(adev); 92 + if (ret) 93 + dev_err(adev->dev, "LSDMA PIO failed to fill memory!\n"); 94 + 95 + return ret; 79 96 } 80 97 81 98 const struct amdgpu_lsdma_funcs lsdma_v6_0_funcs = { 82 - .copy_mem = lsdma_v6_0_copy_mem 99 + .copy_mem = lsdma_v6_0_copy_mem, 100 + .fill_mem = lsdma_v6_0_fill_mem 83 101 };