Commit c4ef8a73 authored by Philip Yang's avatar Philip Yang Committed by Alex Deucher

drm/amdgpu: enable Navi retry fault wptr overflow

If xnack is on, VM retry fault interrupt send to IH ring1, and ring1
will be full quickly. IH cannot receive other interrupts, this causes
deadlock if migrating buffer using sdma and waiting for sdma done
while handling retry fault.

Remove VMC from IH storm client, enable ring1 write pointer
overflow, then IH will drop retry fault interrupts and be able to receive
other interrupts while driver is handling retry fault.

IH ring1 write pointer doesn't writeback to memory by IH, and ring1
write pointer recorded by self-irq is not updated, so always read
the latest ring1 write pointer from register.
Signed-off-by: default avatarPhilip Yang <Philip.Yang@amd.com>
Reviewed-by: default avatarFelix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 8888e2fe
...@@ -276,10 +276,8 @@ static int navi10_ih_enable_ring(struct amdgpu_device *adev, ...@@ -276,10 +276,8 @@ static int navi10_ih_enable_ring(struct amdgpu_device *adev,
tmp = navi10_ih_rb_cntl(ih, tmp); tmp = navi10_ih_rb_cntl(ih, tmp);
if (ih == &adev->irq.ih) if (ih == &adev->irq.ih)
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RPTR_REARM, !!adev->irq.msi_enabled); tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RPTR_REARM, !!adev->irq.msi_enabled);
if (ih == &adev->irq.ih1) { if (ih == &adev->irq.ih1)
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_ENABLE, 0);
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_FULL_DRAIN_ENABLE, 1); tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_FULL_DRAIN_ENABLE, 1);
}
if (amdgpu_sriov_vf(adev) && amdgpu_sriov_reg_indirect_ih(adev)) { if (amdgpu_sriov_vf(adev) && amdgpu_sriov_reg_indirect_ih(adev)) {
if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp)) { if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp)) {
...@@ -320,7 +318,6 @@ static int navi10_ih_irq_init(struct amdgpu_device *adev) ...@@ -320,7 +318,6 @@ static int navi10_ih_irq_init(struct amdgpu_device *adev)
{ {
struct amdgpu_ih_ring *ih[] = {&adev->irq.ih, &adev->irq.ih1, &adev->irq.ih2}; struct amdgpu_ih_ring *ih[] = {&adev->irq.ih, &adev->irq.ih1, &adev->irq.ih2};
u32 ih_chicken; u32 ih_chicken;
u32 tmp;
int ret; int ret;
int i; int i;
...@@ -364,15 +361,6 @@ static int navi10_ih_irq_init(struct amdgpu_device *adev) ...@@ -364,15 +361,6 @@ static int navi10_ih_irq_init(struct amdgpu_device *adev)
adev->nbio.funcs->ih_doorbell_range(adev, ih[0]->use_doorbell, adev->nbio.funcs->ih_doorbell_range(adev, ih[0]->use_doorbell,
ih[0]->doorbell_index); ih[0]->doorbell_index);
tmp = RREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL);
tmp = REG_SET_FIELD(tmp, IH_STORM_CLIENT_LIST_CNTL,
CLIENT18_IS_STORM_CLIENT, 1);
WREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL, tmp);
tmp = RREG32_SOC15(OSSSYS, 0, mmIH_INT_FLOOD_CNTL);
tmp = REG_SET_FIELD(tmp, IH_INT_FLOOD_CNTL, FLOOD_CNTL_ENABLE, 1);
WREG32_SOC15(OSSSYS, 0, mmIH_INT_FLOOD_CNTL, tmp);
pci_set_master(adev->pdev); pci_set_master(adev->pdev);
/* enable interrupts */ /* enable interrupts */
...@@ -421,12 +409,19 @@ static u32 navi10_ih_get_wptr(struct amdgpu_device *adev, ...@@ -421,12 +409,19 @@ static u32 navi10_ih_get_wptr(struct amdgpu_device *adev,
u32 wptr, tmp; u32 wptr, tmp;
struct amdgpu_ih_regs *ih_regs; struct amdgpu_ih_regs *ih_regs;
wptr = le32_to_cpu(*ih->wptr_cpu); if (ih == &adev->irq.ih) {
ih_regs = &ih->ih_regs; /* Only ring0 supports writeback. On other rings fall back
* to register-based code with overflow checking below.
*/
wptr = le32_to_cpu(*ih->wptr_cpu);
if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
goto out; goto out;
}
ih_regs = &ih->ih_regs;
/* Double check that the overflow wasn't already cleared. */
wptr = RREG32_NO_KIQ(ih_regs->ih_rb_wptr); wptr = RREG32_NO_KIQ(ih_regs->ih_rb_wptr);
if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
goto out; goto out;
...@@ -514,15 +509,11 @@ static int navi10_ih_self_irq(struct amdgpu_device *adev, ...@@ -514,15 +509,11 @@ static int navi10_ih_self_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source, struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry) struct amdgpu_iv_entry *entry)
{ {
uint32_t wptr = cpu_to_le32(entry->src_data[0]);
switch (entry->ring_id) { switch (entry->ring_id) {
case 1: case 1:
*adev->irq.ih1.wptr_cpu = wptr;
schedule_work(&adev->irq.ih1_work); schedule_work(&adev->irq.ih1_work);
break; break;
case 2: case 2:
*adev->irq.ih2.wptr_cpu = wptr;
schedule_work(&adev->irq.ih2_work); schedule_work(&adev->irq.ih2_work);
break; break;
default: break; default: break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment