Skip to content

Commit 45284ff

Browse files
Paloma Arellanolumag
authored andcommitted
drm/msm/dpu: Add mutex lock in control vblank irq
Add a mutex lock to control vblank irq to synchronize vblank enable/disable operations happening from different threads to prevent race conditions while registering/unregistering the vblank irq callback. v4: -Removed vblank_ctl_lock from dpu_encoder_virt, so it is only a parameter of dpu_encoder_phys. -Switch from atomic refcnt to a simple int counter as mutex has now been added v3: Mistakenly did not change wording in last version. It is done now. v2: Slightly changed wording of commit message Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Patchwork: https://patchwork.freedesktop.org/patch/571854/ Link: https://lore.kernel.org/r/20231212231101.9240-2-quic_parellan@quicinc.com Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
1 parent 341fb24 commit 45284ff

File tree

4 files changed

+47
-23
lines changed

4 files changed

+47
-23
lines changed

drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2464,7 +2464,6 @@ void dpu_encoder_phys_init(struct dpu_encoder_phys *phys_enc,
24642464
phys_enc->enc_spinlock = p->enc_spinlock;
24652465
phys_enc->enable_state = DPU_ENC_DISABLED;
24662466

2467-
atomic_set(&phys_enc->vblank_refcount, 0);
24682467
atomic_set(&phys_enc->pending_kickoff_cnt, 0);
24692468
atomic_set(&phys_enc->pending_ctlstart_cnt, 0);
24702469

drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ enum dpu_intr_idx {
155155
* @hw_cdm: Hardware interface to the CDM registers
156156
* @dpu_kms: Pointer to the dpu_kms top level
157157
* @cached_mode: DRM mode cached at mode_set time, acted on in enable
158+
* @vblank_ctl_lock: Vblank ctl mutex lock to protect vblank_refcount
158159
* @enabled: Whether the encoder has enabled and running a mode
159160
* @split_role: Role to play in a split-panel configuration
160161
* @intf_mode: Interface mode
@@ -184,11 +185,12 @@ struct dpu_encoder_phys {
184185
struct dpu_hw_cdm *hw_cdm;
185186
struct dpu_kms *dpu_kms;
186187
struct drm_display_mode cached_mode;
188+
struct mutex vblank_ctl_lock;
187189
enum dpu_enc_split_role split_role;
188190
enum dpu_intf_mode intf_mode;
189191
spinlock_t *enc_spinlock;
190192
enum dpu_enc_enable_state enable_state;
191-
atomic_t vblank_refcount;
193+
int vblank_refcount;
192194
atomic_t vsync_cnt;
193195
atomic_t underrun_cnt;
194196
atomic_t pending_ctlstart_cnt;

drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,8 @@ static int dpu_encoder_phys_cmd_control_vblank_irq(
246246
return -EINVAL;
247247
}
248248

249-
refcount = atomic_read(&phys_enc->vblank_refcount);
249+
mutex_lock(&phys_enc->vblank_ctl_lock);
250+
refcount = phys_enc->vblank_refcount;
250251

251252
/* Slave encoders don't report vblank */
252253
if (!dpu_encoder_phys_cmd_is_master(phys_enc))
@@ -262,16 +263,24 @@ static int dpu_encoder_phys_cmd_control_vblank_irq(
262263
phys_enc->hw_pp->idx - PINGPONG_0,
263264
enable ? "true" : "false", refcount);
264265

265-
if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
266-
ret = dpu_core_irq_register_callback(phys_enc->dpu_kms,
267-
phys_enc->irq[INTR_IDX_RDPTR],
268-
dpu_encoder_phys_cmd_te_rd_ptr_irq,
269-
phys_enc);
270-
else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0)
271-
ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms,
272-
phys_enc->irq[INTR_IDX_RDPTR]);
266+
if (enable) {
267+
if (phys_enc->vblank_refcount == 0)
268+
ret = dpu_core_irq_register_callback(phys_enc->dpu_kms,
269+
phys_enc->irq[INTR_IDX_RDPTR],
270+
dpu_encoder_phys_cmd_te_rd_ptr_irq,
271+
phys_enc);
272+
if (!ret)
273+
phys_enc->vblank_refcount++;
274+
} else if (!enable) {
275+
if (phys_enc->vblank_refcount == 1)
276+
ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms,
277+
phys_enc->irq[INTR_IDX_RDPTR]);
278+
if (!ret)
279+
phys_enc->vblank_refcount--;
280+
}
273281

