Merge tag 'drm-msm-fixes-2023-01-16' into msm-fixes
[sfrench/cifs-2.6.git] / drivers / gpu / drm / msm / msm_gpu.c
index 4f495eecc34badc004a238fcb7ad6b3defd5fe00..3802495003258a1258650a2c73c1a0572283dfc6 100644 (file)
@@ -494,6 +494,21 @@ static void hangcheck_timer_reset(struct msm_gpu *gpu)
                        round_jiffies_up(jiffies + msecs_to_jiffies(priv->hangcheck_period)));
 }
 
+static bool made_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
+{
+       if (ring->hangcheck_progress_retries >= DRM_MSM_HANGCHECK_PROGRESS_RETRIES)
+               return false;
+
+       if (!gpu->funcs->progress)
+               return false;
+
+       if (!gpu->funcs->progress(gpu, ring))
+               return false;
+
+       ring->hangcheck_progress_retries++;
+       return true;
+}
+
 static void hangcheck_handler(struct timer_list *t)
 {
        struct msm_gpu *gpu = from_timer(gpu, t, hangcheck_timer);
@@ -504,9 +519,12 @@ static void hangcheck_handler(struct timer_list *t)
        if (fence != ring->hangcheck_fence) {
                /* some progress has been made.. ya! */
                ring->hangcheck_fence = fence;
-       } else if (fence_before(fence, ring->fctx->last_fence)) {
+               ring->hangcheck_progress_retries = 0;
+       } else if (fence_before(fence, ring->fctx->last_fence) &&
+                       !made_progress(gpu, ring)) {
                /* no progress and not done.. hung! */
                ring->hangcheck_fence = fence;
+               ring->hangcheck_progress_retries = 0;
                DRM_DEV_ERROR(dev->dev, "%s: hangcheck detected gpu lockup rb %d!\n",
                                gpu->name, ring->id);
                DRM_DEV_ERROR(dev->dev, "%s:     completed fence: %u\n",
@@ -832,6 +850,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
                struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs,
                const char *name, struct msm_gpu_config *config)
 {
+       struct msm_drm_private *priv = drm->dev_private;
        int i, ret, nr_rings = config->nr_rings;
        void *memptrs;
        uint64_t memptrs_iova;
@@ -859,6 +878,16 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
        kthread_init_work(&gpu->recover_work, recover_worker);
        kthread_init_work(&gpu->fault_work, fault_worker);
 
+       priv->hangcheck_period = DRM_MSM_HANGCHECK_DEFAULT_PERIOD;
+
+       /*
+        * If progress detection is supported, halve the hangcheck timer
+        * duration, as it takes two iterations of the hangcheck handler
+        * to detect a hang.
+        */
+       if (funcs->progress)
+               priv->hangcheck_period /= 2;
+
        timer_setup(&gpu->hangcheck_timer, hangcheck_handler, 0);
 
        spin_lock_init(&gpu->perf_lock);