Not bullet proof yet, as this possibly shoots down more submits than
necessary. However it allows for fairly rapid turnarounds during
userspace development.

Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
---
 drivers/staging/etnaviv/etnaviv_gpu.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c 
b/drivers/staging/etnaviv/etnaviv_gpu.c
index 84dedb77ea76..39ac08d26260 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -719,12 +719,40 @@ static void recover_worker(struct work_struct *work)
        struct etnaviv_gpu *gpu = container_of(work, struct etnaviv_gpu,
                                               recover_work);
        struct drm_device *dev = gpu->drm;
+       unsigned long flags;
+       unsigned int i;

        dev_err(gpu->dev, "hangcheck recover!\n");

+       if (pm_runtime_get_sync(gpu->dev) < 0)
+               return;
+
        mutex_lock(&dev->struct_mutex);
-       /* TODO gpu->funcs->recover(gpu); */
+
+       etnaviv_hw_reset(gpu);
+
+       /* complete all events, the GPU won't do it after the reset */
+       spin_lock_irqsave(&gpu->event_spinlock, flags);
+       for (i = 0; i < ARRAY_SIZE(gpu->event); i++) {
+               if (!gpu->event[i].used)
+                       continue;
+               gpu->event[i].used = false;
+               complete(&gpu->event_free);
+               /*
+                * Decrement the PM count for each stuck event. This is safe
+                * even in atomic context as we use ASYNC RPM here.
+                */
+               pm_runtime_put_autosuspend(gpu->dev);
+       }
+       spin_unlock_irqrestore(&gpu->event_spinlock, flags);
+       gpu->completed_fence = gpu->submitted_fence;
+
+       etnaviv_gpu_hw_init(gpu);
+       gpu->switch_context = true;
+
        mutex_unlock(&dev->struct_mutex);
+       pm_runtime_mark_last_busy(gpu->dev);
+       pm_runtime_put_autosuspend(gpu->dev);

        /* Retire the buffer objects in a work */
        etnaviv_queue_work(gpu->drm, &gpu->retire_work);
-- 
2.5.1

Reply via email to