Commit d93b92c9 authored by Joshua Aberback's avatar Joshua Aberback Committed by Alex Deucher
Browse files

drm/amd/display: Add more debug data to dmub_srv



[Why]
When analyzing some crash dumps, not all of the expected DMUB info was
available, so we want to add in-object storage for this data.

[How]
 - dmub_srv_debug (renamed to dmub_timeout_info) is already a member of
dmub_diagnostic_data, therefore keep a dmub_diagnostic_data directly in
dmub_srv
 - use dmub_srv->debug when collecting diagnostic info instead of stack
object to allow for easy inspection in crash dumps

Reviewed-by: default avatarAlvin Lee <alvin.lee2@amd.com>
Signed-off-by: default avatarJoshua Aberback <joshua.aberback@amd.com>
Signed-off-by: default avatarTom Chung <chiahsuan.chung@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 7b1ba19e
Loading
Loading
Loading
Loading
+44 −45
Original line number Diff line number Diff line
@@ -200,10 +200,10 @@ bool dc_dmub_srv_wait_for_idle(struct dc_dmub_srv *dc_dmub_srv,

		if (status != DMUB_STATUS_OK) {
			DC_LOG_DEBUG("No reply for DMUB command: status=%d\n", status);
			if (!dmub->debug.timeout_occured) {
				dmub->debug.timeout_occured = true;
				dmub->debug.timeout_cmd = *cmd_list;
				dmub->debug.timestamp = dm_get_timestamp(dc_dmub_srv->ctx);
			if (!dmub->debug.timeout_info.timeout_occured) {
				dmub->debug.timeout_info.timeout_occured = true;
				dmub->debug.timeout_info.timeout_cmd = *cmd_list;
				dmub->debug.timeout_info.timestamp = dm_get_timestamp(dc_dmub_srv->ctx);
			}
			dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
			return false;
@@ -927,16 +927,15 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc,
	dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}

bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmub_diagnostic_data *diag_data)
bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv)
{
	if (!dc_dmub_srv || !dc_dmub_srv->dmub || !diag_data)
	if (!dc_dmub_srv || !dc_dmub_srv->dmub)
		return false;
	return dmub_srv_get_diagnostic_data(dc_dmub_srv->dmub, diag_data);
	return dmub_srv_get_diagnostic_data(dc_dmub_srv->dmub);
}

