From 581199cba241d3118ff5cd45bd3896ed33481888 Mon Sep 17 00:00:00 2001 From: Jayaprakash Madisetty Date: Thu, 20 Jan 2022 11:58:11 +0530 Subject: [PATCH] disp: msm: send power_on event in dual display composer kill scenario On composer kill event, drm lastclose occurs during which suspend commit gets triggered on primary. If secondary display is stuck in continuous splash, then we do a early return without triggering this suspend commit. On composer start, userspace waits for power on event, but the drm_driver has never entered suspend state, so power on event is never sent to userspace. This causes HWC deadlock side effect and the current change triggers null_commit on secondary display and then issues a suspend commit on both the displays to avoid this deadlock issue. Change-Id: I126f43ba3dd2c3bfa83346e8fd4678f35527893d Signed-off-by: Jayaprakash Madisetty --- msm/msm_drv.c | 24 +++++++++++++++++++++--- msm/msm_kms.h | 2 ++ msm/sde/sde_kms.c | 36 +++++++++++++++++++++++++++++++++++- 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/msm/msm_drv.c b/msm/msm_drv.c index 5eb8363e2198..a522ca30d78b 100644 --- a/msm/msm_drv.c +++ b/msm/msm_drv.c @@ -1042,8 +1042,19 @@ static void msm_lastclose(struct drm_device *dev) * commit then ignore the last close call */ if (kms->funcs && kms->funcs->check_for_splash - && kms->funcs->check_for_splash(kms, NULL)) - return; + && kms->funcs->check_for_splash(kms, NULL)) { + 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); + + rc = kms->funcs->trigger_null_flush(kms); + if (rc) { + DRM_ERROR("null flush commit failure during lastclose\n"); + return; + } + } /* * clean up vblank disable immediately as this is the last close. @@ -1543,8 +1554,15 @@ static int msm_release(struct inode *inode, struct file *filp) * refcount > 1. This operation is not triggered from upstream * drm as msm_driver does not support DRIVER_LEGACY feature. */ - if (drm_is_current_master(file_priv)) + if (drm_is_current_master(file_priv)) { + msm_wait_event_timeout(priv->pending_crtcs_event, !priv->pending_crtcs, + LASTCLOSE_TIMEOUT_MS, ret); + if (!ret) + DRM_INFO("wait for crtc mask 0x%x failed, commit anyway...\n", + priv->pending_crtcs); + msm_preclose(dev, file_priv); + } ret = drm_release(inode, filp); filp->private_data = NULL; diff --git a/msm/msm_kms.h b/msm/msm_kms.h index 058f97cdf53a..7c929e1df6f8 100644 --- a/msm/msm_kms.h +++ b/msm/msm_kms.h @@ -126,6 +126,8 @@ struct msm_kms_funcs { struct drm_atomic_state *state); /* check for continuous splash status */ bool (*check_for_splash)(struct msm_kms *kms, struct drm_crtc *crtc); + /*trigger null flush if stuck in cont splash*/ + int (*trigger_null_flush)(struct msm_kms *kms); /* topology lm information */ int (*get_mixer_count)(const struct msm_kms *kms, const struct drm_display_mode *mode, diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 9f7a815c9227..4c5705ce81b3 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -2462,6 +2462,7 @@ static int sde_kms_set_crtc_for_conn(struct drm_device *dev, } crtc_state->active = true; + crtc_state->enable = true; ret = drm_atomic_set_crtc_for_connector(conn_state, enc->crtc); if (ret) SDE_ERROR("error %d setting the crtc\n", ret); @@ -3644,7 +3645,7 @@ static int sde_kms_get_dsc_count(const struct msm_kms *kms, return 0; } -static void _sde_kms_null_commit(struct drm_device *dev, +static int _sde_kms_null_commit(struct drm_device *dev, struct drm_encoder *enc) { struct drm_modeset_acquire_ctx ctx; @@ -3687,6 +3688,8 @@ end: drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); + + return ret; } @@ -3715,6 +3718,36 @@ void sde_kms_display_early_wakeup(struct drm_device *dev, drm_connector_list_iter_end(&conn_iter); } +static int sde_kms_trigger_null_flush(struct msm_kms *kms) +{ + struct sde_kms *sde_kms; + struct sde_splash_display *splash_display; + int i, rc = 0; + + if (!kms) { + SDE_ERROR("invalid kms\n"); + return -EINVAL; + } + + sde_kms = to_sde_kms(kms); + + if (!sde_kms->splash_data.num_splash_displays || + sde_kms->dsi_display_count == sde_kms->splash_data.num_splash_displays) + return rc; + + for (i = 0; i < MAX_DSI_DISPLAYS; i++) { + splash_display = &sde_kms->splash_data.splash_display[i]; + + if (splash_display->cont_splash_enabled && splash_display->encoder) { + SDE_DEBUG("triggering null commit on enc:%d\n", + DRMID(splash_display->encoder)); + SDE_EVT32(DRMID(splash_display->encoder), SDE_EVTLOG_FUNC_ENTRY); + rc = _sde_kms_null_commit(sde_kms->dev, splash_display->encoder); + } + } + + return rc; +} #ifdef CONFIG_DEEPSLEEP static int _sde_kms_pm_deepsleep_helper(struct sde_kms *sde_kms, bool enter) @@ -4070,6 +4103,7 @@ static const struct msm_kms_funcs kms_funcs = { .get_address_space_device = _sde_kms_get_address_space_device, .postopen = _sde_kms_post_open, .check_for_splash = sde_kms_check_for_splash, + .trigger_null_flush = sde_kms_trigger_null_flush, .get_mixer_count = sde_kms_get_mixer_count, .get_dsc_count = sde_kms_get_dsc_count, };