[PATCH 05/14] drm/amd/display: Log DMCUB trace buffer events
Solomon Chiu
solomon.chiu at amd.com
Sat Mar 20 01:46:47 UTC 2021
From: "Leo (Hanghong) Ma" <hanghong.ma at amd.com>
[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.
Signed-off-by: Leo (Hanghong) Ma <hanghong.ma at amd.com>
Reviewed-by: Harry Wentland <Harry.Wentland at amd.com>
Acked-by: Solomon Chiu <solomon.chiu at amd.com>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 48 +++++++++++++++++++
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 9 ++++
.../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 12 ++++-
.../drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 20 ++++++++
.../amd/display/amdgpu_dm/amdgpu_dm_trace.h | 21 ++++++++
.../display/dc/irq/dcn21/irq_service_dcn21.c | 32 ++++++++++++-
.../display/dc/irq/dcn30/irq_service_dcn30.c | 32 ++++++++++++-
7 files changed, 170 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 8b464debc1ef..36100eeefb3b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -908,6 +908,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)
{
@@ -3078,6 +3104,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 f7f0680c1fa1..9d12f304b2ee 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 d3c687d07ee6..ffd18cd90947 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
@@ -731,6 +731,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,
@@ -746,6 +758,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,
@@ -768,6 +785,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 0e0f494fbb5e..e9db4f56a39f 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
@@ -58,6 +58,8 @@ enum dc_irq_source to_dal_irq_source_dcn21(
return DC_IRQ_SOURCE_VBLANK5;
case DCN_1_0__SRCID__DC_D6_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK6;
+ case DCN_1_0__SRCID__DMCUB_OUTBOX_HIGH_PRIORITY_READY_INT:
+ return DC_IRQ_SOURCE_DMCUB_OUTBOX0;
case DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT:
return DC_IRQ_SOURCE_PFLIP1;
case DCN_1_0__SRCID__HUBP1_FLIP_INTERRUPT:
@@ -173,6 +175,11 @@ 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
+};
+
#undef BASE_INNER
#define BASE_INNER(seg) DMU_BASE__INST0_SEG ## seg
@@ -185,6 +192,9 @@ static const struct irq_source_info_funcs vupdate_no_lock_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),\
@@ -200,7 +210,19 @@ static const struct irq_source_info_funcs vupdate_no_lock_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] = {\
@@ -254,6 +276,13 @@ static const struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = {
.funcs = &vblank_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\
@@ -366,6 +395,7 @@ irq_source_info_dcn21[DAL_IRQ_SOURCES_NUMBER] = {
vblank_int_entry(3),
vblank_int_entry(4),
vblank_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 a35b76772b9d..238f68cdd41b 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
@@ -65,6 +65,8 @@ enum dc_irq_source to_dal_irq_source_dcn30(
return DC_IRQ_SOURCE_VBLANK5;
case DCN_1_0__SRCID__DC_D6_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK6;
+ case DCN_1_0__SRCID__DMCUB_OUTBOX_HIGH_PRIORITY_READY_INT:
+ return DC_IRQ_SOURCE_DMCUB_OUTBOX0;
case DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT:
return DC_IRQ_SOURCE_PFLIP1;
case DCN_1_0__SRCID__HUBP1_FLIP_INTERRUPT:
@@ -179,6 +181,11 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = {
.ack = NULL
};
+static const struct irq_source_info_funcs dmub_trace_irq_info_funcs = {
+ .set = NULL,
+ .ack = NULL
+};
+
#undef BASE_INNER
#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
@@ -191,6 +198,9 @@ static const struct irq_source_info_funcs vblank_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),\
@@ -206,7 +216,19 @@ static const struct irq_source_info_funcs vblank_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] = {\
@@ -252,6 +274,13 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = {
.funcs = &vblank_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\
@@ -360,6 +389,7 @@ irq_source_info_dcn30[DAL_IRQ_SOURCES_NUMBER] = {
vblank_int_entry(3),
vblank_int_entry(4),
vblank_int_entry(5),
+ dmub_trace_int_entry(),
};
static const struct irq_service_funcs irq_service_funcs_dcn30 = {
--
2.29.0
More information about the amd-gfx
mailing list