diff mbox

[RFC,062/111] staging: etnaviv: ensure GPU reset times out

Message ID 1427988653-754-63-git-send-email-l.stach@pengutronix.de (mailing list archive)
State New, archived
Headers show

Commit Message

Lucas Stach April 2, 2015, 3:30 p.m. UTC
From: Russell King <rmk+kernel@arm.linux.org.uk>

Rather than waiting indefinitely for the GPU to reset, bound this and
if it doesn't appear to be successful, bail out and report why we
failed.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/staging/etnaviv/etnaviv_gpu.c | 32 +++++++++++++++++++++++++++-----
 1 file changed, 27 insertions(+), 5 deletions(-)
diff mbox

Patch

diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c b/drivers/staging/etnaviv/etnaviv_gpu.c
index 4cd84740eac8..f2ce3c71e583 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -287,9 +287,11 @@  static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
 	etnaviv_hw_specs(gpu);
 }
 
-static void etnaviv_hw_reset(struct etnaviv_gpu *gpu)
+static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
 {
 	u32 control, idle;
+	unsigned long timeout;
+	bool failed = true;
 
 	/* TODO
 	 *
@@ -298,7 +300,10 @@  static void etnaviv_hw_reset(struct etnaviv_gpu *gpu)
 	 * - what about VG?
 	 */
 
-	while (true) {
+	/* We hope that the GPU resets in under one second */
+	timeout = jiffies + msecs_to_jiffies(1000);
+
+	while (time_is_after_jiffies(timeout)) {
 		control = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS |
 			  VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(0x40);
 
@@ -342,15 +347,28 @@  static void etnaviv_hw_reset(struct etnaviv_gpu *gpu)
 		control = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
 
 		/* is the GPU idle? */
-		if (((control & VIVS_HI_CLOCK_CONTROL_IDLE_3D) == 0)
-		|| ((control & VIVS_HI_CLOCK_CONTROL_IDLE_2D) == 0)) {
+		if (((control & VIVS_HI_CLOCK_CONTROL_IDLE_3D) == 0) ||
+		    ((control & VIVS_HI_CLOCK_CONTROL_IDLE_2D) == 0)) {
 			dev_dbg(gpu->dev, "GPU is not idle\n");
 			continue;
 		}
 
+		failed = false;
 		break;
 	}
 
+	if (failed) {
+		idle = gpu_read(gpu, VIVS_HI_IDLE_STATE);
+		control = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
+
+		dev_err(gpu->dev, "GPU failed to reset: FE %sidle, 3D %sidle, 2D %sidle\n",
+			idle & VIVS_HI_IDLE_STATE_FE ? "" : "not ",
+			control & VIVS_HI_CLOCK_CONTROL_IDLE_3D ? "" : "not ",
+			control & VIVS_HI_CLOCK_CONTROL_IDLE_2D ? "" : "not ");
+
+		return -EBUSY;
+	}
+
 	/* We rely on the GPU running, so program the clock */
 	control = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS |
 		  VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(0x40);
@@ -359,6 +377,8 @@  static void etnaviv_hw_reset(struct etnaviv_gpu *gpu)
 	gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control |
 		  VIVS_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD);
 	gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
+
+	return 0;
 }
 
 int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
@@ -369,7 +389,9 @@  int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
 	bool mmuv2;
 
 	etnaviv_hw_identify(gpu);
-	etnaviv_hw_reset(gpu);
+	ret = etnaviv_hw_reset(gpu);
+	if (ret)
+		return ret;
 
 	/* set base addresses */
 	gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_RA, 0x0);