drm/amdgpu/sdma4: Enable sdma poll mem addr on vega10 for SRIOV
authorFrank Min <Frank.Min@amd.com>
Wed, 28 Jun 2017 12:02:04 +0000 (20:02 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 15 Aug 2017 18:45:49 +0000 (14:45 -0400)
While doing flr on VFs, there is possibility to lost the doorbell
writing for sdma, so enable poll mem for sdma, then sdma fw would
check the pollmem holding wptr.

Signed-off-by: Frank Min <Frank.Min@amd.com>
Signed-off-by: Xiangliang.Yu <Xiangliang.Yu@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c

index d02f248b2028ebd931564c304918148320a00ebd..0fa6438c152caf197d047a44690eb230a937a250 100644 (file)
@@ -1209,6 +1209,7 @@ struct amdgpu_sdma_instance {
 
        struct amdgpu_ring      ring;
        bool                    burst_nop;
+       uint32_t                poll_mem_offs;
 };
 
 struct amdgpu_sdma {
index 591f3e7fb5089bbe0e650dad310c6b26f7f75f3a..5c247082f699122b979cc3d8ad0a0ea94173da34 100644 (file)
@@ -35,6 +35,7 @@
 #include "vega10/MMHUB/mmhub_1_0_offset.h"
 #include "vega10/MMHUB/mmhub_1_0_sh_mask.h"
 #include "vega10/HDP/hdp_4_0_offset.h"
+#include "vega10/NBIO/nbio_6_1_offset.h"
 #include "raven1/SDMA0/sdma0_4_1_default.h"
 
 #include "soc15_common.h"
@@ -287,6 +288,8 @@ static uint64_t sdma_v4_0_ring_get_wptr(struct amdgpu_ring *ring)
  */
 static void sdma_v4_0_ring_set_wptr(struct amdgpu_ring *ring)
 {
+       int i;
+       u32 offset;
        struct amdgpu_device *adev = ring->adev;
 
        DRM_DEBUG("Setting write pointer\n");
@@ -303,6 +306,17 @@ static void sdma_v4_0_ring_set_wptr(struct amdgpu_ring *ring)
                adev->wb.wb[ring->wptr_offs + 1] = upper_32_bits(ring->wptr << 2);
                DRM_DEBUG("calling WDOORBELL64(0x%08x, 0x%016llx)\n",
                                ring->doorbell_index, ring->wptr << 2);
+
+               if (amdgpu_sriov_vf(adev)) {
+                       for (i = 0; i < adev->sdma.num_instances; i++) {
+                               if (&adev->sdma.instance[i].ring == ring) {
+                                       offset = adev->sdma.instance[i].poll_mem_offs;
+                                       atomic64_set((atomic64_t *)&adev->wb.wb[offset],
+                                                    (ring->wptr << 2));
+                                       nbio_v6_1_hdp_flush(adev);
+                               }
+                       }
+               }
                WDOORBELL64(ring->doorbell_index, ring->wptr << 2);
        } else {
                int me = (ring == &ring->adev->sdma.instance[0].ring) ? 0 : 1;
@@ -573,9 +587,9 @@ static void sdma_v4_0_enable(struct amdgpu_device *adev, bool enable)
 static int sdma_v4_0_gfx_resume(struct amdgpu_device *adev)
 {
        struct amdgpu_ring *ring;
-       u32 rb_cntl, ib_cntl;
+       u32 rb_cntl, ib_cntl, wptr_poll_addr_lo, wptr_poll_addr_hi, wptr_poll_cntl;
        u32 rb_bufsz;
-       u32 wb_offset;
+       u32 wb_offset, poll_offset;
        u32 doorbell;
        u32 doorbell_offset;
        u32 temp;
@@ -687,6 +701,21 @@ static int sdma_v4_0_gfx_resume(struct amdgpu_device *adev)
 
                if (adev->mman.buffer_funcs_ring == ring)
                        amdgpu_ttm_set_active_vram_size(adev, adev->mc.real_vram_size);
+
+               if (amdgpu_sriov_vf(adev)) {
+                       poll_offset = adev->sdma.instance[i].poll_mem_offs * 4;
+
+                       wptr_poll_cntl = RREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_GFX_RB_WPTR_POLL_CNTL));
+                       wptr_poll_addr_lo = RREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_GFX_RB_WPTR_POLL_ADDR_LO));
+                       wptr_poll_addr_lo = REG_SET_FIELD(wptr_poll_addr_lo, SDMA0_GFX_RB_WPTR_POLL_ADDR_LO, ADDR,
+                                                               lower_32_bits(adev->wb.gpu_addr + poll_offset) >> 2);
+                       wptr_poll_addr_hi = upper_32_bits(adev->wb.gpu_addr + poll_offset);
+                       wptr_poll_cntl = REG_SET_FIELD(wptr_poll_cntl, SDMA0_GFX_RB_WPTR_POLL_CNTL, F32_POLL_ENABLE, 1);
+
+                       WREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_GFX_RB_WPTR_POLL_ADDR_LO), wptr_poll_addr_lo);
+                       WREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_GFX_RB_WPTR_POLL_ADDR_HI), wptr_poll_addr_hi);
+                       WREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_GFX_RB_WPTR_POLL_CNTL), wptr_poll_cntl);
+               }
        }
 
        return 0;
@@ -1247,6 +1276,15 @@ static int sdma_v4_0_sw_init(void *handle)
                                     (i == 0) ?
                                     AMDGPU_SDMA_IRQ_TRAP0 :
                                     AMDGPU_SDMA_IRQ_TRAP1);
+
+               if (amdgpu_sriov_vf(adev)) {
+                       r = amdgpu_wb_get_64bit(adev,
+                                               &adev->sdma.instance[i].poll_mem_offs);
+                       if (r) {
+                               dev_err(adev->dev, "(%d) failed to allocate SDMA poll mem wb.\n", r);
+                               return r;
+                       }
+               }
                if (r)
                        return r;
        }
@@ -1259,9 +1297,13 @@ static int sdma_v4_0_sw_fini(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        int i;
 
-       for (i = 0; i < adev->sdma.num_instances; i++)
+       for (i = 0; i < adev->sdma.num_instances; i++) {
                amdgpu_ring_fini(&adev->sdma.instance[i].ring);
 
+               if (amdgpu_sriov_vf(adev))
+                       amdgpu_wb_free_64bit(adev,
+                                            adev->sdma.instance[i].poll_mem_offs);
+       }
        return 0;
 }