void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv)
{
	struct dmub_diagnostic_data diag_data = {0};
	uint32_t i;

	if (!dc_dmub_srv || !dc_dmub_srv->dmub) {
@@ -946,49 +945,49 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv)

	DC_LOG_ERROR("%s: DMCUB error - collecting diagnostic data\n", __func__);

	if (!dc_dmub_srv_get_diagnostic_data(dc_dmub_srv, &diag_data)) {
	if (!dc_dmub_srv_get_diagnostic_data(dc_dmub_srv)) {
		DC_LOG_ERROR("%s: dc_dmub_srv_get_diagnostic_data failed.", __func__);
		return;
	}

	DC_LOG_DEBUG("DMCUB STATE:");
	DC_LOG_DEBUG("    dmcub_version      : %08x", diag_data.dmcub_version);
	DC_LOG_DEBUG("    scratch  [0]       : %08x", diag_data.scratch[0]);
	DC_LOG_DEBUG("    scratch  [1]       : %08x", diag_data.scratch[1]);
	DC_LOG_DEBUG("    scratch  [2]       : %08x", diag_data.scratch[2]);
	DC_LOG_DEBUG("    scratch  [3]       : %08x", diag_data.scratch[3]);
	DC_LOG_DEBUG("    scratch  [4]       : %08x", diag_data.scratch[4]);
	DC_LOG_DEBUG("    scratch  [5]       : %08x", diag_data.scratch[5]);
	DC_LOG_DEBUG("    scratch  [6]       : %08x", diag_data.scratch[6]);
	DC_LOG_DEBUG("    scratch  [7]       : %08x", diag_data.scratch[7]);
	DC_LOG_DEBUG("    scratch  [8]       : %08x", diag_data.scratch[8]);
	DC_LOG_DEBUG("    scratch  [9]       : %08x", diag_data.scratch[9]);
	DC_LOG_DEBUG("    scratch [10]       : %08x", diag_data.scratch[10]);
	DC_LOG_DEBUG("    scratch [11]       : %08x", diag_data.scratch[11]);
	DC_LOG_DEBUG("    scratch [12]       : %08x", diag_data.scratch[12]);
	DC_LOG_DEBUG("    scratch [13]       : %08x", diag_data.scratch[13]);
	DC_LOG_DEBUG("    scratch [14]       : %08x", diag_data.scratch[14]);
	DC_LOG_DEBUG("    scratch [15]       : %08x", diag_data.scratch[15]);
	DC_LOG_DEBUG("    dmcub_version      : %08x", dc_dmub_srv->dmub->debug.dmcub_version);
	DC_LOG_DEBUG("    scratch  [0]       : %08x", dc_dmub_srv->dmub->debug.scratch[0]);
	DC_LOG_DEBUG("    scratch  [1]       : %08x", dc_dmub_srv->dmub->debug.scratch[1]);
	DC_LOG_DEBUG("    scratch  [2]       : %08x", dc_dmub_srv->dmub->debug.scratch[2]);
	DC_LOG_DEBUG("    scratch  [3]       : %08x", dc_dmub_srv->dmub->debug.scratch[3]);
	DC_LOG_DEBUG("    scratch  [4]       : %08x", dc_dmub_srv->dmub->debug.scratch[4]);
	DC_LOG_DEBUG("    scratch  [5]       : %08x", dc_dmub_srv->dmub->debug.scratch[5]);
	DC_LOG_DEBUG("    scratch  [6]       : %08x", dc_dmub_srv->dmub->debug.scratch[6]);
	DC_LOG_DEBUG("    scratch  [7]       : %08x", dc_dmub_srv->dmub->debug.scratch[7]);
	DC_LOG_DEBUG("    scratch  [8]       : %08x", dc_dmub_srv->dmub->debug.scratch[8]);
	DC_LOG_DEBUG("    scratch  [9]       : %08x", dc_dmub_srv->dmub->debug.scratch[9]);
	DC_LOG_DEBUG("    scratch [10]       : %08x", dc_dmub_srv->dmub->debug.scratch[10]);
	DC_LOG_DEBUG("    scratch [11]       : %08x", dc_dmub_srv->dmub->debug.scratch[11]);
	DC_LOG_DEBUG("    scratch [12]       : %08x", dc_dmub_srv->dmub->debug.scratch[12]);
	DC_LOG_DEBUG("    scratch [13]       : %08x", dc_dmub_srv->dmub->debug.scratch[13]);
	DC_LOG_DEBUG("    scratch [14]       : %08x", dc_dmub_srv->dmub->debug.scratch[14]);
	DC_LOG_DEBUG("    scratch [15]       : %08x", dc_dmub_srv->dmub->debug.scratch[15]);
	for (i = 0; i < DMUB_PC_SNAPSHOT_COUNT; i++)
		DC_LOG_DEBUG("    pc[%d]             : %08x", i, diag_data.pc[i]);
	DC_LOG_DEBUG("    unk_fault_addr     : %08x", diag_data.undefined_address_fault_addr);
	DC_LOG_DEBUG("    inst_fault_addr    : %08x", diag_data.inst_fetch_fault_addr);
	DC_LOG_DEBUG("    data_fault_addr    : %08x", diag_data.data_write_fault_addr);
	DC_LOG_DEBUG("    inbox1_rptr        : %08x", diag_data.inbox1_rptr);
	DC_LOG_DEBUG("    inbox1_wptr        : %08x", diag_data.inbox1_wptr);
	DC_LOG_DEBUG("    inbox1_size        : %08x", diag_data.inbox1_size);
	DC_LOG_DEBUG("    inbox0_rptr        : %08x", diag_data.inbox0_rptr);
	DC_LOG_DEBUG("    inbox0_wptr        : %08x", diag_data.inbox0_wptr);
	DC_LOG_DEBUG("    inbox0_size        : %08x", diag_data.inbox0_size);
	DC_LOG_DEBUG("    outbox1_rptr       : %08x", diag_data.outbox1_rptr);
	DC_LOG_DEBUG("    outbox1_wptr       : %08x", diag_data.outbox1_wptr);
	DC_LOG_DEBUG("    outbox1_size       : %08x", diag_data.outbox1_size);
	DC_LOG_DEBUG("    is_enabled         : %d", diag_data.is_dmcub_enabled);
	DC_LOG_DEBUG("    is_soft_reset      : %d", diag_data.is_dmcub_soft_reset);
	DC_LOG_DEBUG("    is_secure_reset    : %d", diag_data.is_dmcub_secure_reset);
	DC_LOG_DEBUG("    is_traceport_en    : %d", diag_data.is_traceport_en);
	DC_LOG_DEBUG("    is_cw0_en          : %d", diag_data.is_cw0_enabled);
	DC_LOG_DEBUG("    is_cw6_en          : %d", diag_data.is_cw6_enabled);
		DC_LOG_DEBUG("    pc[%d]             : %08x", i, dc_dmub_srv->dmub->debug.pc[i]);
	DC_LOG_DEBUG("    unk_fault_addr     : %08x", dc_dmub_srv->dmub->debug.undefined_address_fault_addr);
	DC_LOG_DEBUG("    inst_fault_addr    : %08x", dc_dmub_srv->dmub->debug.inst_fetch_fault_addr);
	DC_LOG_DEBUG("    data_fault_addr    : %08x", dc_dmub_srv->dmub->debug.data_write_fault_addr);
	DC_LOG_DEBUG("    inbox1_rptr        : %08x", dc_dmub_srv->dmub->debug.inbox1_rptr);
	DC_LOG_DEBUG("    inbox1_wptr        : %08x", dc_dmub_srv->dmub->debug.inbox1_wptr);
	DC_LOG_DEBUG("    inbox1_size        : %08x", dc_dmub_srv->dmub->debug.inbox1_size);
	DC_LOG_DEBUG("    inbox0_rptr        : %08x", dc_dmub_srv->dmub->debug.inbox0_rptr);
	DC_LOG_DEBUG("    inbox0_wptr        : %08x", dc_dmub_srv->dmub->debug.inbox0_wptr);
	DC_LOG_DEBUG("    inbox0_size        : %08x", dc_dmub_srv->dmub->debug.inbox0_size);
	DC_LOG_DEBUG("    outbox1_rptr       : %08x", dc_dmub_srv->dmub->debug.outbox1_rptr);
	DC_LOG_DEBUG("    outbox1_wptr       : %08x", dc_dmub_srv->dmub->debug.outbox1_wptr);
	DC_LOG_DEBUG("    outbox1_size       : %08x", dc_dmub_srv->dmub->debug.outbox1_size);
	DC_LOG_DEBUG("    is_enabled         : %d", dc_dmub_srv->dmub->debug.is_dmcub_enabled);
	DC_LOG_DEBUG("    is_soft_reset      : %d", dc_dmub_srv->dmub->debug.is_dmcub_soft_reset);
	DC_LOG_DEBUG("    is_secure_reset    : %d", dc_dmub_srv->dmub->debug.is_dmcub_secure_reset);
	DC_LOG_DEBUG("    is_traceport_en    : %d", dc_dmub_srv->dmub->debug.is_traceport_en);
	DC_LOG_DEBUG("    is_cw0_en          : %d", dc_dmub_srv->dmub->debug.is_cw0_enabled);
	DC_LOG_DEBUG("    is_cw6_en          : %d", dc_dmub_srv->dmub->debug.is_cw6_enabled);
}

static bool dc_dmub_should_update_cursor_data(struct pipe_ctx *pipe_ctx)
+1 −1
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ void dc_dmub_srv_clear_inbox0_ack(struct dc_dmub_srv *dmub_srv);
void dc_dmub_srv_wait_for_inbox0_ack(struct dc_dmub_srv *dmub_srv);
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);
bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv);

