disp: msm: sde: prevent wb commit till cwb is disabled
There is race condition in below scenario leading to crash in sde_encoder_virt_enable as sde_enc->cur_master is set to NULL in sde_encoder_virt_reset in earlier CWB disable commit. 1) commit1-CWB retire fence signalled. 2) commit1-CWB disable commit still in progress. 3) commit2-New WB commit in progress. 4) commit1-sde_enc->cur_master is set to NULL in CWB disable commit. 5) commit2-Crash seen in sde_encoder_virt_enable in WB commit. Also, as WB HW is still attached to commit1 till the next wr_ptr, new WB session cannot be allowed. Adding validate check to fail WB session when CWB is still not cleared in CTL path. Change-Id: I62aca05f8380d3621d4980c0820cdd4da37b3dc1 Signed-off-by: Raviteja Tamatam <quic_travitej@quicinc.com>
This commit is contained in:
committed by
Andhavarapu Karthik
parent
1ad20d00ad
commit
32bd9ab86f
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2013 Red Hat
|
||||
* Author: Rob Clark <robdclark@gmail.com>
|
||||
@@ -3237,6 +3237,23 @@ void sde_encoder_virt_reset(struct drm_encoder *drm_enc)
|
||||
sde_rm_release(&sde_kms->rm, drm_enc, false);
|
||||
}
|
||||
|
||||
void sde_encoder_set_cwb_pending(struct drm_encoder *drm_enc, bool enable)
|
||||
{
|
||||
struct sde_encoder_virt *sde_enc;
|
||||
int i;
|
||||
|
||||
if (!drm_enc) {
|
||||
SDE_ERROR("invalid encoder\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sde_enc = to_sde_encoder_virt(drm_enc);
|
||||
for (i = 0; i < sde_enc->num_phys_encs; i++) {
|
||||
if (sde_enc->phys_encs[i])
|
||||
sde_enc->phys_encs[i]->cwb_disable_pending = enable;
|
||||
}
|
||||
}
|
||||
|
||||
static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
|
||||
{
|
||||
struct sde_encoder_virt *sde_enc = NULL;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2013 Red Hat
|
||||
* Author: Rob Clark <robdclark@gmail.com>
|
||||
@@ -653,6 +653,13 @@ ktime_t sde_encoder_calc_last_vsync_timestamp(struct drm_encoder *drm_enc);
|
||||
*/
|
||||
void sde_encoder_cancel_delayed_work(struct drm_encoder *encoder);
|
||||
|
||||
/**
|
||||
* sde_encoder_set_cwb_pending - set cwb_disable_pending flag
|
||||
* @drm_enc: Pointer to drm encoder structure
|
||||
* @enable: set or reset cwb_disable_pending
|
||||
*/
|
||||
void sde_encoder_set_cwb_pending(struct drm_encoder *drm_enc, bool enable);
|
||||
|
||||
/**
|
||||
* sde_encoder_get_kms - retrieve the kms from encoder
|
||||
* @drm_enc: Pointer to drm encoder structure
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
@@ -315,6 +315,8 @@ struct sde_encoder_irq {
|
||||
* mode display
|
||||
* @recovered: flag set to true when recovered from pp timeout
|
||||
* @autorefresh_disable_trans: flag set to true during autorefresh disable transition
|
||||
* @cwb_disable_pending: Set to true when cwb disable is in progress
|
||||
* and HW is still attached to CTL
|
||||
*/
|
||||
struct sde_encoder_phys {
|
||||
struct drm_encoder *parent;
|
||||
@@ -363,6 +365,7 @@ struct sde_encoder_phys {
|
||||
enum frame_trigger_mode_type frame_trigger_mode;
|
||||
bool recovered;
|
||||
bool autorefresh_disable_trans;
|
||||
bool cwb_disable_pending;
|
||||
};
|
||||
|
||||
static inline int sde_encoder_phys_inc_pending(struct sde_encoder_phys *phys)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
@@ -987,6 +987,7 @@ static int sde_encoder_phys_wb_atomic_check(struct sde_encoder_phys *phys_enc,
|
||||
const struct drm_display_mode *mode = &crtc_state->mode;
|
||||
int rc;
|
||||
bool clone_mode_curr = false;
|
||||
bool cwb_disable_pending = false;
|
||||
|
||||
SDE_DEBUG("[enc:%d wb:%d] atomic_check:\"%s\",%d,%d]\n", DRMID(phys_enc->parent),
|
||||
WBID(wb_enc), mode->name, mode->hdisplay, mode->vdisplay);
|
||||
@@ -1003,12 +1004,13 @@ static int sde_encoder_phys_wb_atomic_check(struct sde_encoder_phys *phys_enc,
|
||||
|
||||
sde_conn_state = to_sde_connector_state(conn_state);
|
||||
clone_mode_curr = phys_enc->in_clone_mode;
|
||||
cwb_disable_pending = phys_enc->cwb_disable_pending;
|
||||
|
||||
_sde_enc_phys_wb_detect_cwb(phys_enc, crtc_state);
|
||||
|
||||
if (clone_mode_curr && !cstate->cwb_enc_mask) {
|
||||
SDE_ERROR("[enc:%d wb:%d] WB commit before CWB disable\n",
|
||||
DRMID(phys_enc->parent), WBID(wb_enc));
|
||||
if ((clone_mode_curr || cwb_disable_pending) && !cstate->cwb_enc_mask) {
|
||||
SDE_ERROR("[enc:%d wb:%d] WB commit before CWB disable, Clone mode %d %d\n",
|
||||
DRMID(phys_enc->parent), WBID(wb_enc), clone_mode_curr, cwb_disable_pending);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2013 Red Hat
|
||||
* Author: Rob Clark <robdclark@gmail.com>
|
||||
@@ -1601,6 +1601,7 @@ static void sde_kms_wait_for_commit_done(struct msm_kms *kms,
|
||||
{
|
||||
struct sde_kms *sde_kms;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_encoder *cwb_encoder = NULL;
|
||||
struct drm_device *dev;
|
||||
int ret;
|
||||
bool cwb_disabling;
|
||||
@@ -1634,8 +1635,12 @@ static void sde_kms_wait_for_commit_done(struct msm_kms *kms,
|
||||
if (encoder->crtc != crtc) {
|
||||
cwb_disabling = sde_encoder_is_cwb_disabling(encoder,
|
||||
crtc);
|
||||
if (!cwb_disabling)
|
||||
if (cwb_disabling) {
|
||||
cwb_encoder = encoder;
|
||||
sde_encoder_set_cwb_pending(encoder, true);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1661,6 +1666,9 @@ static void sde_kms_wait_for_commit_done(struct msm_kms *kms,
|
||||
sde_encoder_virt_reset(encoder);
|
||||
}
|
||||
|
||||
if (cwb_encoder)
|
||||
sde_encoder_set_cwb_pending(cwb_encoder, false);
|
||||
|
||||
/* avoid system cache update to set rd-noalloc bit when NSE feature is enabled */
|
||||
if (!test_bit(SDE_FEATURE_SYS_CACHE_NSE, sde_kms->catalog->features))
|
||||
sde_crtc_static_cache_read_kickoff(crtc);
|
||||
|
||||
Reference in New Issue
Block a user