[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