[PATCH 42/48] staging: etnaviv: implement simple hang recovery
Lucas Stach
l.stach at pengutronix.de
Fri Sep 25 04:57:54 PDT 2015
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
More information about the dri-devel
mailing list