|
@@ -4604,6 +4604,31 @@ void cik_compute_set_wptr(struct radeon_device *rdev,
|
|
|
WDOORBELL32(ring->doorbell_index, ring->wptr);
|
|
|
}
|
|
|
|
|
|
+static void cik_compute_stop(struct radeon_device *rdev,
|
|
|
+ struct radeon_ring *ring)
|
|
|
+{
|
|
|
+ u32 j, tmp;
|
|
|
+
|
|
|
+ cik_srbm_select(rdev, ring->me, ring->pipe, ring->queue, 0);
|
|
|
+ /* Disable wptr polling. */
|
|
|
+ tmp = RREG32(CP_PQ_WPTR_POLL_CNTL);
|
|
|
+ tmp &= ~WPTR_POLL_EN;
|
|
|
+ WREG32(CP_PQ_WPTR_POLL_CNTL, tmp);
|
|
|
+ /* Disable HQD. */
|
|
|
+ if (RREG32(CP_HQD_ACTIVE) & 1) {
|
|
|
+ WREG32(CP_HQD_DEQUEUE_REQUEST, 1);
|
|
|
+ for (j = 0; j < rdev->usec_timeout; j++) {
|
|
|
+ if (!(RREG32(CP_HQD_ACTIVE) & 1))
|
|
|
+ break;
|
|
|
+ udelay(1);
|
|
|
+ }
|
|
|
+ WREG32(CP_HQD_DEQUEUE_REQUEST, 0);
|
|
|
+ WREG32(CP_HQD_PQ_RPTR, 0);
|
|
|
+ WREG32(CP_HQD_PQ_WPTR, 0);
|
|
|
+ }
|
|
|
+ cik_srbm_select(rdev, 0, 0, 0, 0);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* cik_cp_compute_enable - enable/disable the compute CP MEs
|
|
|
*
|
|
@@ -4617,6 +4642,15 @@ static void cik_cp_compute_enable(struct radeon_device *rdev, bool enable)
|
|
|
if (enable)
|
|
|
WREG32(CP_MEC_CNTL, 0);
|
|
|
else {
|
|
|
+ /*
|
|
|
+ * To make hibernation reliable we need to clear compute ring
|
|
|
+ * configuration before halting the compute ring.
|
|
|
+ */
|
|
|
+ mutex_lock(&rdev->srbm_mutex);
|
|
|
+ cik_compute_stop(rdev,&rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]);
|
|
|
+ cik_compute_stop(rdev,&rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]);
|
|
|
+ mutex_unlock(&rdev->srbm_mutex);
|
|
|
+
|
|
|
WREG32(CP_MEC_CNTL, (MEC_ME1_HALT | MEC_ME2_HALT));
|
|
|
rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false;
|
|
|
rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false;
|