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:
parent
234cc26f7d
commit
a08f16cfe8
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 = {
|
||||
|
|
Loading…
Reference in New Issue