On SR-IOV, programming IH_RB_CNTL through PSP is slow enough for the
first MSI to arrive before ih->enabled is set. amdgpu_ih_process()
then drops the interrupt, rptr stays at 0, and RPTR_REARM never
generates another edge, so every ring hits the fence fallback timer.

Set ih->enabled before psp_reg_program() on the indirect IH path for
Navi10 and IH v6.0, and clear it if programming fails.

Change-Id: Ifc89c858149df78f78888f5649118c77195c7463
Signed-off-by: Danijel Slivka <[email protected]>
Signed-off-by: Milan Milicevic <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/ih_v6_0.c   | 13 ++++++++++++-
 drivers/gpu/drm/amd/amdgpu/navi10_ih.c | 13 ++++++++++++-
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c 
b/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c
index 8dee48649650..478b7169f44c 100644
--- a/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c
@@ -168,8 +168,19 @@ static int ih_v6_0_toggle_ring_interrupts(struct 
amdgpu_device *adev,
                tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, ENABLE_INTR, (enable ? 1 : 
0));
 
        if (amdgpu_sriov_vf(adev) && amdgpu_sriov_reg_indirect_ih(adev)) {
-               if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp))
+               /*
+                * PSP programming of IH_RB_CNTL is slow enough for MSI to
+                * arrive before this call returns. Publish ih->enabled first
+                * so amdgpu_ih_process() consumes that IV and rearms.
+                */
+               if (enable) {
+                       ih->enabled = true;
+                       smp_wmb();
+               }
+               if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp)) {
+                       ih->enabled = false;
                        return -ETIMEDOUT;
+               }
        } else {
                WREG32(ih_regs->ih_rb_cntl, tmp);
        }
diff --git a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c 
b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c
index ab12ce8da3dc..fa5148ae526d 100644
--- a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c
@@ -194,8 +194,19 @@ static int navi10_ih_toggle_ring_interrupts(struct 
amdgpu_device *adev,
                tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, ENABLE_INTR, (enable ? 1 : 
0));
 
        if (amdgpu_sriov_vf(adev) && amdgpu_sriov_reg_indirect_ih(adev)) {
-               if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp))
+               /*
+                * PSP programming of IH_RB_CNTL is slow enough for MSI to
+                * arrive before this call returns. Publish ih->enabled first
+                * so amdgpu_ih_process() consumes that IV and rearms.
+                */
+               if (enable) {
+                       ih->enabled = true;
+                       smp_wmb();
+               }
+               if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp)) {
+                       ih->enabled = false;
                        return -ETIMEDOUT;
+               }
        } else {
                WREG32(ih_regs->ih_rb_cntl, tmp);
        }
-- 
2.43.0

Reply via email to