disp: msm: sde: store in_clone_mode flag locally in wb_frame_done

The issue scenario is as follows:
 1. User space issues CWB commit N-1, frame got picked up and wr_ptr_irq
    is received.
 2. Next commit N CWB disable commit is programmed waits for N-1 wb_done
    irq.
 3. The kickoff count is decremented on wb_done_irq of commit N-1
    and wb wait_for_idle is exited.
 4. wb_frame_done irq thread execution stalled before populating fences
    and commit thread execution continues.
 5. wb_reset disables in_clone_mode flag, the stalled wb_done_irq thread
    resumes its execution and signals the release fences on primary
    CRTC.
 6. Commit N-1  frame_done irq is received and release fences is
    signaled again.
Userspace assumes Commit N also completed on receiving of second release
fence causing corruption in screen. This patch stores in_clone_mode
flag in wb_done_irq and only CWB retire fence is signaled.

Change-Id: I758e19178e4ba8722a01fca72d230f066831aec9
Signed-off-by: Mahadevan <quic_mahap@quicinc.com>
Signed-off-by: Akash Gajjar <quic_agajjar@quicinc.com>
This commit is contained in:
Mahadevan
2023-11-24 21:31:58 +05:30
committed by Akash Gajjar
szülő a4550cab5e
commit c831956e54

Fájl megtekintése

@@ -1865,9 +1865,10 @@ static void _sde_encoder_phys_wb_frame_done_helper(void *arg, bool frame_error)
struct sde_encoder_phys *phys_enc = &wb_enc->base; struct sde_encoder_phys *phys_enc = &wb_enc->base;
u32 event = frame_error ? SDE_ENCODER_FRAME_EVENT_ERROR : 0; u32 event = frame_error ? SDE_ENCODER_FRAME_EVENT_ERROR : 0;
u32 ubwc_error = 0; u32 ubwc_error = 0;
bool in_clone_mode = phys_enc->in_clone_mode;
/* don't notify upper layer for internal commit */ /* don't notify upper layer for internal commit */
if (phys_enc->enable_state == SDE_ENC_DISABLING && !phys_enc->in_clone_mode) if (phys_enc->enable_state == SDE_ENC_DISABLING && !in_clone_mode)
goto end; goto end;
if (phys_enc->parent_ops.handle_frame_done && if (phys_enc->parent_ops.handle_frame_done &&
@@ -1886,7 +1887,7 @@ static void _sde_encoder_phys_wb_frame_done_helper(void *arg, bool frame_error)
event |= SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; event |= SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
} }
if (phys_enc->in_clone_mode) if (in_clone_mode)
event |= SDE_ENCODER_FRAME_EVENT_CWB_DONE event |= SDE_ENCODER_FRAME_EVENT_CWB_DONE
| SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; | SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
else else
@@ -1895,7 +1896,7 @@ static void _sde_encoder_phys_wb_frame_done_helper(void *arg, bool frame_error)
phys_enc->parent_ops.handle_frame_done(phys_enc->parent, phys_enc, event); phys_enc->parent_ops.handle_frame_done(phys_enc->parent, phys_enc, event);
} }
if (!phys_enc->in_clone_mode && phys_enc->parent_ops.handle_vblank_virt) if (!in_clone_mode && phys_enc->parent_ops.handle_vblank_virt)
phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent, phys_enc); phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent, phys_enc);
end: end:
@@ -1904,7 +1905,7 @@ end:
wb_enc->hw_wb->ops.get_ubwc_error(wb_enc->hw_wb); wb_enc->hw_wb->ops.get_ubwc_error(wb_enc->hw_wb);
wb_enc->hw_wb->ops.clear_ubwc_error(wb_enc->hw_wb); wb_enc->hw_wb->ops.clear_ubwc_error(wb_enc->hw_wb);
} }
SDE_EVT32_IRQ(DRMID(phys_enc->parent), WBID(wb_enc), phys_enc->in_clone_mode, SDE_EVT32_IRQ(DRMID(phys_enc->parent), WBID(wb_enc), in_clone_mode,
phys_enc->enable_state, event, atomic_read(&phys_enc->pending_kickoff_cnt), phys_enc->enable_state, event, atomic_read(&phys_enc->pending_kickoff_cnt),
atomic_read(&phys_enc->pending_retire_fence_cnt), atomic_read(&phys_enc->pending_retire_fence_cnt),
ubwc_error, frame_error); ubwc_error, frame_error);