From a08f16cfe8dc7402228840d9ef857d6253bba9ee Mon Sep 17 00:00:00 2001 From: "Leo (Hanghong) Ma" Date: Fri, 19 Feb 2021 16:22:58 -0500 Subject: [PATCH] drm/amd/display: Log DMCUB trace buffer events [Why] We want to log DMCUB trace buffer events as Linux kernel traces. [How] Register an IRQ handler for DMCUB outbox0 interrupt in amdgpu_dm, and log the messages in the DMCUB tracebuffer to a new DMCUB TRACE_EVENT as soon as we receive the outbox0 IRQ from DMCUB FW. Tested-by: Daniel Wheeler Signed-off-by: Leo (Hanghong) Ma Reviewed-by: Harry Wentland Acked-by: Solomon Chiu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 48 ++++++++++++++++++++++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 9 ++++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 12 +++++- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 20 +++++++++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h | 21 ++++++++++ .../amd/display/dc/irq/dcn21/irq_service_dcn21.c | 29 ++++++++++++- .../amd/display/dc/irq/dcn30/irq_service_dcn30.c | 25 ++++++++++- 7 files changed, 160 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 00edf78975b1..66a5b6b4e827 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -922,6 +922,32 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev) return 0; } +#define DMUB_TRACE_MAX_READ 64 +static void dm_dmub_trace_high_irq(void *interrupt_params) +{ + struct common_irq_params *irq_params = interrupt_params; + struct amdgpu_device *adev = irq_params->adev; + struct amdgpu_display_manager *dm = &adev->dm; + struct dmcub_trace_buf_entry entry = { 0 }; + uint32_t count = 0; + + do { + if (dc_dmub_srv_get_dmub_outbox0_msg(dm->dc, &entry)) { + trace_amdgpu_dmub_trace_high_irq(entry.trace_code, entry.tick_count, + entry.param0, entry.param1); + + DRM_DEBUG_DRIVER("trace_code:%u, tick_count:%u, param0:%u, param1:%u\n", + entry.trace_code, entry.tick_count, entry.param0, entry.param1); + } else + break; + + count++; + + } while (count <= DMUB_TRACE_MAX_READ); + + ASSERT(count <= DMUB_TRACE_MAX_READ); +} + #if defined(CONFIG_DRM_AMD_DC_DCN) static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_addr_space_config *pa_config) { @@ -3104,6 +3130,28 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev) } + if (dc->ctx->dmub_srv) { + i = DCN_1_0__SRCID__DMCUB_OUTBOX_HIGH_PRIORITY_READY_INT; + r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, i, &adev->dmub_trace_irq); + + if (r) { + DRM_ERROR("Failed to add dmub trace irq id!\n"); + return r; + } + + int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; + int_params.irq_source = + dc_interrupt_to_irq_source(dc, i, 0); + + c_irq_params = &adev->dm.dmub_trace_params[0]; + + c_irq_params->adev = adev; + c_irq_params->irq_src = int_params.irq_source; + + amdgpu_dm_irq_register_interrupt(adev, &int_params, + dm_dmub_trace_high_irq, c_irq_params); + } + /* HPD */ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, DCN_1_0__SRCID__DC_HPD1_INT, &adev->hpd_irq); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 6209d2293339..3ec33696a9bd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -339,6 +339,15 @@ struct amdgpu_display_manager { struct common_irq_params vupdate_params[DC_IRQ_SOURCE_VUPDATE6 - DC_IRQ_SOURCE_VUPDATE1 + 1]; + /** + * @dmub_trace_params: + * + * DMUB trace event IRQ parameters, passed to registered handlers when + * triggered. + */ + struct common_irq_params + dmub_trace_params[1]; + spinlock_t irq_handler_list_table_lock; struct backlight_device *backlight_dev; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 09bdffb3a09e..103e29905b57 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -700,6 +700,14 @@ void dm_helpers_free_gpu_mem( bool dm_helpers_dmub_outbox0_interrupt_control(struct dc_context *ctx, bool enable) { - // TODO - return true; + enum dc_irq_source irq_source; + bool ret; + + irq_source = DC_IRQ_SOURCE_DMCUB_OUTBOX0; + + ret = dc_interrupt_set(ctx->dc, irq_source, enable); + + DRM_DEBUG_DRIVER("Dmub trace irq %sabling: r=%d\n", + enable ? "en" : "dis", ret); + return ret; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index a682b070f12c..72d9a950b723 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -732,6 +732,18 @@ static int amdgpu_dm_set_vupdate_irq_state(struct amdgpu_device *adev, __func__); } +static int amdgpu_dm_set_dmub_trace_irq_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned int type, + enum amdgpu_interrupt_state state) +{ + enum dc_irq_source irq_source = DC_IRQ_SOURCE_DMCUB_OUTBOX0; + bool st = (state == AMDGPU_IRQ_STATE_ENABLE); + + dc_interrupt_set(adev->dm.dc, irq_source, st); + return 0; +} + static const struct amdgpu_irq_src_funcs dm_crtc_irq_funcs = { .set = amdgpu_dm_set_crtc_irq_state, .process = amdgpu_dm_irq_handler, @@ -747,6 +759,11 @@ static const struct amdgpu_irq_src_funcs dm_vupdate_irq_funcs = { .process = amdgpu_dm_irq_handler, }; +static const struct amdgpu_irq_src_funcs dm_dmub_trace_irq_funcs = { + .set = amdgpu_dm_set_dmub_trace_irq_state, + .process = amdgpu_dm_irq_handler, +}; + static const struct amdgpu_irq_src_funcs dm_pageflip_irq_funcs = { .set = amdgpu_dm_set_pflip_irq_state, .process = amdgpu_dm_irq_handler, @@ -769,6 +786,9 @@ void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev) adev->vupdate_irq.num_types = adev->mode_info.num_crtc; adev->vupdate_irq.funcs = &dm_vupdate_irq_funcs; + adev->dmub_trace_irq.num_types = 1; + adev->dmub_trace_irq.funcs = &dm_dmub_trace_irq_funcs; + adev->pageflip_irq.num_types = adev->mode_info.num_crtc; adev->pageflip_irq.funcs = &dm_pageflip_irq_funcs; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h index 86960476823c..ac8bcd171b57 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h @@ -597,6 +597,27 @@ TRACE_EVENT(amdgpu_dm_dce_clocks_state, ) ); +TRACE_EVENT(amdgpu_dmub_trace_high_irq, + TP_PROTO(uint32_t trace_code, uint32_t tick_count, uint32_t param0, + uint32_t param1), + TP_ARGS(trace_code, tick_count, param0, param1), + TP_STRUCT__entry( + __field(uint32_t, trace_code) + __field(uint32_t, tick_count) + __field(uint32_t, param0) + __field(uint32_t, param1) + ), + TP_fast_assign( + __entry->trace_code = trace_code; + __entry->tick_count = tick_count; + __entry->param0 = param0; + __entry->param1 = param1; + ), + TP_printk("trace_code=%u tick_count=%u param0=%u param1=%u", + __entry->trace_code, __entry->tick_count, + __entry->param0, __entry->param1) +); + #endif /* _AMDGPU_DM_TRACE_H_ */ #undef TRACE_INCLUDE_PATH diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c index 6ee9dd833b85..1a5be2792055 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c @@ -187,6 +187,10 @@ static const struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = { .ack = NULL }; +static const struct irq_source_info_funcs dmub_trace_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; static const struct irq_source_info_funcs vline0_irq_info_funcs = { .set = NULL, @@ -205,6 +209,9 @@ static const struct irq_source_info_funcs vline0_irq_info_funcs = { BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ mm ## block ## id ## _ ## reg_name +#define SRI_DMUB(reg_name)\ + BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name #define IRQ_REG_ENTRY(block, reg_num, reg1, mask1, reg2, mask2)\ .enable_reg = SRI(reg1, block, reg_num),\ @@ -220,7 +227,19 @@ static const struct irq_source_info_funcs vline0_irq_info_funcs = { .ack_value = \ block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK \ - +#define IRQ_REG_ENTRY_DMUB(reg1, mask1, reg2, mask2)\ + .enable_reg = SRI_DMUB(reg1),\ + .enable_mask = \ + reg1 ## __ ## mask1 ## _MASK,\ + .enable_value = {\ + reg1 ## __ ## mask1 ## _MASK,\ + ~reg1 ## __ ## mask1 ## _MASK \ + },\ + .ack_reg = SRI_DMUB(reg2),\ + .ack_mask = \ + reg2 ## __ ## mask2 ## _MASK,\ + .ack_value = \ + reg2 ## __ ## mask2 ## _MASK \ #define hpd_int_entry(reg_num)\ [DC_IRQ_SOURCE_HPD1 + reg_num] = {\ @@ -282,6 +301,13 @@ static const struct irq_source_info_funcs vline0_irq_info_funcs = { .funcs = &vline0_irq_info_funcs\ } +#define dmub_trace_int_entry()\ + [DC_IRQ_SOURCE_DMCUB_OUTBOX0] = {\ + IRQ_REG_ENTRY_DMUB(DMCUB_INTERRUPT_ENABLE, DMCUB_OUTBOX0_READY_INT_EN,\ + DMCUB_INTERRUPT_ACK, DMCUB_OUTBOX0_READY_INT_ACK),\ + .funcs = &dmub_trace_irq_info_funcs\ + } + #define dummy_irq_entry() \ {\ .funcs = &dummy_irq_info_funcs\ @@ -400,6 +426,7 @@ irq_source_info_dcn21[DAL_IRQ_SOURCES_NUMBER] = { vline0_int_entry(3), vline0_int_entry(4), vline0_int_entry(5), + dmub_trace_int_entry(), }; static const struct irq_service_funcs irq_service_funcs_dcn21 = { diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c b/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c index 4ec6f6ad8c48..914ce2ce1c2f 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c @@ -215,6 +215,9 @@ static const struct irq_source_info_funcs vline0_irq_info_funcs = { BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ mm ## block ## id ## _ ## reg_name +#define SRI_DMUB(reg_name)\ + BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name #define IRQ_REG_ENTRY(block, reg_num, reg1, mask1, reg2, mask2)\ .enable_reg = SRI(reg1, block, reg_num),\ @@ -230,7 +233,19 @@ static const struct irq_source_info_funcs vline0_irq_info_funcs = { .ack_value = \ block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK \ - +#define IRQ_REG_ENTRY_DMUB(reg1, mask1, reg2, mask2)\ + .enable_reg = SRI_DMUB(reg1),\ + .enable_mask = \ + reg1 ## __ ## mask1 ## _MASK,\ + .enable_value = {\ + reg1 ## __ ## mask1 ## _MASK,\ + ~reg1 ## __ ## mask1 ## _MASK \ + },\ + .ack_reg = SRI_DMUB(reg2),\ + .ack_mask = \ + reg2 ## __ ## mask2 ## _MASK,\ + .ack_value = \ + reg2 ## __ ## mask2 ## _MASK \ #define hpd_int_entry(reg_num)\ [DC_IRQ_SOURCE_HPD1 + reg_num] = {\ @@ -284,6 +299,13 @@ static const struct irq_source_info_funcs vline0_irq_info_funcs = { .funcs = &vline0_irq_info_funcs\ } +#define dmub_trace_int_entry()\ + [DC_IRQ_SOURCE_DMCUB_OUTBOX0] = {\ + IRQ_REG_ENTRY_DMUB(DMCUB_INTERRUPT_ENABLE, DMCUB_OUTBOX0_READY_INT_EN,\ + DMCUB_INTERRUPT_ACK, DMCUB_OUTBOX0_READY_INT_ACK),\ + .funcs = &dmub_trace_irq_info_funcs\ + } + #define dummy_irq_entry() \ {\ .funcs = &dummy_irq_info_funcs\ @@ -398,6 +420,7 @@ irq_source_info_dcn30[DAL_IRQ_SOURCES_NUMBER] = { vline0_int_entry(3), vline0_int_entry(4), vline0_int_entry(5), + dmub_trace_int_entry(), }; static const struct irq_service_funcs irq_service_funcs_dcn30 = { -- 2.11.0