disp: msm: sde: fix race between disable commit and vblank work
This patch addresses the following sequence: 1. DRM framework drops vblank reference, work is queued on event thread 2. Lastclose stages disable commit, swap-state occurs on display thread 3. vblank worker runs on event thread encoder cannot drop the FW vblank reference since it's no longer in crtc->encoder_mask Instead, iterate through all encoders and match the enc->crtc back-pointer to be sure the vblank vote is applied. Also, flush the event thread in all cases during the CRTC disable to be sure the vblank work is complete before the back-pointer is removed. Change-Id: Ib307e9aefc2d4f729a3af7a6140bc887684f4489 Signed-off-by: Steve Cohen <cohens@codeaurora.org>
Esse commit está contido em:
@@ -3850,8 +3850,10 @@ static int _sde_crtc_vblank_enable_no_lock(
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
drm_for_each_encoder_mask(enc, crtc->dev,
|
||||
crtc->state->encoder_mask) {
|
||||
drm_for_each_encoder(enc, crtc->dev) {
|
||||
if (enc->crtc != crtc)
|
||||
continue;
|
||||
|
||||
SDE_EVT32(DRMID(&sde_crtc->base), DRMID(enc), enable,
|
||||
sde_crtc->enabled);
|
||||
|
||||
@@ -3859,8 +3861,10 @@ static int _sde_crtc_vblank_enable_no_lock(
|
||||
sde_crtc_vblank_cb, (void *)crtc);
|
||||
}
|
||||
} else {
|
||||
drm_for_each_encoder_mask(enc, crtc->dev,
|
||||
crtc->state->encoder_mask) {
|
||||
drm_for_each_encoder(enc, crtc->dev) {
|
||||
if (enc->crtc != crtc)
|
||||
continue;
|
||||
|
||||
SDE_EVT32(DRMID(&sde_crtc->base), DRMID(enc), enable,
|
||||
sde_crtc->enabled);
|
||||
|
||||
@@ -4159,11 +4163,9 @@ static void sde_crtc_disable(struct drm_crtc *crtc)
|
||||
msm_mode_object_event_notify(&crtc->base, crtc->dev, &event,
|
||||
(u8 *)&power_on);
|
||||
|
||||
if (atomic_read(&sde_crtc->frame_pending)) {
|
||||
mutex_unlock(&sde_crtc->crtc_lock);
|
||||
_sde_crtc_flush_event_thread(crtc);
|
||||
mutex_lock(&sde_crtc->crtc_lock);
|
||||
}
|
||||
mutex_unlock(&sde_crtc->crtc_lock);
|
||||
_sde_crtc_flush_event_thread(crtc);
|
||||
mutex_lock(&sde_crtc->crtc_lock);
|
||||
|
||||
kthread_cancel_delayed_work_sync(&sde_crtc->static_cache_read_work);
|
||||
kthread_cancel_delayed_work_sync(&sde_crtc->idle_notify_work);
|
||||
|
Referência em uma nova issue
Block a user