OSDN Git Service

drm/amd/display: Log DMCUB trace buffer events
authorLeo (Hanghong) Ma <hanghong.ma@amd.com>
Fri, 19 Feb 2021 21:22:58 +0000 (16:22 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 9 Apr 2021 20:40:43 +0000 (16:40 -0400)
[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 <daniel.wheeler@amd.com>
Signed-off-by: Leo (Hanghong) Ma <hanghong.ma@amd.com>
Reviewed-by: Harry Wentland <Harry.Wentland@amd.com>
Acked-by: Solomon Chiu <solomon.chiu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c

index 00edf78..66a5b6b 100644 (file)
@@ -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);
index 6209d22..3ec3369 100644 (file)
@@ -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;
index 09bdffb..103e299 100644 (file)
@@ -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;
 }
index a682b07..72d9a95 100644 (file)
@@ -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;
 
index 8696047..ac8bcd1 100644 (file)
@@ -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
index 6ee9dd8..1a5be27 100644 (file)
@@ -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 = {
index 4ec6f6a..914ce2c 100644 (file)
@@ -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 = {