disp: msm: sde: dma fence out of order handling in fence error case

Handle out of order dma fence signalling and propagation of fence
error. Out of order fence signaling is required only in Video mode.
For example, in case of N, N+1, N+2 frames where N, N+2 are good
frames and N+1 is frame with fence error. The release fence signal
sequence in video mode would be N+1, N, N+2.

Change-Id: I8b6f88cfeee945e28571b765f24ffea22fad23b8
Signed-off-by: GG Hou <quic_renjhou@quicinc.com>
This commit is contained in:
GG Hou
2023-04-17 14:11:48 +08:00
committed by Gerrit - the friendly Code Review server
父節點 725c7a0f3d
當前提交 a658fb17b7
共有 12 個文件被更改,包括 271 次插入8 次删除

查看文件

@@ -2021,6 +2021,24 @@ static void sde_encoder_misr_configure(struct drm_encoder *drm_enc,
sde_enc->misr_reconfigure = false;
}
void sde_encoder_clear_fence_error_in_progress(struct sde_encoder_phys *phys_enc)
{
struct sde_crtc *sde_crtc;
if (!phys_enc || !phys_enc->parent || !phys_enc->parent->crtc) {
SDE_DEBUG("invalid sde_encoder_phys.\n");
return;
}
sde_crtc = to_sde_crtc(phys_enc->parent->crtc);
if ((!phys_enc->sde_hw_fence_error_status) && (!sde_crtc->input_fence_status) &&
phys_enc->fence_error_handle_in_progress) {
phys_enc->fence_error_handle_in_progress = false;
SDE_EVT32(DRMID(phys_enc->parent), phys_enc->fence_error_handle_in_progress);
}
}
static int sde_encoder_hw_fence_signal(struct sde_encoder_phys *phys_enc)
{
struct sde_hw_ctl *hw_ctl;
@@ -2062,6 +2080,100 @@ static int sde_encoder_hw_fence_signal(struct sde_encoder_phys *phys_enc)
SDE_EVT32(DRMID(phys_enc->parent), SDE_EVTLOG_FUNC_CASE2);
}
SDE_EVT32(DRMID(phys_enc->parent), SDE_EVTLOG_FUNC_EXIT);
return rc;
}
int sde_encoder_handle_dma_fence_out_of_order(struct drm_encoder *drm_enc)
{
struct drm_crtc *crtc;
struct sde_crtc *sde_crtc;
struct sde_crtc_state *cstate;
struct sde_encoder_virt *sde_enc;
struct sde_encoder_phys *phys_enc;
struct sde_fence_context *ctx;
struct drm_connector *conn;
bool is_vid;
int i, fence_status = 0, pending_kickoff_cnt = 0, rc = 0;
ktime_t time_stamp;
crtc = drm_enc->crtc;
sde_crtc = to_sde_crtc(crtc);
cstate = to_sde_crtc_state(crtc->state);
sde_enc = to_sde_encoder_virt(drm_enc);
if (!sde_enc || !sde_enc->phys_encs[0]) {
SDE_ERROR("invalid params\n");
return -EINVAL;
}
phys_enc = sde_enc->phys_encs[0];
ctx = sde_crtc->output_fence;
time_stamp = ktime_get();
/* out of order sw fence error signal for video panel.
* Hold the last good frame for video mode panel.
*/
if (phys_enc->sde_hw_fence_error_value) {
fence_status = phys_enc->sde_hw_fence_error_value;
phys_enc->sde_hw_fence_error_value = 0;
} else {
fence_status = sde_crtc->input_fence_status;
}
is_vid = sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_VIDEO_MODE);
SDE_EVT32(is_vid, fence_status, phys_enc->fence_error_handle_in_progress);
if (is_vid) {
/* update last_good_frame_fence_seqno after at least one good frame */
if (!phys_enc->fence_error_handle_in_progress) {
ctx->sde_fence_error_ctx.last_good_frame_fence_seqno =
ctx->sde_fence_error_ctx.curr_frame_fence_seqno - 1;
phys_enc->fence_error_handle_in_progress = true;
}
/* signal release fence for vid panel */
sde_fence_error_ctx_update(ctx, fence_status, HANDLE_OUT_OF_ORDER);
} else {
/*
* out of order sw fence error signal for CMD panel.
* always wait frame done for cmd panel.
* signal the sw fence error release fence for CMD panel.
*/
pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt);
if (pending_kickoff_cnt) {
SDE_EVT32(DRMID(drm_enc), pending_kickoff_cnt, SDE_EVTLOG_FUNC_CASE1);
rc = sde_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE);
if (rc && rc != -EWOULDBLOCK) {
SDE_DEBUG("wait for frame done failed %d\n", rc);
SDE_EVT32(DRMID(drm_enc), rc, pending_kickoff_cnt,
SDE_EVTLOG_ERROR);
}
}
/* update fence error context for cmd panel */
sde_fence_error_ctx_update(ctx, fence_status, SET_ERROR_ONLY_CMD_RELEASE);
}
sde_fence_signal(ctx, time_stamp, SDE_FENCE_SIGNAL, NULL);
/**
* clear flag in sde_fence_error_ctx after fence signal,
* the last_good_frame_fence_seqno is supposed to be updated or cleared after
* at least one good frame in case of constant fence error
*/
sde_fence_error_ctx_update(ctx, 0, NO_ERROR);
/* signal retire fence */
for (i = 0; i < cstate->num_connectors; ++i) {
conn = cstate->connectors[i];
sde_connector_fence_error_ctx_signal(conn, fence_status, is_vid);
}
SDE_EVT32(ctx->sde_fence_error_ctx.fence_error_status,
ctx->sde_fence_error_ctx.fence_error_state,
ctx->sde_fence_error_ctx.last_good_frame_fence_seqno, pending_kickoff_cnt);
return rc;
}
@@ -2086,6 +2198,12 @@ int sde_encoder_hw_fence_error_handle(struct drm_encoder *drm_enc)
SDE_EVT32(DRMID(drm_enc), rc, SDE_EVTLOG_ERROR);
}
rc = sde_encoder_handle_dma_fence_out_of_order(phys_enc->parent);
if (rc) {
SDE_DEBUG("sde_encoder_handle_dma_fence_out_of_order failed, rc = %d\n", rc);
SDE_EVT32(DRMID(phys_enc->parent), rc, SDE_EVTLOG_ERROR);
}
phys_enc->sde_hw_fence_error_status = false;
SDE_EVT32(DRMID(drm_enc), SDE_EVTLOG_FUNC_EXIT);
return rc;