void dc_dmub_setup_subvp_dmub_command(struct dc *dc, struct dc_state *context, bool enable);
void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv);
+5 −5
Original line number Diff line number Diff line
@@ -313,7 +313,7 @@ struct dmub_srv_hw_params {
 * @timeout_occured: Indicates a timeout occured on any message from driver to dmub
 * @timeout_cmd: first cmd sent from driver that timed out - subsequent timeouts are not stored
 */
struct dmub_srv_debug {
struct dmub_timeout_info {
	bool timeout_occured;
	union dmub_rb_cmd timeout_cmd;
	unsigned long long timestamp;
@@ -340,7 +340,7 @@ struct dmub_diagnostic_data {
	uint32_t outbox1_wptr;
	uint32_t outbox1_size;
	uint32_t gpint_datain0;
	struct dmub_srv_debug timeout_info;
	struct dmub_timeout_info timeout_info;
	uint8_t is_dmcub_enabled : 1;
	uint8_t is_dmcub_soft_reset : 1;
	uint8_t is_dmcub_secure_reset : 1;
@@ -456,7 +456,7 @@ 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);
	void (*get_diagnostic_data)(struct dmub_srv *dmub);

	bool (*should_detect)(struct dmub_srv *dmub);
	void (*init_reg_offsets)(struct dmub_srv *dmub, struct dc_context *ctx);
@@ -545,7 +545,7 @@ struct dmub_srv {
	struct dmub_visual_confirm_color visual_confirm_color;

	enum dmub_srv_power_state_type power_state;
	struct dmub_srv_debug debug;
	struct dmub_diagnostic_data debug;
};

/**
@@ -901,7 +901,7 @@ enum dmub_status dmub_srv_set_skip_panel_power_sequence(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);
bool dmub_srv_get_diagnostic_data(struct dmub_srv *dmub);

bool dmub_srv_should_detect(struct dmub_srv *dmub);

+44 −41
Original line number Diff line number Diff line
@@ -414,63 +414,66 @@ 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)
void dmub_dcn20_get_diagnostic_data(struct dmub_srv *dmub)
{
	uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset;
	uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled;
	struct dmub_timeout_info timeout = {0};

	if (!dmub || !diag_data)
	if (!dmub)
		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);
	/* timeout data filled externally, cache before resetting memory */
	timeout = dmub->debug.timeout_info;
	memset(&dmub->debug, 0, sizeof(dmub->debug));
	dmub->debug.timeout_info = timeout;

	dmub->debug.dmcub_version = dmub->fw_version;

	dmub->debug.scratch[0] = REG_READ(DMCUB_SCRATCH0);
	dmub->debug.scratch[1] = REG_READ(DMCUB_SCRATCH1);
	dmub->debug.scratch[2] = REG_READ(DMCUB_SCRATCH2);
	dmub->debug.scratch[3] = REG_READ(DMCUB_SCRATCH3);
	dmub->debug.scratch[4] = REG_READ(DMCUB_SCRATCH4);
	dmub->debug.scratch[5] = REG_READ(DMCUB_SCRATCH5);
	dmub->debug.scratch[6] = REG_READ(DMCUB_SCRATCH6);
	dmub->debug.scratch[7] = REG_READ(DMCUB_SCRATCH7);
	dmub->debug.scratch[8] = REG_READ(DMCUB_SCRATCH8);
	dmub->debug.scratch[9] = REG_READ(DMCUB_SCRATCH9);
	dmub->debug.scratch[10] = REG_READ(DMCUB_SCRATCH10);
	dmub->debug.scratch[11] = REG_READ(DMCUB_SCRATCH11);
	dmub->debug.scratch[12] = REG_READ(DMCUB_SCRATCH12);
	dmub->debug.scratch[13] = REG_READ(DMCUB_SCRATCH13);
	dmub->debug.scratch[14] = REG_READ(DMCUB_SCRATCH14);
	dmub->debug.scratch[15] = REG_READ(DMCUB_SCRATCH15);

	dmub->debug.undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR);
	dmub->debug.inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR);
	dmub->debug.data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR);

	dmub->debug.inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR);
	dmub->debug.inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR);
	dmub->debug.inbox1_size = REG_READ(DMCUB_INBOX1_SIZE);

	dmub->debug.inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR);
	dmub->debug.inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR);
	dmub->debug.inbox0_size = REG_READ(DMCUB_INBOX0_SIZE);

	REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
	diag_data->is_dmcub_enabled = is_dmub_enabled;
	dmub->debug.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;
	dmub->debug.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;
	dmub->debug.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;
	dmub->debug.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;
	dmub->debug.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;
	diag_data->timeout_info = dmub->debug;
	dmub->debug.is_cw6_enabled = is_cw6_enabled;
}
+1 −1
Original line number Diff line number Diff line
@@ -247,6 +247,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);
void dmub_dcn20_get_diagnostic_data(struct dmub_srv *dmub);

#endif /* _DMUB_DCN20_H_ */
Loading