drm/amd/display: Add Underflow Asserts to dc
authorThomas Lim <Thomas.Lim@amd.com>
Mon, 29 Apr 2019 20:05:42 +0000 (16:05 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Sat, 22 Jun 2019 14:34:14 +0000 (09:34 -0500)
[Why]
For debugging underflow issues it can be useful to have asserts when the
underflow initially occurs.

[How]
Read the underflow status registers after actions that have a high risk
of causing underflow and assert that no underflow occurred. If underflow
occurred, clear the bit.

Signed-off-by: Thomas Lim <Thomas.Lim@amd.com>
Reviewed-by: Eric Yang <eric.yang2@amd.com>
Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h

index 5ebfeee9d08ee9537d5d5db1da1cb8a4b4a80d44..e513028faefaa4fb03c2c40f57f0cd4fda6a1dfe 100644 (file)
@@ -346,6 +346,7 @@ struct dc_debug_options {
        int sr_exit_time_ns;
        int sr_enter_plus_exit_time_ns;
        int urgent_latency_ns;
+       uint32_t underflow_assert_delay_us;
        int percent_of_ideal_drambw;
        int dram_clock_change_latency_ns;
        bool optimized_watermark;
index d8c54f96c366a9046d1bebd7abfb645f782f08c9..e50a696fcb5deac0bd97acae0b257951565807c9 100644 (file)
@@ -421,6 +421,23 @@ void dcn10_log_hw_state(struct dc *dc,
        DTN_INFO_END();
 }
 
+bool dcn10_did_underflow_occur(struct dc *dc, struct pipe_ctx *pipe_ctx)
+{
+       struct hubp *hubp = pipe_ctx->plane_res.hubp;
+       struct timing_generator *tg = pipe_ctx->stream_res.tg;
+
+       if (tg->funcs->is_optc_underflow_occurred(tg)) {
+               tg->funcs->clear_optc_underflow(tg);
+               return true;
+       }
+
+       if (hubp->funcs->hubp_get_underflow_status(hubp)) {
+               hubp->funcs->hubp_clear_underflow(hubp);
+               return true;
+       }
+       return false;
+}
+
 static void enable_power_gating_plane(
        struct dce_hwseq *hws,
        bool enable)
@@ -2398,6 +2415,7 @@ static void dcn10_apply_ctx_for_surface(
 {
        int i;
        struct timing_generator *tg;
+       uint32_t underflow_check_delay_us;
        bool removed_pipe[4] = { false };
        bool interdependent_update = false;
        struct pipe_ctx *top_pipe_to_program =
@@ -2412,11 +2430,22 @@ static void dcn10_apply_ctx_for_surface(
        interdependent_update = top_pipe_to_program->plane_state &&
                top_pipe_to_program->plane_state->update_flags.bits.full_update;
 
+       underflow_check_delay_us = dc->debug.underflow_assert_delay_us;
+
+       if (underflow_check_delay_us != 0xFFFFFFFF && dc->hwss.did_underflow_occur)
+               ASSERT(dc->hwss.did_underflow_occur(dc, top_pipe_to_program));
+
        if (interdependent_update)
                lock_all_pipes(dc, context, true);
        else
                dcn10_pipe_control_lock(dc, top_pipe_to_program, true);
 
+       if (underflow_check_delay_us != 0xFFFFFFFF)
+               udelay(underflow_check_delay_us);
+
+       if (underflow_check_delay_us != 0xFFFFFFFF && dc->hwss.did_underflow_occur)
+               ASSERT(dc->hwss.did_underflow_occur(dc, top_pipe_to_program));
+
        if (num_planes == 0) {
                /* OTG blank before remove all front end */
                dc->hwss.blank_pixel_data(dc, top_pipe_to_program, true);
@@ -3093,7 +3122,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
        .disable_stream_gating = NULL,
        .enable_stream_gating = NULL,
        .setup_periodic_interrupt = dcn10_setup_periodic_interrupt,
-       .setup_vupdate_interrupt = dcn10_setup_vupdate_interrupt
+       .setup_vupdate_interrupt = dcn10_setup_vupdate_interrupt,
+       .did_underflow_occur = dcn10_did_underflow_occur
 };
 
 
index ef94d6b15843fa9b228318091913df0e4a51740a..d3616b1948cc7be67e7ae0d5a39e4ae3a7a6ee71 100644 (file)
@@ -71,6 +71,8 @@ void dcn10_get_hdr_visual_confirm_color(
                struct pipe_ctx *pipe_ctx,
                struct tg_color *color);
 
+bool dcn10_did_underflow_occur(struct dc *dc, struct pipe_ctx *pipe_ctx);
+
 void update_dchubp_dpp(
        struct dc *dc,
        struct pipe_ctx *pipe_ctx,
index f6004bc53dce9c95a34edde27b6dd2ef9d08a937..29fd3cb9422bef147d52abf58da5ae865c2fc590 100644 (file)
@@ -560,6 +560,7 @@ static const struct dc_debug_options debug_defaults_drv = {
                .az_endpoint_mute_only = true,
                .recovery_enabled = false, /*enable this by default after testing.*/
                .max_downscale_src_width = 3840,
+               .underflow_assert_delay_us = 0xFFFFFFFF,
 };
 
 static const struct dc_debug_options debug_defaults_diags = {
@@ -569,7 +570,8 @@ static const struct dc_debug_options debug_defaults_diags = {
                .clock_trace = true,
                .disable_stutter = true,
                .disable_pplib_clock_request = true,
-               .disable_pplib_wm_range = true
+               .disable_pplib_wm_range = true,
+               .underflow_assert_delay_us = 0xFFFFFFFF,
 };
 
 static void dcn10_dpp_destroy(struct dpp **dpp)
index 20bc3b9fe879aae8291e15ec436720e2a9f63117..4b0d8b9f61da303a26a5ae101c142bea41121804 100644 (file)
@@ -2003,4 +2003,5 @@ void dcn20_hw_sequencer_construct(struct dc *dc)
        dc->hwss.reset_hw_ctx_wrap = dcn20_reset_hw_ctx_wrap;
        dc->hwss.update_mpcc = dcn20_update_mpcc;
        dc->hwss.set_flip_control_gsl = dcn20_set_flip_control_gsl;
+       dc->hwss.did_underflow_occur = dcn10_did_underflow_occur;
 }
index 4cc66c2ccb1dd2816c5797bd03db7c7134e6740c..6d9fd93ece8574c8cd1c50ba0f322d4a11b1f79d 100644 (file)
@@ -710,6 +710,7 @@ static const struct dc_debug_options debug_defaults_drv = {
                .scl_reset_length10 = true,
                .sanity_checks = false,
                .disable_tri_buf = true,
+               .underflow_assert_delay_us = 0xFFFFFFFF,
 };
 
 static const struct dc_debug_options debug_defaults_diags = {
@@ -724,6 +725,7 @@ static const struct dc_debug_options debug_defaults_diags = {
                .disable_pplib_wm_range = true,
                .disable_stutter = true,
                .scl_reset_length10 = true,
+               .underflow_assert_delay_us = 0xFFFFFFFF,
 };
 
 void dcn20_dpp_destroy(struct dpp **dpp)
index 4ffe42c27c3efc29e9e615eb59dd0419c749e857..4d56d48a317936c567d4ebf95b4ed8c2006b8c9e 100644 (file)
@@ -277,6 +277,7 @@ struct hw_sequencer_funcs {
 
        void (*setup_periodic_interrupt)(struct pipe_ctx *pipe_ctx, enum vline_select vline);
        void (*setup_vupdate_interrupt)(struct pipe_ctx *pipe_ctx);
+       bool (*did_underflow_occur)(struct dc *dc, struct pipe_ctx *pipe_ctx);
 
 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
        void (*update_odm)(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx);