From: Russell King <rmk+ker...@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 at arm.linux.org.uk>
---
 drivers/staging/etnaviv/etnaviv_gpu.c | 32 +++++++++++++++++++++++++++-----
 1 file changed, 27 insertions(+), 5 deletions(-)

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);
-- 
2.1.4

Reply via email to