]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
drm/amd/display: Add extra DMUB logging to track message timeout
authorAlvin Lee <alvin.lee2@amd.com>
Thu, 21 Mar 2024 15:06:06 +0000 (11:06 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 10 Apr 2024 02:04:32 +0000 (22:04 -0400)
[Description]
- Add logging for first DMUB inbox message that timed out to diagnostic
  data
- It is useful to track the first failed message for debug purposes
  because once DMUB becomes hung (typically on a message), it will
  remain hung and all subsequent messages. In these cases we're
  interested in knowing which is the first message that failed.

Reviewed-by: Josip Pavic <josip.pavic@amd.com>
Acked-by: Roman Li <roman.li@amd.com>
Signed-off-by: Alvin Lee <alvin.lee2@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
drivers/gpu/drm/amd/display/dmub/dmub_srv.h
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c

index 9ae0e602e737ec0137094c21c8029d1320e4db5b..34d199b08dd9c9839b67aee0b7989e9a1b51f07a 100644 (file)
@@ -23,6 +23,7 @@
  *
  */
 
+#include "dm_services.h"
 #include "dc.h"
 #include "dc_dmub_srv.h"
 #include "../dmub/dmub_srv.h"
@@ -198,6 +199,11 @@ 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);
+                       }
                        dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
                        return false;
                }
@@ -904,6 +910,7 @@ bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmu
 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) {
                DC_LOG_ERROR("%s: invalid parameters.", __func__);
@@ -935,7 +942,8 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv)
        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("    pc                 : %08x", diag_data.pc);
+       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);
index 7785908a6676a73559bcae04b21f6aa74ac8b5c6..662bdb0e5d3dd1c52d09632888cb41a6e38d382d 100644 (file)
@@ -71,6 +71,8 @@
 extern "C" {
 #endif
 
+#define DMUB_PC_SNAPSHOT_COUNT 10
+
 /* Forward declarations */
 struct dmub_srv;
 struct dmub_srv_common_regs;
@@ -299,6 +301,17 @@ struct dmub_srv_hw_params {
        enum dmub_ips_disable_type disable_ips;
 };
 
+/**
+ * struct dmub_srv_debug - Debug info for dmub_srv
+ * @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 {
+       bool timeout_occured;
+       union dmub_rb_cmd timeout_cmd;
+       unsigned long long timestamp;
+};
+
 /**
  * struct dmub_diagnostic_data - Diagnostic data retrieved from DMCUB for
  * debugging purposes, including logging, crash analysis, etc.
@@ -306,7 +319,7 @@ struct dmub_srv_hw_params {
 struct dmub_diagnostic_data {
        uint32_t dmcub_version;
        uint32_t scratch[17];
-       uint32_t pc;
+       uint32_t pc[DMUB_PC_SNAPSHOT_COUNT];
        uint32_t undefined_address_fault_addr;
        uint32_t inst_fetch_fault_addr;
        uint32_t data_write_fault_addr;
@@ -317,6 +330,7 @@ struct dmub_diagnostic_data {
        uint32_t inbox0_wptr;
        uint32_t inbox0_size;
        uint32_t gpint_datain0;
+       struct dmub_srv_debug timeout_info;
        uint8_t is_dmcub_enabled : 1;
        uint8_t is_dmcub_soft_reset : 1;
        uint8_t is_dmcub_secure_reset : 1;
@@ -506,6 +520,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;
 };
 
 /**
index cae96fba634982186b2cf7624ff001cd2ee60ef0..e500ca9ae09ce81766c70d67d3b37f3803bf465d 100644 (file)
@@ -472,4 +472,5 @@ void dmub_dcn20_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnosti
 
        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;
 }
index 2bcf5fb87dd9e82499648e18f0c1e4a44c0251e5..662c34e9495ccbe079c3521309eba09d1cc24cf1 100644 (file)
@@ -466,6 +466,7 @@ void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnosti
 
        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;
 }
 
 bool dmub_dcn31_should_detect(struct dmub_srv *dmub)
index 0d521eeda0501cf7bf98bc162573774df9728a2f..e1da270502cc921dc32b8f2599a6ef8041cbb351 100644 (file)
@@ -478,6 +478,8 @@ void dmub_dcn32_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnosti
        diag_data->is_cw6_enabled = is_cw6_enabled;
 
        diag_data->gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0);
+
+       diag_data->timeout_info = dmub->debug;
 }
 void dmub_dcn32_configure_dmub_in_system_memory(struct dmub_srv *dmub)
 {
index 53f359f3fae26f1dd5c9f64ec9265741df145642..98afaecd3984ac65d4f62fe335a32ffa38c677f1 100644 (file)
@@ -516,6 +516,7 @@ void dmub_dcn35_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnosti
        diag_data->is_cw6_enabled = is_cw6_enabled;
 
        diag_data->gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0);
+       diag_data->timeout_info = dmub->debug;
 }
 void dmub_dcn35_configure_dmub_in_system_memory(struct dmub_srv *dmub)
 {