drm/msm/sde: queue display failure work to event thread

There are possibilities of deadlock if esd trigger work is
queued to display thread. There is a corner case where
during bridge disable, display thread is waiting for esd
trigger work to complete to cancel esd thread, while esd
trigger work is blocked on display thread. To fix this
queue esd trigger work to event thread.

Below is the call stack of both threads:

ESD thread
----------
__switch_to+0xb8/0xec
kthread_flush_work+0xdc/0x150
sde_encoder_display_failure_notification+0xc0/0x1e8
_sde_connector_report_panel_dead.part.8+0x6c/0xd4
sde_connector_check_status_work+0x10c/0x1d4
process_one_work+0x168/0x468
worker_thread+0x140/0x460
kthread+0xf4/0x108
ret_from_fork+0x10/0x50
0xffffffffffffffff

Commit thread
-------------
__switch_to+0xb8/0xec
flush_work+0x44/0x68
__cancel_work_timer+0x138/0x1e0
cancel_delayed_work_sync+0x24/0x30
sde_connector_schedule_status_work.part.16+0xc0/0x114
_sde_connector_update_power_locked+0x1c4/0x224
_sde_connector_update_dirty_properties+0x80/0x100
sde_connector_helper_bridge_disable+0x24/0x100
dsi_bridge_disable+0x30/0x98
drm_bridge_disable+0x128/0x144
msm_atomic_helper_commit_modeset_disables+0x148/0x578
complete_commit+0x74/0x668
_msm_drm_commit_work_cb+0x4c/0x1c4
kthread_worker_fn+0xc0/0x1e4
kthread+0xf4/0x108
ret_from_fork+0x10/0x50
0xffffffffffffffff

Change-Id: Ifd95664113857fd5c06098a3a2f87f28c1975513
Signed-off-by: Jayant Shekhar <jshekhar@codeaurora.org>
This commit is contained in:
Jayant Shekhar 2018-06-04 12:15:23 +05:30 committed by Shashank Babu Chinta Venkata
parent a087e2b7b3
commit 0e138412af
2 changed files with 14 additions and 5 deletions

View File

@ -1782,6 +1782,14 @@ static void _sde_connector_report_panel_dead(struct sde_connector *conn)
if (!conn)
return;
/* Panel dead notification can come:
* 1) ESD thread
* 2) Commit thread (if TE stops coming)
* So such case, avoid failure notification twice.
*/
if (conn->panel_dead)
return;
conn->panel_dead = true;
event.type = DRM_EVENT_PANEL_DEAD;
event.length = sizeof(bool);

View File

@ -5251,7 +5251,7 @@ int sde_encoder_update_caps_for_cont_splash(struct drm_encoder *encoder)
int sde_encoder_display_failure_notification(struct drm_encoder *enc)
{
struct msm_drm_thread *disp_thread = NULL;
struct msm_drm_thread *event_thread = NULL;
struct msm_drm_private *priv = NULL;
struct sde_encoder_virt *sde_enc = NULL;
@ -5263,7 +5263,7 @@ int sde_encoder_display_failure_notification(struct drm_encoder *enc)
priv = enc->dev->dev_private;
sde_enc = to_sde_encoder_virt(enc);
if (!sde_enc->crtc || (sde_enc->crtc->index
>= ARRAY_SIZE(priv->disp_thread))) {
>= ARRAY_SIZE(priv->event_thread))) {
SDE_DEBUG_ENC(sde_enc,
"invalid cached CRTC: %d or crtc index: %d\n",
sde_enc->crtc == NULL,
@ -5273,11 +5273,12 @@ int sde_encoder_display_failure_notification(struct drm_encoder *enc)
SDE_EVT32_VERBOSE(DRMID(enc));
disp_thread = &priv->disp_thread[sde_enc->crtc->index];
event_thread = &priv->event_thread[sde_enc->crtc->index];
kthread_queue_work(&disp_thread->worker,
&sde_enc->esd_trigger_work);
kthread_queue_work(&event_thread->worker,
&sde_enc->esd_trigger_work);
kthread_flush_work(&sde_enc->esd_trigger_work);
/**
* panel may stop generating te signal (vsync) during esd failure. rsc
* hardware may hang without vsync. Avoid rsc hang by generating the