From: Ashley Thomas <Ashley.Thomas2@xxxxxxx> [WHY] Ability to triage DMCUB is improved with availability of certain dmub registers not currently captured in crash dump diagnostic data. [HOW] Add dmub registers to diagnostic data collection. Thanks Nicholas Kazlauskas for awesome input on this! Signed-off-by: Ashley Thomas <Ashley.Thomas2@xxxxxxx> Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@xxxxxxx> Acked-by: Anson Jacob <Anson.Jacob@xxxxxxx> --- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 100 +++++++++++++++++- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 4 + drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 29 +++++ .../gpu/drm/amd/display/dmub/src/dmub_dcn20.c | 65 +++++++++++- .../gpu/drm/amd/display/dmub/src/dmub_dcn20.h | 14 ++- .../gpu/drm/amd/display/dmub/src/dmub_dcn21.c | 5 +- .../gpu/drm/amd/display/dmub/src/dmub_dcn30.c | 5 +- .../drm/amd/display/dmub/src/dmub_dcn301.c | 5 +- .../drm/amd/display/dmub/src/dmub_dcn302.c | 5 +- .../drm/amd/display/dmub/src/dmub_dcn303.c | 5 +- .../gpu/drm/amd/display/dmub/src/dmub_srv.c | 10 ++ 11 files changed, 238 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 48ca23e1e599..36b6fbcc0441 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -86,6 +86,7 @@ void dc_dmub_srv_cmd_queue(struct dc_dmub_srv *dc_dmub_srv, error: DC_ERROR("Error queuing DMUB command: status=%d\n", status); + dc_dmub_srv_log_diagnostic_data(dc_dmub_srv); } void dc_dmub_srv_cmd_execute(struct dc_dmub_srv *dc_dmub_srv) @@ -95,8 +96,10 @@ void dc_dmub_srv_cmd_execute(struct dc_dmub_srv *dc_dmub_srv) enum dmub_status status; status = dmub_srv_cmd_execute(dmub); - if (status != DMUB_STATUS_OK) + if (status != DMUB_STATUS_OK) { DC_ERROR("Error starting DMUB execution: status=%d\n", status); + dc_dmub_srv_log_diagnostic_data(dc_dmub_srv); + } } void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv) @@ -106,8 +109,10 @@ void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv) enum dmub_status status; status = dmub_srv_wait_for_idle(dmub, 100000); - if (status != DMUB_STATUS_OK) + if (status != DMUB_STATUS_OK) { DC_ERROR("Error waiting for DMUB idle: status=%d\n", status); + dc_dmub_srv_log_diagnostic_data(dc_dmub_srv); + } } void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dmub_srv, @@ -214,3 +219,94 @@ void dc_dmub_trace_event_control(struct dc *dc, bool enable) { dm_helpers_dmub_outbox_interrupt_control(dc->ctx, enable); } + +bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmub_diagnostic_data *diag_data) +{ + if (!dc_dmub_srv || !dc_dmub_srv->dmub || !diag_data) + return false; + return dmub_srv_get_diagnostic_data(dc_dmub_srv->dmub, diag_data); +} + +void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv) +{ + struct dmub_diagnostic_data diag_data = {0}; + + if (!dc_dmub_srv || !dc_dmub_srv->dmub) { + DC_LOG_ERROR("%s: invalid parameters.", __func__); + return; + } + + if (!dc_dmub_srv_get_diagnostic_data(dc_dmub_srv, &diag_data)) { + DC_LOG_ERROR("%s: dc_dmub_srv_get_diagnostic_data failed.", __func__); + return; + } + + DC_LOG_DEBUG( + "DMCUB STATE\n" + " dmcub_version : %08x\n" + " scratch [0] : %08x\n" + " scratch [1] : %08x\n" + " scratch [2] : %08x\n" + " scratch [3] : %08x\n" + " scratch [4] : %08x\n" + " scratch [5] : %08x\n" + " scratch [6] : %08x\n" + " scratch [7] : %08x\n" + " scratch [8] : %08x\n" + " scratch [9] : %08x\n" + " scratch [10] : %08x\n" + " scratch [11] : %08x\n" + " scratch [12] : %08x\n" + " scratch [13] : %08x\n" + " scratch [14] : %08x\n" + " scratch [15] : %08x\n" + " pc : %08x\n" + " unk_fault_addr : %08x\n" + " inst_fault_addr : %08x\n" + " data_fault_addr : %08x\n" + " inbox1_rptr : %08x\n" + " inbox1_wptr : %08x\n" + " inbox1_size : %08x\n" + " inbox0_rptr : %08x\n" + " inbox0_wptr : %08x\n" + " inbox0_size : %08x\n" + " is_enabled : %d\n" + " is_soft_reset : %d\n" + " is_secure_reset : %d\n" + " is_traceport_en : %d\n" + " is_cw0_en : %d\n" + " is_cw6_en : %d\n", + diag_data.dmcub_version, + diag_data.scratch[0], + diag_data.scratch[1], + diag_data.scratch[2], + diag_data.scratch[3], + diag_data.scratch[4], + diag_data.scratch[5], + diag_data.scratch[6], + diag_data.scratch[7], + diag_data.scratch[8], + diag_data.scratch[9], + diag_data.scratch[10], + diag_data.scratch[11], + diag_data.scratch[12], + diag_data.scratch[13], + diag_data.scratch[14], + diag_data.scratch[15], + diag_data.pc, + diag_data.undefined_address_fault_addr, + diag_data.inst_fetch_fault_addr, + diag_data.data_write_fault_addr, + diag_data.inbox1_rptr, + diag_data.inbox1_wptr, + diag_data.inbox1_size, + diag_data.inbox0_rptr, + diag_data.inbox0_wptr, + diag_data.inbox0_size, + diag_data.is_dmcub_enabled, + diag_data.is_dmcub_soft_reset, + diag_data.is_dmcub_secure_reset, + diag_data.is_traceport_en, + diag_data.is_cw0_enabled, + diag_data.is_cw6_enabled); +} diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h index f5489c7aa770..0d5680198937 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h @@ -71,4 +71,8 @@ void dc_dmub_trace_event_control(struct dc *dc, bool enable); void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dmub_srv, union dmub_inbox0_data_register data); +bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmub_diagnostic_data *dmub_oca); + +void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv); + #endif /* _DMUB_DC_SRV_H_ */ diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h index 7634e8d94543..2bf5e7207744 100644 --- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h @@ -243,6 +243,31 @@ struct dmub_srv_hw_params { #endif }; +/** + * struct dmub_diagnostic_data - Diagnostic data retrieved from DMCUB for + * debugging purposes, including logging, crash analysis, etc. + */ +struct dmub_diagnostic_data { + uint32_t dmcub_version; + uint32_t scratch[16]; + uint32_t pc; + uint32_t undefined_address_fault_addr; + uint32_t inst_fetch_fault_addr; + uint32_t data_write_fault_addr; + uint32_t inbox1_rptr; + uint32_t inbox1_wptr; + uint32_t inbox1_size; + uint32_t inbox0_rptr; + uint32_t inbox0_wptr; + uint32_t inbox0_size; + uint8_t is_dmcub_enabled : 1; + uint8_t is_dmcub_soft_reset : 1; + uint8_t is_dmcub_secure_reset : 1; + uint8_t is_traceport_en : 1; + uint8_t is_cw0_enabled : 1; + uint8_t is_cw6_enabled : 1; +}; + /** * struct dmub_srv_base_funcs - Driver specific base callbacks */ @@ -335,6 +360,8 @@ struct dmub_srv_hw_funcs { void (*send_inbox0_cmd)(struct dmub_srv *dmub, union dmub_inbox0_data_register data); uint32_t (*get_current_time)(struct dmub_srv *dmub); + + void (*get_diagnostic_data)(struct dmub_srv *dmub, struct dmub_diagnostic_data *dmub_oca); }; /** @@ -685,6 +712,8 @@ enum dmub_status dmub_srv_cmd_with_reply_data(struct dmub_srv *dmub, bool dmub_srv_get_outbox0_msg(struct dmub_srv *dmub, struct dmcub_trace_buf_entry *entry); +bool dmub_srv_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data); + #if defined(__cplusplus) } #endif diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c index 8cdc1c75394e..a6540e27044d 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c @@ -40,7 +40,10 @@ const struct dmub_srv_common_regs dmub_srv_dcn20_regs = { #define DMUB_SR(reg) REG_OFFSET(reg), - { DMUB_COMMON_REGS() }, + { + DMUB_COMMON_REGS() + DMCUB_INTERNAL_REGS() + }, #undef DMUB_SR #define DMUB_SF(reg, field) FD_MASK(reg, field), @@ -404,3 +407,63 @@ uint32_t dmub_dcn20_get_current_time(struct dmub_srv *dmub) { return REG_READ(DMCUB_TIMER_CURRENT); } + +void dmub_dcn20_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data) +{ + uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset; + uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled; + + if (!dmub || !diag_data) + return; + + memset(diag_data, 0, sizeof(*diag_data)); + + diag_data->dmcub_version = dmub->fw_version; + + diag_data->scratch[0] = REG_READ(DMCUB_SCRATCH0); + diag_data->scratch[1] = REG_READ(DMCUB_SCRATCH1); + diag_data->scratch[2] = REG_READ(DMCUB_SCRATCH2); + diag_data->scratch[3] = REG_READ(DMCUB_SCRATCH3); + diag_data->scratch[4] = REG_READ(DMCUB_SCRATCH4); + diag_data->scratch[5] = REG_READ(DMCUB_SCRATCH5); + diag_data->scratch[6] = REG_READ(DMCUB_SCRATCH6); + diag_data->scratch[7] = REG_READ(DMCUB_SCRATCH7); + diag_data->scratch[8] = REG_READ(DMCUB_SCRATCH8); + diag_data->scratch[9] = REG_READ(DMCUB_SCRATCH9); + diag_data->scratch[10] = REG_READ(DMCUB_SCRATCH10); + diag_data->scratch[11] = REG_READ(DMCUB_SCRATCH11); + diag_data->scratch[12] = REG_READ(DMCUB_SCRATCH12); + diag_data->scratch[13] = REG_READ(DMCUB_SCRATCH13); + diag_data->scratch[14] = REG_READ(DMCUB_SCRATCH14); + diag_data->scratch[15] = REG_READ(DMCUB_SCRATCH15); + + diag_data->undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); + diag_data->inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); + diag_data->data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); + + diag_data->inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); + diag_data->inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); + diag_data->inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); + + diag_data->inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); + diag_data->inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); + diag_data->inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); + + REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled); + diag_data->is_dmcub_enabled = is_dmub_enabled; + + REG_GET(DMCUB_CNTL, DMCUB_SOFT_RESET, &is_soft_reset); + diag_data->is_dmcub_soft_reset = is_soft_reset; + + REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset); + diag_data->is_dmcub_secure_reset = is_sec_reset; + + REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled); + diag_data->is_traceport_en = is_traceport_enabled; + + REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled); + diag_data->is_cw0_enabled = is_cw0_enabled; + + REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); + diag_data->is_cw6_enabled = is_cw6_enabled; +} diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h index f772f8b348ea..c2e5831ac52c 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h @@ -36,6 +36,9 @@ struct dmub_srv; DMUB_SR(DMCUB_CNTL) \ DMUB_SR(DMCUB_MEM_CNTL) \ DMUB_SR(DMCUB_SEC_CNTL) \ + DMUB_SR(DMCUB_INBOX0_SIZE) \ + DMUB_SR(DMCUB_INBOX0_RPTR) \ + DMUB_SR(DMCUB_INBOX0_WPTR) \ DMUB_SR(DMCUB_INBOX1_BASE_ADDRESS) \ DMUB_SR(DMCUB_INBOX1_SIZE) \ DMUB_SR(DMCUB_INBOX1_RPTR) \ @@ -108,7 +111,12 @@ struct dmub_srv; DMUB_SR(DCN_VM_FB_LOCATION_BASE) \ DMUB_SR(DCN_VM_FB_OFFSET) \ DMUB_SR(DMCUB_INTERRUPT_ACK) \ - DMUB_SR(DMCUB_TIMER_CURRENT) + DMUB_SR(DMCUB_TIMER_CURRENT) \ + DMUB_SR(DMCUB_INST_FETCH_FAULT_ADDR) \ + DMUB_SR(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR) \ + DMUB_SR(DMCUB_DATA_WRITE_FAULT_ADDR) + +#define DMCUB_INTERNAL_REGS() #define DMUB_COMMON_FIELDS() \ DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \ @@ -118,6 +126,7 @@ struct dmub_srv; DMUB_SF(DMCUB_MEM_CNTL, DMCUB_MEM_WRITE_SPACE) \ DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET) \ DMUB_SF(DMCUB_SEC_CNTL, DMCUB_MEM_UNIT_ID) \ + DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS) \ DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_TOP_ADDRESS) \ DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE) \ DMUB_SF(DMCUB_REGION3_CW1_TOP_ADDRESS, DMCUB_REGION3_CW1_TOP_ADDRESS) \ @@ -147,6 +156,7 @@ struct dmub_srv; struct dmub_srv_common_reg_offset { #define DMUB_SR(reg) uint32_t reg; DMUB_COMMON_REGS() + DMCUB_INTERNAL_REGS() #undef DMUB_SR }; @@ -234,4 +244,6 @@ bool dmub_dcn20_use_cached_trace_buffer(struct dmub_srv *dmub); uint32_t dmub_dcn20_get_current_time(struct dmub_srv *dmub); +void dmub_dcn20_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *dmub_oca); + #endif /* _DMUB_DCN20_H_ */ diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c index 1cf67b3e4771..51bb9bceb1b1 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c @@ -39,7 +39,10 @@ const struct dmub_srv_common_regs dmub_srv_dcn21_regs = { #define DMUB_SR(reg) REG_OFFSET(reg), - { DMUB_COMMON_REGS() }, + { + DMUB_COMMON_REGS() + DMCUB_INTERNAL_REGS() + }, #undef DMUB_SR #define DMUB_SF(reg, field) FD_MASK(reg, field), diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c index fb11c8d39208..81dae75e9ff8 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c @@ -40,7 +40,10 @@ const struct dmub_srv_common_regs dmub_srv_dcn30_regs = { #define DMUB_SR(reg) REG_OFFSET(reg), - { DMUB_COMMON_REGS() }, + { + DMUB_COMMON_REGS() + DMCUB_INTERNAL_REGS() + }, #undef DMUB_SR #define DMUB_SF(reg, field) FD_MASK(reg, field), diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn301.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn301.c index 197398257692..84c3ab3becc5 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn301.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn301.c @@ -39,7 +39,10 @@ const struct dmub_srv_common_regs dmub_srv_dcn301_regs = { #define DMUB_SR(reg) REG_OFFSET(reg), - { DMUB_COMMON_REGS() }, + { + DMUB_COMMON_REGS() + DMCUB_INTERNAL_REGS() + }, #undef DMUB_SR #define DMUB_SF(reg, field) FD_MASK(reg, field), diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn302.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn302.c index f5db4437a882..8c02575e168d 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn302.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn302.c @@ -39,7 +39,10 @@ const struct dmub_srv_common_regs dmub_srv_dcn302_regs = { #define DMUB_SR(reg) REG_OFFSET(reg), - { DMUB_COMMON_REGS() }, + { + DMUB_COMMON_REGS() + DMCUB_INTERNAL_REGS() + }, #undef DMUB_SR #define DMUB_SF(reg, field) FD_MASK(reg, field), diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn303.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn303.c index 9331e1719901..b42369984473 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn303.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn303.c @@ -21,7 +21,10 @@ const struct dmub_srv_common_regs dmub_srv_dcn303_regs = { #define DMUB_SR(reg) REG_OFFSET(reg), - { DMUB_COMMON_REGS() }, + { + DMUB_COMMON_REGS() + DMCUB_INTERNAL_REGS() + }, #undef DMUB_SR #define DMUB_SF(reg, field) FD_MASK(reg, field), diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index 681500f42c91..a195734b4ddf 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -176,6 +176,8 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) funcs->get_outbox0_wptr = dmub_dcn20_get_outbox0_wptr; funcs->set_outbox0_rptr = dmub_dcn20_set_outbox0_rptr; + funcs->get_diagnostic_data = dmub_dcn20_get_diagnostic_data; + if (asic == DMUB_ASIC_DCN21) { dmub->regs = &dmub_srv_dcn21_regs; @@ -794,3 +796,11 @@ bool dmub_srv_get_outbox0_msg(struct dmub_srv *dmub, struct dmcub_trace_buf_entr return dmub_rb_out_trace_buffer_front(&dmub->outbox0_rb, (void *)entry); } + +bool dmub_srv_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data) +{ + if (!dmub || !dmub->hw_funcs.get_diagnostic_data || !diag_data) + return false; + dmub->hw_funcs.get_diagnostic_data(dmub, diag_data); + return true; +} -- 2.25.1 _______________________________________________ amd-gfx mailing list amd-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/amd-gfx