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 <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>
This commit is contained in:
Leo (Hanghong) Ma 2021-02-19 16:22:58 -05:00 committed by Alex Deucher
parent 234cc26f7d
commit a08f16cfe8
7 changed files with 160 additions and 4 deletions

View 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);

View 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;

View 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;
}

View 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;

View 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

View 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 = {

View 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 = {