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

drm/amdgpu: simplify IH programming

Calculate all the addresses and pointers in amdgpu_ih.c

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

authored by

Christian König and committed by
Alex Deucher
d81f78b4 8bb9eb48

+73 -85
+23 -11
drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c
··· 52 52 ih->use_bus_addr = use_bus_addr; 53 53 54 54 if (use_bus_addr) { 55 + dma_addr_t dma_addr; 56 + 55 57 if (ih->ring) 56 58 return 0; 57 59 ··· 61 59 * add them to the end of the ring allocation. 62 60 */ 63 61 ih->ring = dma_alloc_coherent(adev->dev, ih->ring_size + 8, 64 - &ih->rb_dma_addr, GFP_KERNEL); 62 + &dma_addr, GFP_KERNEL); 65 63 if (ih->ring == NULL) 66 64 return -ENOMEM; 67 65 68 66 memset((void *)ih->ring, 0, ih->ring_size + 8); 69 - ih->wptr_offs = (ih->ring_size / 4) + 0; 70 - ih->rptr_offs = (ih->ring_size / 4) + 1; 67 + ih->gpu_addr = dma_addr; 68 + ih->wptr_addr = dma_addr + ih->ring_size; 69 + ih->wptr_cpu = &ih->ring[ih->ring_size / 4]; 70 + ih->rptr_addr = dma_addr + ih->ring_size + 4; 71 + ih->rptr_cpu = &ih->ring[(ih->ring_size / 4) + 1]; 71 72 } else { 72 - r = amdgpu_device_wb_get(adev, &ih->wptr_offs); 73 + unsigned wptr_offs, rptr_offs; 74 + 75 + r = amdgpu_device_wb_get(adev, &wptr_offs); 73 76 if (r) 74 77 return r; 75 78 76 - r = amdgpu_device_wb_get(adev, &ih->rptr_offs); 79 + r = amdgpu_device_wb_get(adev, &rptr_offs); 77 80 if (r) { 78 - amdgpu_device_wb_free(adev, ih->wptr_offs); 81 + amdgpu_device_wb_free(adev, wptr_offs); 79 82 return r; 80 83 } 81 84 ··· 89 82 &ih->ring_obj, &ih->gpu_addr, 90 83 (void **)&ih->ring); 91 84 if (r) { 92 - amdgpu_device_wb_free(adev, ih->rptr_offs); 93 - amdgpu_device_wb_free(adev, ih->wptr_offs); 85 + amdgpu_device_wb_free(adev, rptr_offs); 86 + amdgpu_device_wb_free(adev, wptr_offs); 94 87 return r; 95 88 } 89 + 90 + ih->wptr_addr = adev->wb.gpu_addr + wptr_offs * 4; 91 + ih->wptr_cpu = &adev->wb.wb[wptr_offs]; 92 + ih->rptr_addr = adev->wb.gpu_addr + rptr_offs * 4; 93 + ih->rptr_cpu = &adev->wb.wb[rptr_offs]; 96 94 } 97 95 return 0; 98 96 } ··· 121 109 * add them to the end of the ring allocation. 122 110 */ 123 111 dma_free_coherent(adev->dev, ih->ring_size + 8, 124 - (void *)ih->ring, ih->rb_dma_addr); 112 + (void *)ih->ring, ih->gpu_addr); 125 113 ih->ring = NULL; 126 114 } else { 127 115 amdgpu_bo_free_kernel(&ih->ring_obj, &ih->gpu_addr, 128 116 (void **)&ih->ring); 129 - amdgpu_device_wb_free(adev, ih->wptr_offs); 130 - amdgpu_device_wb_free(adev, ih->rptr_offs); 117 + amdgpu_device_wb_free(adev, (ih->wptr_addr - ih->gpu_addr) / 4); 118 + amdgpu_device_wb_free(adev, (ih->rptr_addr - ih->gpu_addr) / 4); 131 119 } 132 120 } 133 121
+14 -9
drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
··· 31 31 * R6xx+ IH ring 32 32 */ 33 33 struct amdgpu_ih_ring { 34 - struct amdgpu_bo *ring_obj; 35 - volatile uint32_t *ring; 36 - unsigned rptr; 37 34 unsigned ring_size; 38 - uint64_t gpu_addr; 39 35 uint32_t ptr_mask; 40 - atomic_t lock; 41 - bool enabled; 42 - unsigned wptr_offs; 43 - unsigned rptr_offs; 44 36 u32 doorbell_index; 45 37 bool use_doorbell; 46 38 bool use_bus_addr; 47 - dma_addr_t rb_dma_addr; /* only used when use_bus_addr = true */ 39 + 40 + struct amdgpu_bo *ring_obj; 41 + volatile uint32_t *ring; 42 + uint64_t gpu_addr; 43 + 44 + uint64_t wptr_addr; 45 + volatile uint32_t *wptr_cpu; 46 + 47 + uint64_t rptr_addr; 48 + volatile uint32_t *rptr_cpu; 49 + 50 + bool enabled; 51 + unsigned rptr; 52 + atomic_t lock; 48 53 }; 49 54 50 55 /* provided by the ih block */
+4 -5
drivers/gpu/drm/amd/amdgpu/cik_ih.c
··· 103 103 */ 104 104 static int cik_ih_irq_init(struct amdgpu_device *adev) 105 105 { 106 + struct amdgpu_ih_ring *ih = &adev->irq.ih; 106 107 int rb_bufsz; 107 108 u32 interrupt_cntl, ih_cntl, ih_rb_cntl; 108 - u64 wptr_off; 109 109 110 110 /* disable irqs */ 111 111 cik_ih_disable_interrupts(adev); ··· 131 131 ih_rb_cntl |= IH_RB_CNTL__WPTR_WRITEBACK_ENABLE_MASK; 132 132 133 133 /* set the writeback address whether it's enabled or not */ 134 - wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4); 135 - WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off)); 136 - WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF); 134 + WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr)); 135 + WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF); 137 136 138 137 WREG32(mmIH_RB_CNTL, ih_rb_cntl); 139 138 ··· 187 188 { 188 189 u32 wptr, tmp; 189 190 190 - wptr = le32_to_cpu(adev->wb.wb[ih->wptr_offs]); 191 + wptr = le32_to_cpu(*ih->wptr_cpu); 191 192 192 193 if (wptr & IH_RB_WPTR__RB_OVERFLOW_MASK) { 193 194 wptr &= ~IH_RB_WPTR__RB_OVERFLOW_MASK;
+5 -6
drivers/gpu/drm/amd/amdgpu/cz_ih.c
··· 103 103 */ 104 104 static int cz_ih_irq_init(struct amdgpu_device *adev) 105 105 { 106 - int rb_bufsz; 106 + struct amdgpu_ih_ring *ih = &adev->irq.ih; 107 107 u32 interrupt_cntl, ih_cntl, ih_rb_cntl; 108 - u64 wptr_off; 108 + int rb_bufsz; 109 109 110 110 /* disable irqs */ 111 111 cz_ih_disable_interrupts(adev); ··· 133 133 ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_WRITEBACK_ENABLE, 1); 134 134 135 135 /* set the writeback address whether it's enabled or not */ 136 - wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4); 137 - WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off)); 138 - WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF); 136 + WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr)); 137 + WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF); 139 138 140 139 WREG32(mmIH_RB_CNTL, ih_rb_cntl); 141 140 ··· 189 190 { 190 191 u32 wptr, tmp; 191 192 192 - wptr = le32_to_cpu(adev->wb.wb[ih->wptr_offs]); 193 + wptr = le32_to_cpu(*ih->wptr_cpu); 193 194 194 195 if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) { 195 196 wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
+4 -5
drivers/gpu/drm/amd/amdgpu/iceland_ih.c
··· 103 103 */ 104 104 static int iceland_ih_irq_init(struct amdgpu_device *adev) 105 105 { 106 + struct amdgpu_ih_ring *ih = &adev->irq.ih; 106 107 int rb_bufsz; 107 108 u32 interrupt_cntl, ih_cntl, ih_rb_cntl; 108 - u64 wptr_off; 109 109 110 110 /* disable irqs */ 111 111 iceland_ih_disable_interrupts(adev); ··· 133 133 ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_WRITEBACK_ENABLE, 1); 134 134 135 135 /* set the writeback address whether it's enabled or not */ 136 - wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4); 137 - WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off)); 138 - WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF); 136 + WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr)); 137 + WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF); 139 138 140 139 WREG32(mmIH_RB_CNTL, ih_rb_cntl); 141 140 ··· 189 190 { 190 191 u32 wptr, tmp; 191 192 192 - wptr = le32_to_cpu(adev->wb.wb[ih->wptr_offs]); 193 + wptr = le32_to_cpu(*ih->wptr_cpu); 193 194 194 195 if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) { 195 196 wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
+4 -5
drivers/gpu/drm/amd/amdgpu/si_ih.c
··· 57 57 58 58 static int si_ih_irq_init(struct amdgpu_device *adev) 59 59 { 60 + struct amdgpu_ih_ring *ih = &adev->irq.ih; 60 61 int rb_bufsz; 61 62 u32 interrupt_cntl, ih_cntl, ih_rb_cntl; 62 - u64 wptr_off; 63 63 64 64 si_ih_disable_interrupts(adev); 65 65 WREG32(INTERRUPT_CNTL2, adev->irq.ih.gpu_addr >> 8); ··· 76 76 (rb_bufsz << 1) | 77 77 IH_WPTR_WRITEBACK_ENABLE; 78 78 79 - wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4); 80 - WREG32(IH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off)); 81 - WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF); 79 + WREG32(IH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr)); 80 + WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF); 82 81 WREG32(IH_RB_CNTL, ih_rb_cntl); 83 82 WREG32(IH_RB_RPTR, 0); 84 83 WREG32(IH_RB_WPTR, 0); ··· 104 105 { 105 106 u32 wptr, tmp; 106 107 107 - wptr = le32_to_cpu(adev->wb.wb[ih->wptr_offs]); 108 + wptr = le32_to_cpu(*ih->wptr_cpu); 108 109 109 110 if (wptr & IH_RB_WPTR__RB_OVERFLOW_MASK) { 110 111 wptr &= ~IH_RB_WPTR__RB_OVERFLOW_MASK;
+7 -20
drivers/gpu/drm/amd/amdgpu/tonga_ih.c
··· 99 99 */ 100 100 static int tonga_ih_irq_init(struct amdgpu_device *adev) 101 101 { 102 - int rb_bufsz; 103 102 u32 interrupt_cntl, ih_rb_cntl, ih_doorbell_rtpr; 104 - u64 wptr_off; 103 + struct amdgpu_ih_ring *ih = &adev->irq.ih; 104 + int rb_bufsz; 105 105 106 106 /* disable irqs */ 107 107 tonga_ih_disable_interrupts(adev); ··· 118 118 WREG32(mmINTERRUPT_CNTL, interrupt_cntl); 119 119 120 120 /* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/ 121 - if (adev->irq.ih.use_bus_addr) 122 - WREG32(mmIH_RB_BASE, adev->irq.ih.rb_dma_addr >> 8); 123 - else 124 - WREG32(mmIH_RB_BASE, adev->irq.ih.gpu_addr >> 8); 121 + WREG32(mmIH_RB_BASE, ih->gpu_addr >> 8); 125 122 126 123 rb_bufsz = order_base_2(adev->irq.ih.ring_size / 4); 127 124 ih_rb_cntl = REG_SET_FIELD(0, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); ··· 133 136 WREG32(mmIH_RB_CNTL, ih_rb_cntl); 134 137 135 138 /* set the writeback address whether it's enabled or not */ 136 - if (adev->irq.ih.use_bus_addr) 137 - wptr_off = adev->irq.ih.rb_dma_addr + (adev->irq.ih.wptr_offs * 4); 138 - else 139 - wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4); 140 - WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off)); 141 - WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF); 139 + WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr)); 140 + WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF); 142 141 143 142 /* set rptr, wptr to 0 */ 144 143 WREG32(mmIH_RB_RPTR, 0); ··· 191 198 { 192 199 u32 wptr, tmp; 193 200 194 - if (adev->irq.ih.use_bus_addr) 195 - wptr = le32_to_cpu(ih->ring[ih->wptr_offs]); 196 - else 197 - wptr = le32_to_cpu(adev->wb.wb[ih->wptr_offs]); 201 + wptr = le32_to_cpu(*ih->wptr_cpu); 198 202 199 203 if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) { 200 204 wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0); ··· 253 263 { 254 264 if (ih->use_doorbell) { 255 265 /* XXX check if swapping is necessary on BE */ 256 - if (ih->use_bus_addr) 257 - ih->ring[ih->rptr_offs] = ih->rptr; 258 - else 259 - adev->wb.wb[ih->rptr_offs] = ih->rptr; 266 + *ih->rptr_cpu = ih->rptr; 260 267 WDOORBELL32(ih->doorbell_index, ih->rptr); 261 268 } else { 262 269 WREG32(mmIH_RB_RPTR, ih->rptr);
+12 -24
drivers/gpu/drm/amd/amdgpu/vega10_ih.c
··· 86 86 */ 87 87 static int vega10_ih_irq_init(struct amdgpu_device *adev) 88 88 { 89 + struct amdgpu_ih_ring *ih = &adev->irq.ih; 89 90 int ret = 0; 90 91 int rb_bufsz; 91 92 u32 ih_rb_cntl, ih_doorbell_rtpr; 92 93 u32 tmp; 93 - u64 wptr_off; 94 94 95 95 /* disable irqs */ 96 96 vega10_ih_disable_interrupts(adev); ··· 99 99 100 100 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL); 101 101 /* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/ 102 - if (adev->irq.ih.use_bus_addr) { 103 - WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, adev->irq.ih.rb_dma_addr >> 8); 104 - WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI, ((u64)adev->irq.ih.rb_dma_addr >> 40) & 0xff); 105 - ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SPACE, 1); 106 - } else { 107 - WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, adev->irq.ih.gpu_addr >> 8); 108 - WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI, (adev->irq.ih.gpu_addr >> 40) & 0xff); 109 - ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SPACE, 4); 110 - } 102 + WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, adev->irq.ih.gpu_addr >> 8); 103 + WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI, 104 + (adev->irq.ih.gpu_addr >> 40) & 0xff); 105 + ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SPACE, 106 + ih->use_bus_addr ? 1 : 4); 111 107 rb_bufsz = order_base_2(adev->irq.ih.ring_size / 4); 112 108 ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); 113 109 ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_OVERFLOW_ENABLE, 1); ··· 120 124 WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl); 121 125 122 126 /* set the writeback address whether it's enabled or not */ 123 - if (adev->irq.ih.use_bus_addr) 124 - wptr_off = adev->irq.ih.rb_dma_addr + (adev->irq.ih.wptr_offs * 4); 125 - else 126 - wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4); 127 - WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off)); 128 - WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFFFF); 127 + WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_LO, 128 + lower_32_bits(ih->wptr_addr)); 129 + WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_HI, 130 + upper_32_bits(ih->wptr_addr) & 0xFFFF); 129 131 130 132 /* set rptr, wptr to 0 */ 131 133 WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, 0); ··· 190 196 { 191 197 u32 wptr, tmp; 192 198 193 - if (ih->use_bus_addr) 194 - wptr = le32_to_cpu(ih->ring[ih->wptr_offs]); 195 - else 196 - wptr = le32_to_cpu(adev->wb.wb[ih->wptr_offs]); 199 + wptr = le32_to_cpu(*ih->wptr_cpu); 197 200 198 201 if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) { 199 202 wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0); ··· 266 275 { 267 276 if (ih->use_doorbell) { 268 277 /* XXX check if swapping is necessary on BE */ 269 - if (ih->use_bus_addr) 270 - ih->ring[ih->rptr_offs] = ih->rptr; 271 - else 272 - adev->wb.wb[ih->rptr_offs] = ih->rptr; 278 + *ih->rptr_cpu = ih->rptr; 273 279 WDOORBELL32(ih->doorbell_index, ih->rptr); 274 280 } else { 275 281 WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, ih->rptr);