274282
end:
283+
mutex_unlock(&phys_enc->vblank_ctl_lock);
275284
if (ret) {
276285
DRM_ERROR("vblank irq err id:%u pp:%d ret:%d, enable %s/%d\n",
277286
DRMID(phys_enc->parent),
@@ -287,7 +296,7 @@ static void dpu_encoder_phys_cmd_irq_control(struct dpu_encoder_phys *phys_enc,
287296
{
288297
trace_dpu_enc_phys_cmd_irq_ctrl(DRMID(phys_enc->parent),
289298
phys_enc->hw_pp->idx - PINGPONG_0,
290-
enable, atomic_read(&phys_enc->vblank_refcount));
299+
enable, phys_enc->vblank_refcount);
291300

292301
if (enable) {
293302
dpu_core_irq_register_callback(phys_enc->dpu_kms,
@@ -728,6 +737,9 @@ struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(struct drm_device *dev,
728737

729738
dpu_encoder_phys_init(phys_enc, p);
730739

740+
mutex_init(&phys_enc->vblank_ctl_lock);
741+
phys_enc->vblank_refcount = 0;
742+
731743
dpu_encoder_phys_cmd_init_ops(&phys_enc->ops);
732744
phys_enc->intf_mode = INTF_MODE_CMD;
733745
cmd_enc->stream_sel = 0;

drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,8 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
366366
int ret = 0;
367367
int refcount;
368368

369-
refcount = atomic_read(&phys_enc->vblank_refcount);
369+
mutex_lock(&phys_enc->vblank_ctl_lock);
370+
refcount = phys_enc->vblank_refcount;
370371

371372
/* Slave encoders don't report vblank */
372373
if (!dpu_encoder_phys_vid_is_master(phys_enc))
@@ -379,18 +380,26 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
379380
}
380381

381382
DRM_DEBUG_VBL("id:%u enable=%d/%d\n", DRMID(phys_enc->parent), enable,
382-
atomic_read(&phys_enc->vblank_refcount));
383+
refcount);
383384

384-
if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
385-
ret = dpu_core_irq_register_callback(phys_enc->dpu_kms,
386-
phys_enc->irq[INTR_IDX_VSYNC],
387-
dpu_encoder_phys_vid_vblank_irq,
388-
phys_enc);
389-
else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0)
390-
ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms,
391-
phys_enc->irq[INTR_IDX_VSYNC]);
385+
if (enable) {
386+
if (phys_enc->vblank_refcount == 0)
387+
ret = dpu_core_irq_register_callback(phys_enc->dpu_kms,
388+
phys_enc->irq[INTR_IDX_VSYNC],
389+
dpu_encoder_phys_vid_vblank_irq,
390+
phys_enc);
391+
if (!ret)
392+
phys_enc->vblank_refcount++;
393+
} else if (!enable) {
394+
if (phys_enc->vblank_refcount == 1)
395+
ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms,
396+
phys_enc->irq[INTR_IDX_VSYNC]);
397+
if (!ret)
398+
phys_enc->vblank_refcount--;
399+
}
392400

393401
end:
402+
mutex_unlock(&phys_enc->vblank_ctl_lock);
394403
if (ret) {
395404
DRM_ERROR("failed: id:%u intf:%d ret:%d enable:%d refcnt:%d\n",
396405
DRMID(phys_enc->parent),
@@ -614,7 +623,7 @@ static void dpu_encoder_phys_vid_irq_control(struct dpu_encoder_phys *phys_enc,
614623
trace_dpu_enc_phys_vid_irq_ctrl(DRMID(phys_enc->parent),
615624
phys_enc->hw_intf->idx - INTF_0,
616625
enable,
617-
atomic_read(&phys_enc->vblank_refcount));
626+
phys_enc->vblank_refcount);
618627

619628
if (enable) {
620629
ret = dpu_encoder_phys_vid_control_vblank_irq(phys_enc, true);
@@ -707,6 +716,8 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(struct drm_device *dev,
707716
DPU_DEBUG_VIDENC(phys_enc, "\n");
708717

709718
dpu_encoder_phys_init(phys_enc, p);
719+
mutex_init(&phys_enc->vblank_ctl_lock);
720+
phys_enc->vblank_refcount = 0;
710721

711722
dpu_encoder_phys_vid_init_ops(&phys_enc->ops);
712723
phys_enc->intf_mode = INTF_MODE_VIDEO;

0 commit comments

Comments
 (0)