From f030fa4c2a858c531a802a19a9df0d350d6eb996 Mon Sep 17 00:00:00 2001 From: Steve Cohen Date: Fri, 26 Jun 2020 17:11:07 -0400 Subject: [PATCH] disp: msm: sde: wait for pending crtcs before lastclose commits If a SIG_TERM/SIG_KILL or other signal is sent to the final drm client, the driver will be force-closed. A -ERESTARTSYS error is occasionally seen from the interruptible wait in msm_atomic_commit when this occurs, and causes the lastclose cleanup to fail if any crtc is busy at that point. To prevent this, wait for any pending crtcs to complete before calling the lastclose cleanup commits. Change-Id: Ib6a5e55a4b737213756cb9ed8364d5c34ab47c16 Signed-off-by: Steve Cohen --- msm/msm_drv.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/msm/msm_drv.c b/msm/msm_drv.c index 3382a4f112..4fead9512e 100644 --- a/msm/msm_drv.c +++ b/msm/msm_drv.c @@ -65,6 +65,23 @@ #define MSM_VERSION_MINOR 4 #define MSM_VERSION_PATCHLEVEL 0 +#define LASTCLOSE_TIMEOUT_MS 500 + +#define msm_wait_event_timeout(waitq, cond, timeout_ms, ret) \ + do { \ + ktime_t cur_ktime; \ + ktime_t exp_ktime; \ + s64 wait_time_jiffies = msecs_to_jiffies(timeout_ms); \ +\ + exp_ktime = ktime_add_ms(ktime_get(), timeout_ms); \ + do { \ + ret = wait_event_timeout(waitq, cond, \ + wait_time_jiffies); \ + cur_ktime = ktime_get(); \ + } while ((!cond) && (ret == 0) && \ + (ktime_compare_safe(exp_ktime, cur_ktime) > 0));\ + } while (0) + static void msm_fb_output_poll_changed(struct drm_device *dev) { struct msm_drm_private *priv = NULL; @@ -1022,6 +1039,13 @@ static void msm_lastclose(struct drm_device *dev) /* wait for pending vblank requests to be executed by worker thread */ flush_workqueue(priv->wq); + /* wait for any pending crtcs to finish before lastclose commit */ + msm_wait_event_timeout(priv->pending_crtcs_event, !priv->pending_crtcs, + LASTCLOSE_TIMEOUT_MS, rc); + if (!rc) + DRM_INFO("wait for crtc mask 0x%x failed, commit anyway...\n", + priv->pending_crtcs); + if (priv->fbdev) { rc = drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev); if (rc) @@ -1032,6 +1056,13 @@ static void msm_lastclose(struct drm_device *dev) DRM_ERROR("client modeset commit failed: %d\n", rc); } + /* wait again, before kms driver does it's lastclose commit */ + msm_wait_event_timeout(priv->pending_crtcs_event, !priv->pending_crtcs, + LASTCLOSE_TIMEOUT_MS, rc); + if (!rc) + DRM_INFO("wait for crtc mask 0x%x failed, commit anyway...\n", + priv->pending_crtcs); + if (kms->funcs && kms->funcs->lastclose) kms->funcs->lastclose(kms); }