drm/radeon/cik: stop the sdma engines in the enable() function
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / radeon / cik_sdma.c
index d08b83c6267b4cde4ff5ce0ad71754c1e5e446a1..94626ea90fa57abc5efca249ab4d0d08cfc9566d 100644 (file)
@@ -51,6 +51,75 @@ u32 cik_gpu_check_soft_reset(struct radeon_device *rdev);
  * buffers.
  */
 
+/**
+ * cik_sdma_get_rptr - get the current read pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring pointer
+ *
+ * Get the current rptr from the hardware (CIK+).
+ */
+uint32_t cik_sdma_get_rptr(struct radeon_device *rdev,
+                          struct radeon_ring *ring)
+{
+       u32 rptr, reg;
+
+       if (rdev->wb.enabled) {
+               rptr = rdev->wb.wb[ring->rptr_offs/4];
+       } else {
+               if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+                       reg = SDMA0_GFX_RB_RPTR + SDMA0_REGISTER_OFFSET;
+               else
+                       reg = SDMA0_GFX_RB_RPTR + SDMA1_REGISTER_OFFSET;
+
+               rptr = RREG32(reg);
+       }
+
+       return (rptr & 0x3fffc) >> 2;
+}
+
+/**
+ * cik_sdma_get_wptr - get the current write pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring pointer
+ *
+ * Get the current wptr from the hardware (CIK+).
+ */
+uint32_t cik_sdma_get_wptr(struct radeon_device *rdev,
+                          struct radeon_ring *ring)
+{
+       u32 reg;
+
+       if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+               reg = SDMA0_GFX_RB_WPTR + SDMA0_REGISTER_OFFSET;
+       else
+               reg = SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET;
+
+       return (RREG32(reg) & 0x3fffc) >> 2;
+}
+
+/**
+ * cik_sdma_set_wptr - commit the write pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring pointer
+ *
+ * Write the wptr back to the hardware (CIK+).
+ */
+void cik_sdma_set_wptr(struct radeon_device *rdev,
+                      struct radeon_ring *ring)
+{
+       u32 reg;
+
+       if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+               reg = SDMA0_GFX_RB_WPTR + SDMA0_REGISTER_OFFSET;
+       else
+               reg = SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET;
+
+       WREG32(reg, (ring->wptr << 2) & 0x3fffc);
+}
+
 /**
  * cik_sdma_ring_ib_execute - Schedule an IB on the DMA engine
  *
@@ -87,6 +156,35 @@ void cik_sdma_ring_ib_execute(struct radeon_device *rdev,
 
 }
 
+/**
+ * cik_sdma_hdp_flush_ring_emit - emit an hdp flush on the DMA ring
+ *
+ * @rdev: radeon_device pointer
+ * @ridx: radeon ring index
+ *
+ * Emit an hdp flush packet on the requested DMA ring.
+ */
+static void cik_sdma_hdp_flush_ring_emit(struct radeon_device *rdev,
+                                        int ridx)
+{
+       struct radeon_ring *ring = &rdev->ring[ridx];
+       u32 extra_bits = (SDMA_POLL_REG_MEM_EXTRA_OP(1) |
+                         SDMA_POLL_REG_MEM_EXTRA_FUNC(3)); /* == */
+       u32 ref_and_mask;
+
+       if (ridx == R600_RING_TYPE_DMA_INDEX)
+               ref_and_mask = SDMA0;
+       else
+               ref_and_mask = SDMA1;
+
+       radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_POLL_REG_MEM, 0, extra_bits));
+       radeon_ring_write(ring, GPU_HDP_FLUSH_DONE);
+       radeon_ring_write(ring, GPU_HDP_FLUSH_REQ);
+       radeon_ring_write(ring, ref_and_mask); /* reference */
+       radeon_ring_write(ring, ref_and_mask); /* mask */
+       radeon_ring_write(ring, (0xfff << 16) | 10); /* retry count, poll interval */
+}
+
 /**
  * cik_sdma_fence_ring_emit - emit a fence on the DMA ring
  *
@@ -111,12 +209,7 @@ void cik_sdma_fence_ring_emit(struct radeon_device *rdev,
        /* generate an interrupt */
        radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_TRAP, 0, 0));
        /* flush HDP */
-       /* We should be using the new POLL_REG_MEM special op packet here
-        * but it causes sDMA to hang sometimes
-        */
-       radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000));
-       radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
-       radeon_ring_write(ring, 0);
+       cik_sdma_hdp_flush_ring_emit(rdev, fence->ring);
 }
 
 /**
@@ -157,7 +250,9 @@ static void cik_sdma_gfx_stop(struct radeon_device *rdev)
        u32 rb_cntl, reg_offset;
        int i;
 
-       radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
+       if ((rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) ||
+           (rdev->asic->copy.copy_ring_index == CAYMAN_RING_TYPE_DMA1_INDEX))
+               radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
 
        for (i = 0; i < 2; i++) {
                if (i == 0)
@@ -169,6 +264,8 @@ static void cik_sdma_gfx_stop(struct radeon_device *rdev)
                WREG32(SDMA0_GFX_RB_CNTL + reg_offset, rb_cntl);
                WREG32(SDMA0_GFX_IB_CNTL + reg_offset, 0);
        }
+       rdev->ring[R600_RING_TYPE_DMA_INDEX].ready = false;
+       rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX].ready = false;
 }
 
 /**
@@ -196,6 +293,11 @@ void cik_sdma_enable(struct radeon_device *rdev, bool enable)
        u32 me_cntl, reg_offset;
        int i;
 
+       if (enable == false) {
+               cik_sdma_gfx_stop(rdev);
+               cik_sdma_rlc_stop(rdev);
+       }
+
        for (i = 0; i < 2; i++) {
                if (i == 0)
                        reg_offset = SDMA0_REGISTER_OFFSET;
@@ -288,7 +390,9 @@ static int cik_sdma_gfx_resume(struct radeon_device *rdev)
                }
        }
 
-       radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
+       if ((rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) ||
+           (rdev->asic->copy.copy_ring_index == CAYMAN_RING_TYPE_DMA1_INDEX))
+               radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
 
        return 0;
 }
@@ -323,10 +427,6 @@ static int cik_sdma_load_microcode(struct radeon_device *rdev)
        if (!rdev->sdma_fw)
                return -EINVAL;
 
-       /* stop the gfx rings and rlc compute queues */
-       cik_sdma_gfx_stop(rdev);
-       cik_sdma_rlc_stop(rdev);
-
        /* halt the MEs */
        cik_sdma_enable(rdev, false);
 
@@ -395,9 +495,6 @@ int cik_sdma_resume(struct radeon_device *rdev)
  */
 void cik_sdma_fini(struct radeon_device *rdev)
 {
-       /* stop the gfx rings and rlc compute queues */
-       cik_sdma_gfx_stop(rdev);
-       cik_sdma_rlc_stop(rdev);
        /* halt the MEs */
        cik_sdma_enable(rdev, false);
        radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX]);
@@ -747,12 +844,7 @@ void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm
        radeon_ring_write(ring, VMID(0));
 
        /* flush HDP */
-       /* We should be using the new POLL_REG_MEM special op packet here
-        * but it causes sDMA to hang sometimes
-        */
-       radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000));
-       radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
-       radeon_ring_write(ring, 0);
+       cik_sdma_hdp_flush_ring_emit(rdev, ridx);
 
        /* flush TLB */
        radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000));