diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index 580ab53007f5..8f07399cf402 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -3637,8 +3637,11 @@ int sde_crtc_reset_hw(struct drm_crtc *crtc, struct drm_crtc_state *old_state, } /* Early out if simple ctl reset succeeded */ - if (i == sde_crtc->num_ctls) + if (i == sde_crtc->num_ctls) { + sde_kms_update_recovery_mask(_sde_crtc_get_kms(crtc), + crtc, false); return 0; + } SDE_DEBUG("crtc%d: issuing hard reset\n", DRMID(crtc)); @@ -3696,6 +3699,8 @@ int sde_crtc_reset_hw(struct drm_crtc *crtc, struct drm_crtc_state *old_state, sde_encoder_kickoff(encoder, false, true); } + sde_kms_update_recovery_mask(_sde_crtc_get_kms(crtc), + crtc, false); /* panic the device if VBIF is not in good state */ return !recovery_events ? 0 : -EAGAIN; } @@ -3771,6 +3776,8 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, params.recovery_events_enabled)) is_error = true; sde_crtc->needs_hw_reset = false; + } else { + sde_kms_update_recovery_mask(sde_kms, crtc, false); } sde_crtc_calc_fps(sde_crtc); @@ -3791,9 +3798,10 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, sde_vbif_clear_errors(sde_kms); - if (is_error) { + if (is_error || sde_kms->recovery_mask) { _sde_crtc_remove_pipe_flush(crtc); _sde_crtc_blend_setup(crtc, old_state, false); + SDE_EVT32(sde_kms->recovery_mask); } list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 3e4a6e2c7f09..f3dfc261c374 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -1512,6 +1512,31 @@ static void sde_kms_complete_commit(struct msm_kms *kms, SDE_ATRACE_END("sde_kms_complete_commit"); } +void sde_kms_update_recovery_mask(struct sde_kms *sde_kms, + struct drm_crtc *crtc, bool flag) +{ + int i; + struct sde_hw_ctl *ctl; + struct sde_crtc *sde_crtc; + + if (!crtc || !sde_kms) { + SDE_ERROR("invalid params\n"); + return; + } + + sde_crtc = to_sde_crtc(crtc); + + for (i = 0; i < sde_crtc->num_ctls; ++i) { + ctl = sde_crtc->mixers[i].hw_ctl; + if (!ctl || !ctl->ops.reset) + continue; + if (flag) + sde_kms->recovery_mask |= BIT(ctl->idx - CTL_0); + else + sde_kms->recovery_mask &= ~BIT(ctl->idx - CTL_0); + } +} + static void sde_kms_wait_for_commit_done(struct msm_kms *kms, struct drm_crtc *crtc) { @@ -1561,6 +1586,8 @@ static void sde_kms_wait_for_commit_done(struct msm_kms *kms, ret = sde_encoder_wait_for_event(encoder, MSM_ENC_COMMIT_DONE); if (ret && ret != -EWOULDBLOCK) { SDE_ERROR("wait for commit done returned %d\n", ret); + sde_kms_update_recovery_mask(to_sde_kms(kms), + crtc, true); sde_crtc_request_frame_reset(crtc); break; } diff --git a/msm/sde/sde_kms.h b/msm/sde/sde_kms.h index 560b53ee1cca..b6332f9c54b9 100644 --- a/msm/sde/sde_kms.h +++ b/msm/sde/sde_kms.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -274,6 +274,7 @@ struct sde_kms { int irq_num; /* mdss irq number */ bool irq_enabled; + int recovery_mask; struct sde_core_perf perf; /* saved atomic state during system suspend */ @@ -754,4 +755,14 @@ int sde_kms_vm_trusted_prepare_commit(struct sde_kms *sde_kms, */ int sde_kms_vm_primary_prepare_commit(struct sde_kms *sde_kms, struct drm_atomic_state *state); + +/** + * sde_kms_update_recovery_mask - function to update recovery ctl mask + * during error cases + * @sde_kms: pointer to sde_kms + * @crtc: pointer to drm_crtc + * @flag: to determine whether to clear/set recovery mask + */ +void sde_kms_update_recovery_mask(struct sde_kms *sde_kms, + struct drm_crtc *crtc, bool flag); #endif /* __sde_kms_H__ */