disp: msm: sde: add support for hwfence profiling

This change adds hwfence input and output fence profiling
registers and debugfs to enable them.
To enable input hw fences timestamps:
echo 0x1 > /d/dri/0/debug/hw_fence_status
To enable output hw fences timestamps:
echo 0x2 > /d/dri/0/debug/hw_fence_status
To enable both, input and output hw fences timestamps:
echo 0x3 > /d/dri/0/debug/hw_fence_status.

Change-Id: I269a38f3843a01ec8c0816890e50bb7d847a4ed9
Signed-off-by: Christina Oliveira <quic_coliveir@quicinc.com>
This commit is contained in:
Christina Oliveira
2022-05-18 09:38:40 -07:00
parent d2d060cf80
commit 21ca2acab9
11 changed files with 252 additions and 23 deletions

View File

@@ -3433,6 +3433,35 @@ static enum sde_wb sde_encoder_get_wb(struct sde_mdss_cfg *catalog,
return WB_MAX;
}
void sde_encoder_hw_fence_status(struct sde_kms *sde_kms,
struct drm_crtc *crtc, struct sde_hw_ctl *hw_ctl)
{
u64 start_timestamp, end_timestamp;
if (!sde_kms || !hw_ctl || !sde_kms->hw_mdp) {
SDE_ERROR("invalid inputs\n");
return;
}
if ((sde_kms->debugfs_hw_fence & SDE_INPUT_HW_FENCE_TIMESTAMP)
&& sde_kms->hw_mdp->ops.hw_fence_input_status) {
sde_kms->hw_mdp->ops.hw_fence_input_status(sde_kms->hw_mdp,
&start_timestamp, &end_timestamp);
trace_sde_hw_fence_status(crtc->base.id, "input",
start_timestamp, end_timestamp);
}
if ((sde_kms->debugfs_hw_fence & SDE_OUTPUT_HW_FENCE_TIMESTAMP)
&& hw_ctl->ops.hw_fence_output_status) {
hw_ctl->ops.hw_fence_output_status(hw_ctl,
&start_timestamp, &end_timestamp);
trace_sde_hw_fence_status(crtc->base.id, "output",
start_timestamp, end_timestamp);
}
}
void sde_encoder_perf_uidle_status(struct sde_kms *sde_kms,
struct drm_crtc *crtc)
{
@@ -3492,7 +3521,7 @@ static void sde_encoder_vblank_callback(struct drm_encoder *drm_enc,
unsigned long lock_flags;
ktime_t ts = 0;
if (!drm_enc || !phy_enc)
if (!drm_enc || !phy_enc || !phy_enc->sde_kms)
return;
SDE_ATRACE_BEGIN("encoder_vblank_callback");
@@ -3502,8 +3531,7 @@ static void sde_encoder_vblank_callback(struct drm_encoder *drm_enc,
* calculate accurate vsync timestamp when available
* set current time otherwise
*/
if (phy_enc->sde_kms && test_bit(SDE_FEATURE_HW_VSYNC_TS,
phy_enc->sde_kms->catalog->features))
if (test_bit(SDE_FEATURE_HW_VSYNC_TS, phy_enc->sde_kms->catalog->features))
ts = sde_encoder_calc_last_vsync_timestamp(drm_enc);
if (!ts)
ts = ktime_get();
@@ -3515,10 +3543,12 @@ static void sde_encoder_vblank_callback(struct drm_encoder *drm_enc,
sde_enc->crtc_vblank_cb(sde_enc->crtc_vblank_cb_data, ts);
spin_unlock_irqrestore(&sde_enc->enc_spinlock, lock_flags);
if (phy_enc->sde_kms &&
phy_enc->sde_kms->catalog->uidle_cfg.debugfs_perf)
if (phy_enc->sde_kms->catalog->uidle_cfg.debugfs_perf)
sde_encoder_perf_uidle_status(phy_enc->sde_kms, sde_enc->crtc);
if (phy_enc->sde_kms->debugfs_hw_fence)
sde_encoder_hw_fence_status(phy_enc->sde_kms, sde_enc->crtc, phy_enc->hw_ctl);
SDE_ATRACE_END("encoder_vblank_callback");
}
@@ -3706,7 +3736,8 @@ int sde_encoder_idle_request(struct drm_encoder *drm_enc)
* phys: Pointer to physical encoder structure
*
*/
static inline void _sde_encoder_update_retire_txq(struct sde_encoder_phys *phys)
static inline void _sde_encoder_update_retire_txq(struct sde_encoder_phys *phys,
struct sde_kms *sde_kms)
{
struct sde_connector *c_conn;
int line_count;
@@ -3720,7 +3751,8 @@ static inline void _sde_encoder_update_retire_txq(struct sde_encoder_phys *phys)
line_count = sde_connector_get_property(phys->connector->state,
CONNECTOR_PROP_EARLY_FENCE_LINE);
if (c_conn->hwfence_wb_retire_fences_enable)
sde_fence_update_hw_fences_txq(c_conn->retire_fence, false, line_count);
sde_fence_update_hw_fences_txq(c_conn->retire_fence, false, line_count,
sde_kms->debugfs_hw_fence);
}
/**
@@ -3933,16 +3965,23 @@ void sde_encoder_helper_hw_reset(struct sde_encoder_phys *phys_enc)
void sde_encoder_helper_update_out_fence_txq(struct sde_encoder_virt *sde_enc, bool is_vid)
{
struct sde_crtc *sde_crtc;
struct sde_kms *sde_kms = NULL;
if (!sde_enc || !sde_enc->crtc) {
SDE_ERROR("invalid encoder %d\n", !sde_enc);
return;
}
sde_kms = sde_encoder_get_kms(&sde_enc->base);
if (!sde_kms) {
SDE_ERROR("invalid kms\n");
return;
}
sde_crtc = to_sde_crtc(sde_enc->crtc);
SDE_EVT32(DRMID(sde_enc->crtc), is_vid);
sde_fence_update_hw_fences_txq(sde_crtc->output_fence, is_vid, 0);
sde_fence_update_hw_fences_txq(sde_crtc->output_fence, is_vid, 0, sde_kms ?
sde_kms->debugfs_hw_fence : 0);
}
/**
@@ -4594,6 +4633,7 @@ void sde_encoder_kickoff(struct drm_encoder *drm_enc, bool config_changed)
{
struct sde_encoder_virt *sde_enc;
struct sde_encoder_phys *phys;
struct sde_kms *sde_kms;
unsigned int i;
if (!drm_enc) {
@@ -4619,8 +4659,9 @@ void sde_encoder_kickoff(struct drm_encoder *drm_enc, bool config_changed)
}
/* update txq for any output retire hw-fence (wb-path) */
sde_kms = sde_encoder_get_kms(&sde_enc->base);
if (sde_enc->cur_master)
_sde_encoder_update_retire_txq(sde_enc->cur_master);
_sde_encoder_update_retire_txq(sde_enc->cur_master, sde_kms);
/* All phys encs are ready to go, trigger the kickoff */
_sde_encoder_kickoff_phys(sde_enc, config_changed);