diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/tonga_ih.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/tonga_ih.c | 91 |
1 files changed, 26 insertions, 65 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c index 3abffd06b5c7..a20b711a6756 100644 --- a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c @@ -99,9 +99,9 @@ static void tonga_ih_disable_interrupts(struct amdgpu_device *adev) */ static int tonga_ih_irq_init(struct amdgpu_device *adev) { - int rb_bufsz; u32 interrupt_cntl, ih_rb_cntl, ih_doorbell_rtpr; - u64 wptr_off; + struct amdgpu_ih_ring *ih = &adev->irq.ih; + int rb_bufsz; /* disable irqs */ tonga_ih_disable_interrupts(adev); @@ -118,10 +118,7 @@ static int tonga_ih_irq_init(struct amdgpu_device *adev) WREG32(mmINTERRUPT_CNTL, interrupt_cntl); /* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/ - if (adev->irq.ih.use_bus_addr) - WREG32(mmIH_RB_BASE, adev->irq.ih.rb_dma_addr >> 8); - else - WREG32(mmIH_RB_BASE, adev->irq.ih.gpu_addr >> 8); + WREG32(mmIH_RB_BASE, ih->gpu_addr >> 8); rb_bufsz = order_base_2(adev->irq.ih.ring_size / 4); ih_rb_cntl = REG_SET_FIELD(0, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); @@ -136,12 +133,8 @@ static int tonga_ih_irq_init(struct amdgpu_device *adev) WREG32(mmIH_RB_CNTL, ih_rb_cntl); /* set the writeback address whether it's enabled or not */ - if (adev->irq.ih.use_bus_addr) - wptr_off = adev->irq.ih.rb_dma_addr + (adev->irq.ih.wptr_offs * 4); - else - wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4); - WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off)); - WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF); + WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr)); + WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF); /* set rptr, wptr to 0 */ WREG32(mmIH_RB_RPTR, 0); @@ -193,14 +186,12 @@ static void tonga_ih_irq_disable(struct amdgpu_device *adev) * Used by cz_irq_process(VI). * Returns the value of the wptr. */ -static u32 tonga_ih_get_wptr(struct amdgpu_device *adev) +static u32 tonga_ih_get_wptr(struct amdgpu_device *adev, + struct amdgpu_ih_ring *ih) { u32 wptr, tmp; - if (adev->irq.ih.use_bus_addr) - wptr = le32_to_cpu(adev->irq.ih.ring[adev->irq.ih.wptr_offs]); - else - wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]); + wptr = le32_to_cpu(*ih->wptr_cpu); if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) { wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0); @@ -209,41 +200,13 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev) * this should allow us to catchup. */ dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", - wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask); - adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask; + wptr, ih->rptr, (wptr + 16) & ih->ptr_mask); + ih->rptr = (wptr + 16) & ih->ptr_mask; tmp = RREG32(mmIH_RB_CNTL); tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); WREG32(mmIH_RB_CNTL, tmp); } - return (wptr & adev->irq.ih.ptr_mask); -} - -/** - * tonga_ih_prescreen_iv - prescreen an interrupt vector - * - * @adev: amdgpu_device pointer - * - * Returns true if the interrupt vector should be further processed. - */ -static bool tonga_ih_prescreen_iv(struct amdgpu_device *adev) -{ - u32 ring_index = adev->irq.ih.rptr >> 2; - u16 pasid; - - switch (le32_to_cpu(adev->irq.ih.ring[ring_index]) & 0xff) { - case 146: - case 147: - pasid = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]) >> 16; - if (!pasid || amdgpu_vm_pasid_fault_credit(adev, pasid)) - return true; - break; - default: - /* Not a VM fault */ - return true; - } - - adev->irq.ih.rptr += 16; - return false; + return (wptr & ih->ptr_mask); } /** @@ -255,16 +218,17 @@ static bool tonga_ih_prescreen_iv(struct amdgpu_device *adev) * position and also advance the position. */ static void tonga_ih_decode_iv(struct amdgpu_device *adev, - struct amdgpu_iv_entry *entry) + struct amdgpu_ih_ring *ih, + struct amdgpu_iv_entry *entry) { /* wptr/rptr are in bytes! */ - u32 ring_index = adev->irq.ih.rptr >> 2; + u32 ring_index = ih->rptr >> 2; uint32_t dw[4]; - dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]); - dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]); - dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]); - dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]); + dw[0] = le32_to_cpu(ih->ring[ring_index + 0]); + dw[1] = le32_to_cpu(ih->ring[ring_index + 1]); + dw[2] = le32_to_cpu(ih->ring[ring_index + 2]); + dw[3] = le32_to_cpu(ih->ring[ring_index + 3]); entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY; entry->src_id = dw[0] & 0xff; @@ -274,7 +238,7 @@ static void tonga_ih_decode_iv(struct amdgpu_device *adev, entry->pasid = (dw[2] >> 16) & 0xffff; /* wptr/rptr are in bytes! */ - adev->irq.ih.rptr += 16; + ih->rptr += 16; } /** @@ -284,17 +248,15 @@ static void tonga_ih_decode_iv(struct amdgpu_device *adev, * * Set the IH ring buffer rptr. */ -static void tonga_ih_set_rptr(struct amdgpu_device *adev) +static void tonga_ih_set_rptr(struct amdgpu_device *adev, + struct amdgpu_ih_ring *ih) { - if (adev->irq.ih.use_doorbell) { + if (ih->use_doorbell) { /* XXX check if swapping is necessary on BE */ - if (adev->irq.ih.use_bus_addr) - adev->irq.ih.ring[adev->irq.ih.rptr_offs] = adev->irq.ih.rptr; - else - adev->wb.wb[adev->irq.ih.rptr_offs] = adev->irq.ih.rptr; - WDOORBELL32(adev->irq.ih.doorbell_index, adev->irq.ih.rptr); + *ih->rptr_cpu = ih->rptr; + WDOORBELL32(ih->doorbell_index, ih->rptr); } else { - WREG32(mmIH_RB_RPTR, adev->irq.ih.rptr); + WREG32(mmIH_RB_RPTR, ih->rptr); } } @@ -322,7 +284,7 @@ static int tonga_ih_sw_init(void *handle) return r; adev->irq.ih.use_doorbell = true; - adev->irq.ih.doorbell_index = AMDGPU_DOORBELL_IH; + adev->irq.ih.doorbell_index = adev->doorbell_index.ih; r = amdgpu_irq_init(adev); @@ -506,7 +468,6 @@ static const struct amd_ip_funcs tonga_ih_ip_funcs = { static const struct amdgpu_ih_funcs tonga_ih_funcs = { .get_wptr = tonga_ih_get_wptr, - .prescreen_iv = tonga_ih_prescreen_iv, .decode_iv = tonga_ih_decode_iv, .set_rptr = tonga_ih_set_rptr }; |