disp: msm: sde: add spinlocks to handle_frame_done call
By adding spin locks around the handle frame done, a race condition, between the wait for idle of one frame, and the pp done of the next frame, is mitigated. Change-Id: I78650fc9688b22db6d314b9bed023e0ddad20dbf Signed-off-by: Nilaan Gunabalachandran <ngunabal@codeaurora.org>
This commit is contained in:
@@ -186,8 +186,10 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
|
|||||||
atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0)) {
|
atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0)) {
|
||||||
event = SDE_ENCODER_FRAME_EVENT_DONE |
|
event = SDE_ENCODER_FRAME_EVENT_DONE |
|
||||||
SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
|
SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
|
||||||
|
spin_lock(phys_enc->enc_spinlock);
|
||||||
phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
|
phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
|
||||||
phys_enc, event);
|
phys_enc, event);
|
||||||
|
spin_unlock(phys_enc->enc_spinlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDE_EVT32_IRQ(DRMID(phys_enc->parent),
|
SDE_EVT32_IRQ(DRMID(phys_enc->parent),
|
||||||
@@ -285,9 +287,12 @@ static void sde_encoder_phys_cmd_wr_ptr_irq(void *arg, int irq_idx)
|
|||||||
|
|
||||||
if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0)) {
|
if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0)) {
|
||||||
event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
|
event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
|
||||||
if (phys_enc->parent_ops.handle_frame_done)
|
if (phys_enc->parent_ops.handle_frame_done) {
|
||||||
|
spin_lock(phys_enc->enc_spinlock);
|
||||||
phys_enc->parent_ops.handle_frame_done(
|
phys_enc->parent_ops.handle_frame_done(
|
||||||
phys_enc->parent, phys_enc, event);
|
phys_enc->parent, phys_enc, event);
|
||||||
|
spin_unlock(phys_enc->enc_spinlock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sde_encoder_helper_get_pp_line_count(phys_enc->parent, info);
|
sde_encoder_helper_get_pp_line_count(phys_enc->parent, info);
|
||||||
@@ -467,6 +472,7 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout(
|
|||||||
struct drm_connector *conn;
|
struct drm_connector *conn;
|
||||||
int event;
|
int event;
|
||||||
u32 pending_kickoff_cnt;
|
u32 pending_kickoff_cnt;
|
||||||
|
unsigned long lock_flags;
|
||||||
|
|
||||||
if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_ctl)
|
if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_ctl)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -523,9 +529,12 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout(
|
|||||||
phys_enc->enable_state = SDE_ENC_ERR_NEEDS_HW_RESET;
|
phys_enc->enable_state = SDE_ENC_ERR_NEEDS_HW_RESET;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (phys_enc->parent_ops.handle_frame_done)
|
if (phys_enc->parent_ops.handle_frame_done) {
|
||||||
|
spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
|
||||||
phys_enc->parent_ops.handle_frame_done(
|
phys_enc->parent_ops.handle_frame_done(
|
||||||
phys_enc->parent, phys_enc, frame_event);
|
phys_enc->parent, phys_enc, frame_event);
|
||||||
|
spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
|
||||||
|
}
|
||||||
|
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
@@ -664,6 +673,7 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
|
|||||||
int ret;
|
int ret;
|
||||||
struct sde_hw_ctl *ctl;
|
struct sde_hw_ctl *ctl;
|
||||||
bool wr_ptr_wait_success = true;
|
bool wr_ptr_wait_success = true;
|
||||||
|
unsigned long lock_flags;
|
||||||
|
|
||||||
if (!phys_enc) {
|
if (!phys_enc) {
|
||||||
SDE_ERROR("invalid encoder\n");
|
SDE_ERROR("invalid encoder\n");
|
||||||
@@ -682,10 +692,12 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
|
|||||||
atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0) &&
|
atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0) &&
|
||||||
phys_enc->parent_ops.handle_frame_done) {
|
phys_enc->parent_ops.handle_frame_done) {
|
||||||
|
|
||||||
|
spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
|
||||||
phys_enc->parent_ops.handle_frame_done(
|
phys_enc->parent_ops.handle_frame_done(
|
||||||
phys_enc->parent, phys_enc,
|
phys_enc->parent, phys_enc,
|
||||||
SDE_ENCODER_FRAME_EVENT_DONE |
|
SDE_ENCODER_FRAME_EVENT_DONE |
|
||||||
SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE);
|
SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE);
|
||||||
|
spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1466,6 +1478,7 @@ static int _sde_encoder_phys_cmd_handle_wr_ptr_timeout(
|
|||||||
to_sde_encoder_phys_cmd(phys_enc);
|
to_sde_encoder_phys_cmd(phys_enc);
|
||||||
bool switch_te;
|
bool switch_te;
|
||||||
int ret = -ETIMEDOUT;
|
int ret = -ETIMEDOUT;
|
||||||
|
unsigned long lock_flags;
|
||||||
|
|
||||||
switch_te = _sde_encoder_phys_cmd_needs_vsync_change(
|
switch_te = _sde_encoder_phys_cmd_needs_vsync_change(
|
||||||
phys_enc, profile_timestamp);
|
phys_enc, profile_timestamp);
|
||||||
@@ -1495,10 +1508,15 @@ static int _sde_encoder_phys_cmd_handle_wr_ptr_timeout(
|
|||||||
SDE_EVT32(DRMID(phys_enc->parent), switch_te, SDE_EVTLOG_ERROR);
|
SDE_EVT32(DRMID(phys_enc->parent), switch_te, SDE_EVTLOG_ERROR);
|
||||||
|
|
||||||
if (sde_encoder_phys_cmd_is_master(phys_enc) &&
|
if (sde_encoder_phys_cmd_is_master(phys_enc) &&
|
||||||
atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0))
|
atomic_add_unless(
|
||||||
|
&phys_enc->pending_retire_fence_cnt, -1, 0)) {
|
||||||
|
spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
|
||||||
phys_enc->parent_ops.handle_frame_done(
|
phys_enc->parent_ops.handle_frame_done(
|
||||||
phys_enc->parent, phys_enc,
|
phys_enc->parent, phys_enc,
|
||||||
SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE);
|
SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE);
|
||||||
|
spin_unlock_irqrestore(phys_enc->enc_spinlock,
|
||||||
|
lock_flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_enc->wr_ptr_wait_success = (ret == 0) ? true : false;
|
cmd_enc->wr_ptr_wait_success = (ret == 0) ? true : false;
|
||||||
|
Reference in New Issue
Block a user