drm/radeon/kms: simplify & improve GPU reset V2

This simplify and improve GPU reset for R1XX-R6XX hw, it's
not 100% reliable here are result:
- R1XX/R2XX works bunch of time in a row, sometimes it
  seems it can work indifinitly
- R3XX/R3XX the most unreliable one, sometimes you will be
  able to reset few times, sometimes not even once
- R5XX more reliable than previous hw, seems to work most
  of the times but once in a while it fails for no obvious
  reasons (same status than previous reset just no same
  happy ending)
- R6XX/R7XX are lot more reliable with this patch, still
  it seems that it can fail after a bunch (reset every
  2sec for 3hour bring down the GPU & computer)

This have been tested on various hw, for some odd reasons
i wasn't able to lockup RS480/RS690 (while they use to
love locking up).

Note that on R1XX-R5XX the cursor will disapear after
lockup haven't checked why, switch to console and back
to X will restore cursor.

Next step is to record the bogus command that leaded to
the lockup.

V2 Fix r6xx resume path to avoid reinitializing blit
module, use the gpu_lockup boolean to avoid entering
inifinite waiting loop on fence while reiniting the GPU

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 24fd545..13c9cc3 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -749,7 +749,6 @@
 			S_008014_DB2_BUSY(1) | S_008014_DB3_BUSY(1) |
 			S_008014_CB0_BUSY(1) | S_008014_CB1_BUSY(1) |
 			S_008014_CB2_BUSY(1) | S_008014_CB3_BUSY(1);
-	u32 srbm_reset = 0;
 	u32 tmp;
 
 	dev_info(rdev->dev, "GPU softreset \n");
@@ -764,7 +763,7 @@
 		dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
 	}
 	/* Disable CP parsing/prefetching */
-	WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(0xff));
+	WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));
 	/* Check if any of the rendering block is busy and reset it */
 	if ((RREG32(R_008010_GRBM_STATUS) & grbm_busy_mask) ||
 	    (RREG32(R_008014_GRBM_STATUS2) & grbm2_busy_mask)) {
@@ -783,55 +782,17 @@
 			S_008020_SOFT_RESET_VGT(1);
 		dev_info(rdev->dev, "  R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp);
 		WREG32(R_008020_GRBM_SOFT_RESET, tmp);
-		(void)RREG32(R_008020_GRBM_SOFT_RESET);
-		mdelay(1);
+		RREG32(R_008020_GRBM_SOFT_RESET);
+		mdelay(15);
 		WREG32(R_008020_GRBM_SOFT_RESET, 0);
-		(void)RREG32(R_008020_GRBM_SOFT_RESET);
 	}
 	/* Reset CP (we always reset CP) */
 	tmp = S_008020_SOFT_RESET_CP(1);
 	dev_info(rdev->dev, "R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp);
 	WREG32(R_008020_GRBM_SOFT_RESET, tmp);
-	(void)RREG32(R_008020_GRBM_SOFT_RESET);
-	udelay(50);
+	RREG32(R_008020_GRBM_SOFT_RESET);
+	mdelay(15);
 	WREG32(R_008020_GRBM_SOFT_RESET, 0);
-	(void)RREG32(R_008020_GRBM_SOFT_RESET);
-	/* Reset others GPU block if necessary */
-	if (G_000E50_RLC_BUSY(RREG32(R_000E50_SRBM_STATUS)))
-		srbm_reset |= S_000E60_SOFT_RESET_RLC(1);
-	if (G_000E50_GRBM_RQ_PENDING(RREG32(R_000E50_SRBM_STATUS)))
-		srbm_reset |= S_000E60_SOFT_RESET_GRBM(1);
-	if (G_000E50_HI_RQ_PENDING(RREG32(R_000E50_SRBM_STATUS)))
-		srbm_reset |= S_000E60_SOFT_RESET_IH(1);
-	if (G_000E50_VMC_BUSY(RREG32(R_000E50_SRBM_STATUS)))
-		srbm_reset |= S_000E60_SOFT_RESET_VMC(1);
-	if (G_000E50_MCB_BUSY(RREG32(R_000E50_SRBM_STATUS)))
-		srbm_reset |= S_000E60_SOFT_RESET_MC(1);
-	if (G_000E50_MCDZ_BUSY(RREG32(R_000E50_SRBM_STATUS)))
-		srbm_reset |= S_000E60_SOFT_RESET_MC(1);
-	if (G_000E50_MCDY_BUSY(RREG32(R_000E50_SRBM_STATUS)))
-		srbm_reset |= S_000E60_SOFT_RESET_MC(1);
-	if (G_000E50_MCDX_BUSY(RREG32(R_000E50_SRBM_STATUS)))
-		srbm_reset |= S_000E60_SOFT_RESET_MC(1);
-	if (G_000E50_MCDW_BUSY(RREG32(R_000E50_SRBM_STATUS)))
-		srbm_reset |= S_000E60_SOFT_RESET_MC(1);
-	if (G_000E50_RLC_BUSY(RREG32(R_000E50_SRBM_STATUS)))
-		srbm_reset |= S_000E60_SOFT_RESET_RLC(1);
-	if (G_000E50_SEM_BUSY(RREG32(R_000E50_SRBM_STATUS)))
-		srbm_reset |= S_000E60_SOFT_RESET_SEM(1);
-	if (G_000E50_BIF_BUSY(RREG32(R_000E50_SRBM_STATUS)))
-		srbm_reset |= S_000E60_SOFT_RESET_BIF(1);
-	dev_info(rdev->dev, "  R_000E60_SRBM_SOFT_RESET=0x%08X\n", srbm_reset);
-	WREG32(R_000E60_SRBM_SOFT_RESET, srbm_reset);
-	(void)RREG32(R_000E60_SRBM_SOFT_RESET);
-	mdelay(1);
-	WREG32(R_000E60_SRBM_SOFT_RESET, 0);
-	(void)RREG32(R_000E60_SRBM_SOFT_RESET);
-	WREG32(R_000E60_SRBM_SOFT_RESET, srbm_reset);
-	(void)RREG32(R_000E60_SRBM_SOFT_RESET);
-	mdelay(1);
-	WREG32(R_000E60_SRBM_SOFT_RESET, 0);
-	(void)RREG32(R_000E60_SRBM_SOFT_RESET);
 	/* Wait a little for things to settle down */
 	mdelay(1);
 	dev_info(rdev->dev, "  R_008010_GRBM_STATUS=0x%08X\n",
@@ -840,10 +801,6 @@
 		RREG32(R_008014_GRBM_STATUS2));
 	dev_info(rdev->dev, "  R_000E50_SRBM_STATUS=0x%08X\n",
 		RREG32(R_000E50_SRBM_STATUS));
-	/* After reset we need to reinit the asic as GPU often endup in an
-	 * incoherent state.
-	 */
-	atom_asic_init(rdev->mode_info.atom_context);
 	rv515_mc_resume(rdev, &save);
 	return 0;
 }