diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2018-07-25 17:04:08 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2018-07-25 17:04:07 -0700 |
| commit | 3fbf4c7216af0f002752d4f802a2fb1488eee129 (patch) | |
| tree | 84374ee14d351bd6525882532d01a830a1584b2e | |
| parent | 4e72dda7209a9ef1883778665ad55c080de5b704 (diff) | |
| parent | bf9dde89b8b843bfe27232307380c4a30b00bd28 (diff) | |
Merge "drm/sde: report MDP underrun error only if not stabilized"
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_encoder.c | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 77fdcd86c920..dde742014125 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -44,6 +44,13 @@ /* timeout in frames waiting for frame done */ #define SDE_ENCODER_FRAME_DONE_TIMEOUT 60 +/* timeout in msecs */ +#define SDE_ENCODER_UNDERRUN_TIMEOUT 200 +/* underrun count threshold value */ +#define SDE_ENCODER_UNDERRUN_CNT_MAX 10 +/* 3 vsync time period in msec, report underrun */ +#define SDE_ENCODER_UNDERRUN_DELTA 50 + #define MISR_BUFF_SIZE 256 /* @@ -155,6 +162,11 @@ static struct sde_csc_cfg sde_csc_10bit_convert[SDE_MAX_CSC] = { * @crtc_frame_event: callback event * @frame_done_timeout: frame done timeout in Hz * @frame_done_timer: watchdog timer for frame done event + * @last_underrun_ts: variable to hold the last occurred underrun + * timestamp + * @underrun_cnt_dwork: underrun counter for delayed work + * @dwork: delayed work for deferring the reporting + * of underrun error */ struct sde_encoder_virt { struct drm_encoder base; @@ -181,6 +193,9 @@ struct sde_encoder_virt { u32 crtc_frame_event; atomic_t frame_done_timeout; struct timer_list frame_done_timer; + atomic_t last_underrun_ts; + atomic_t underrun_cnt_dwork; + struct delayed_work dwork; }; #define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base) @@ -597,14 +612,28 @@ static void sde_encoder_vblank_callback(struct drm_encoder *drm_enc, static void sde_encoder_underrun_callback(struct drm_encoder *drm_enc, struct sde_encoder_phys *phy_enc) { + struct sde_encoder_virt *sde_enc = NULL; + if (!phy_enc) return; + sde_enc = to_sde_encoder_virt(drm_enc); + SDE_ATRACE_BEGIN("encoder_underrun_callback"); atomic_inc(&phy_enc->underrun_cnt); SDE_EVT32(DRMID(drm_enc), atomic_read(&phy_enc->underrun_cnt)); - sde_recovery_set_events(SDE_UNDERRUN); + /* schedule delayed work if it has not scheduled or executed earlier */ + if ((!atomic_read(&sde_enc->last_underrun_ts)) && + (!atomic_read(&sde_enc->underrun_cnt_dwork))) { + schedule_delayed_work(&sde_enc->dwork, + msecs_to_jiffies(SDE_ENCODER_UNDERRUN_TIMEOUT)); + } + + /* take snapshot of current underrun and increment the count */ + atomic_set(&sde_enc->last_underrun_ts, jiffies); + atomic_inc(&sde_enc->underrun_cnt_dwork); + trace_sde_encoder_underrun(DRMID(drm_enc), atomic_read(&phy_enc->underrun_cnt)); SDE_DBG_CTRL("stop_ftrace"); @@ -1391,6 +1420,37 @@ static void sde_encoder_frame_done_timeout(unsigned long data) SDE_ENCODER_FRAME_EVENT_ERROR); } +static void sde_encoder_underrun_work_func(struct work_struct *work) +{ + struct sde_encoder_virt *sde_enc = + container_of(work, struct sde_encoder_virt, dwork.work); + + unsigned long delta, time; + + if (!sde_enc) { + SDE_ERROR("invalid parameters\n"); + return; + } + + delta = jiffies - atomic_read(&sde_enc->last_underrun_ts); + time = jiffies_to_msecs(delta); + + /* + * report underrun error when it exceeds the threshold count + * and the occurrence of last underrun error is less than 3 + * vsync period. + */ + if (atomic_read(&sde_enc->underrun_cnt_dwork) > + SDE_ENCODER_UNDERRUN_CNT_MAX && + time < SDE_ENCODER_UNDERRUN_DELTA) { + sde_recovery_set_events(SDE_UNDERRUN); + } + + /* reset underrun last timestamp and counter */ + atomic_set(&sde_enc->last_underrun_ts, 0); + atomic_set(&sde_enc->underrun_cnt_dwork, 0); +} + struct drm_encoder *sde_encoder_init( struct drm_device *dev, struct msm_display_info *disp_info) @@ -1421,8 +1481,11 @@ struct drm_encoder *sde_encoder_init( drm_encoder_helper_add(drm_enc, &sde_encoder_helper_funcs); atomic_set(&sde_enc->frame_done_timeout, 0); + atomic_set(&sde_enc->last_underrun_ts, 0); + atomic_set(&sde_enc->underrun_cnt_dwork, 0); setup_timer(&sde_enc->frame_done_timer, sde_encoder_frame_done_timeout, (unsigned long) sde_enc); + INIT_DELAYED_WORK(&sde_enc->dwork, sde_encoder_underrun_work_func); _sde_encoder_init_debugfs(drm_enc, sde_enc, sde_kms); |
