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 <quic_jmadiset@quicinc.com>
Signed-off-by: Veera Sundaram Sankaran <quic_veeras@quicinc.com>
This commit is contained in:
Jayaprakash Madisetty
2022-01-20 11:58:11 +05:30
committed by Veera Sundaram Sankaran
부모 7a013221ae
커밋 b837aa4c77
3개의 변경된 파일58개의 추가작업 그리고 4개의 파일을 삭제

파일 보기

@@ -1130,8 +1130,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))
&& kms->funcs->check_for_splash(kms)) {
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.
@@ -1574,8 +1585,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;

파일 보기

@@ -131,6 +131,8 @@ struct msm_kms_funcs {
struct drm_atomic_state *state);
/* check for continuous splash status */
bool (*check_for_splash)(struct msm_kms *kms);
/*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,

파일 보기

@@ -2542,6 +2542,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);
@@ -3800,7 +3801,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;
@@ -3843,6 +3844,8 @@ end:
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
return ret;
}
@@ -3871,6 +3874,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;
}
static void _sde_kms_pm_suspend_idle_helper(struct sde_kms *sde_kms,
struct device *dev)
@@ -4180,6 +4213,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,
};