drm/amdgpu: add timeout flush mechanism to update wptr for self interrupt (v2)
authorChengming Gui <Jack.Gui@amd.com>
Tue, 14 Jul 2020 08:25:04 +0000 (16:25 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 21 Jul 2020 19:37:39 +0000 (15:37 -0400)
outstanding log reaches threshold will trigger IH ring1/2's wptr
reported, that will avoid generating interrupts to ring0 too frequent.
But if ring1/2's wptr hasn't been increased for a long time, the outstanding log
can't reach threshold so that driver can't get latest wptr info and
miss some interrupts.

v2: squash in warning fix

Signed-off-by: Chengming Gui <Jack.Gui@amd.com>
Reviewed-by: Feifei Xu <Feifei.Xu@amd.com>
Acked-by: Felix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/navi10_ih.c

index fdabaf0..350f1bf 100644 (file)
 static void navi10_ih_set_interrupt_funcs(struct amdgpu_device *adev);
 
 /**
+ * force_update_wptr_for_self_int - Force update the wptr for self interrupt
+ *
+ * @adev: amdgpu_device pointer
+ * @threshold: threshold to trigger the wptr reporting
+ * @timeout: timeout to trigger the wptr reporting
+ * @enabled: Enable/disable timeout flush mechanism
+ *
+ * threshold input range: 0 ~ 15, default 0,
+ * real_threshold = 2^threshold
+ * timeout input range: 0 ~ 20, default 8,
+ * real_timeout = (2^timeout) * 1024 / (socclk_freq)
+ *
+ * Force update wptr for self interrupt ( >= SIENNA_CICHLID).
+ */
+static void
+force_update_wptr_for_self_int(struct amdgpu_device *adev,
+                              u32 threshold, u32 timeout, bool enabled)
+{
+       u32 ih_cntl, ih_rb_cntl;
+
+       if (adev->asic_type < CHIP_SIENNA_CICHLID)
+               return;
+
+       ih_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_CNTL2);
+       ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
+
+       ih_cntl = REG_SET_FIELD(ih_cntl, IH_CNTL2,
+                               SELF_IV_FORCE_WPTR_UPDATE_TIMEOUT, timeout);
+       ih_cntl = REG_SET_FIELD(ih_cntl, IH_CNTL2,
+                               SELF_IV_FORCE_WPTR_UPDATE_ENABLE, enabled);
+       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
+                                  RB_USED_INT_THRESHOLD, threshold);
+
+       WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
+       ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
+       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
+                                  RB_USED_INT_THRESHOLD, threshold);
+       WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
+       WREG32_SOC15(OSSSYS, 0, mmIH_CNTL2, ih_cntl);
+}
+
+/**
  * navi10_ih_enable_interrupts - Enable the interrupt ring buffer
  *
  * @adev: amdgpu_device pointer
@@ -371,6 +413,8 @@ static int navi10_ih_irq_init(struct amdgpu_device *adev)
 
        /* enable interrupts */
        navi10_ih_enable_interrupts(adev);
+       /* enable wptr force update for self int */
+       force_update_wptr_for_self_int(adev, 0, 8, true);
 
        return 0;
 }
@@ -384,6 +428,7 @@ static int navi10_ih_irq_init(struct amdgpu_device *adev)
  */
 static void navi10_ih_irq_disable(struct amdgpu_device *adev)
 {
+       force_update_wptr_for_self_int(adev, 0, 8, false);
        navi10_ih_disable_interrupts(adev);
 
        /* Wait and acknowledge irq */