diff --git a/qdf/inc/qdf_types.h b/qdf/inc/qdf_types.h index 2acb3ddc9d..a76dff9c2f 100644 --- a/qdf/inc/qdf_types.h +++ b/qdf/inc/qdf_types.h @@ -1606,6 +1606,14 @@ enum qdf_suspend_type { * of order packet counter values * @QDF_MGMT_RX_REO_ZERO_DURATION_PKT: Reception of management packet with zero * packet duration + * @QDF_VDEV_ACTIVE_SER_CONNECT_TIMEOUT: Active connect cmd in serialization + * timed out. + * @QDF_VDEV_ACTIVE_SER_DISCONNECT_TIMEOUT: Active disconnect cmd in + * serialization timed out. + * @QDF_VDEV_ACTIVE_SER_REASSOC_TIMEOUT: Active reassoc cmd in serialization + * timed out. + * @QDF_VDEV_ACTIVE_SER_LINK_SWITCH_TIMEOUT: Active link switch cmd in + * serialization timed out. */ enum qdf_hang_reason { QDF_REASON_UNSPECIFIED, @@ -1646,6 +1654,10 @@ enum qdf_hang_reason { QDF_MGMT_RX_REO_INCONSISTENT_SNAPSHOT, QDF_MGMT_RX_REO_OUT_OF_ORDER_PKT, QDF_MGMT_RX_REO_ZERO_DURATION_PKT, + QDF_VDEV_ACTIVE_SER_CONNECT_TIMEOUT, + QDF_VDEV_ACTIVE_SER_DISCONNECT_TIMEOUT, + QDF_VDEV_ACTIVE_SER_REASSOC_TIMEOUT, + QDF_VDEV_ACTIVE_SER_LINK_SWITCH_TIMEOUT, }; /** diff --git a/umac/cmn_services/sm_engine/inc/wlan_sm_engine_dbg.h b/umac/cmn_services/sm_engine/inc/wlan_sm_engine_dbg.h index f16f70b1e7..15659a5ba4 100644 --- a/umac/cmn_services/sm_engine/inc/wlan_sm_engine_dbg.h +++ b/umac/cmn_services/sm_engine/inc/wlan_sm_engine_dbg.h @@ -51,7 +51,12 @@ #define sm_engine_nofl_debug(params...) \ QDF_TRACE_DEBUG_NO_FL(QDF_MODULE_ID_SM_ENGINE, params) -#define WLAN_SM_ENGINE_HISTORY_SIZE 50 +#ifdef CONN_MGR_ADV_FEATURE +#define WLAN_SM_ENGINE_HISTORY_SIZE 15 +#else +#define WLAN_SM_ENGINE_HISTORY_SIZE 50 +#endif /* CONN_MGR_ADV_FEATURE */ + struct wlan_sm; /** * enum wlan_sm_trace_type - history element type @@ -64,7 +69,7 @@ enum wlan_sm_trace_type { }; #ifdef SM_ENG_HIST_ENABLE - +#define WLAN_SM_PID_MAX_LEN 7 /** * struct wlan_sm_history_info - history element structure * @trace_type: history element type @@ -72,6 +77,7 @@ enum wlan_sm_trace_type { * @initial_state: Current state (state/sub-state) * @final_state: New state * @time: Timestamp + * @pid_name: Name of task (truncated to WLAN_SM_PID_MAX_LEN bytes) */ struct wlan_sm_history_info { enum wlan_sm_trace_type trace_type; @@ -79,6 +85,7 @@ struct wlan_sm_history_info { uint8_t initial_state; uint8_t final_state; uint64_t time; + char pid_name[WLAN_SM_PID_MAX_LEN]; }; /** diff --git a/umac/cmn_services/sm_engine/src/wlan_sm_engine_dbg.c b/umac/cmn_services/sm_engine/src/wlan_sm_engine_dbg.c index 4e1532f516..78ee1338e9 100644 --- a/umac/cmn_services/sm_engine/src/wlan_sm_engine_dbg.c +++ b/umac/cmn_services/sm_engine/src/wlan_sm_engine_dbg.c @@ -18,6 +18,7 @@ /** * DOC: Implements general SM debug framework */ +#include #include #include @@ -47,6 +48,8 @@ void wlan_sm_save_history(struct wlan_sm *sm, p_memento->final_state = final_state; p_memento->event_type = event_type; p_memento->time = qdf_get_log_timestamp(); + qdf_scnprintf(p_memento->pid_name, WLAN_SM_PID_MAX_LEN, "%.6s", + qdf_get_current_comm()); } void wlan_sm_history_init(struct wlan_sm *sm) @@ -74,8 +77,8 @@ static void wlan_sm_print_history_entry(struct wlan_sm *sm, return; sm_engine_nofl_err( - "| 0x%016llx |%6d |%11d |%23s[%3d] |%19s[%2d] |%19s[%2d] |", - ent->time, i, ent->trace_type, + "| 0x%016llx |%6d |%6s |%11d |%23s[%3d] |%19s[%2d] |%19s[%2d] |", + ent->time, i, ent->pid_name, ent->trace_type, event_name ? event_name : "UNKNOWN_EVENT", ent->event_type, sm->state_info[ent->initial_state].name, @@ -84,8 +87,8 @@ static void wlan_sm_print_history_entry(struct wlan_sm *sm, ent->final_state); } else { sm_engine_nofl_err( - "| 0x%016llx |%6d |%11d |%28d |%19s[%2d] |%19s[%2d] |", - ent->time, i, ent->trace_type, + "| 0x%016llx |%6d |%6s |%11d |%28d |%19s[%2d] |%19s[%2d] |", + ent->time, i, ent->pid_name, ent->trace_type, ent->event_type, sm->state_info[ent->initial_state].name, ent->initial_state, @@ -106,8 +109,8 @@ void wlan_sm_print_history(struct wlan_sm *sm) */ qdf_spin_lock_bh(&p_sm_history->sm_history_lock); - sm_engine_nofl_err("|%19s |%6s |%11s |%28s |%23s |%23s |", "Time", - "Index", "Trace Type", "Event", + sm_engine_nofl_err("|%19s |%6s |%6s |%11s |%28s |%23s |%23s |", "Time", + "Index", "PID", "Trace Type", "Event", "Initial State", "Final State"); for (i = 0; i < WLAN_SM_ENGINE_HISTORY_SIZE; i++) { @@ -134,8 +137,8 @@ static void wlan_sm_print_fs_history_entry(struct wlan_sm *sm, return; qdf_debugfs_printf( - m, "| 0x%016llx |%6d |%11d |%23s[%3d] |%19s[%2d] |%19s[%2d] |\n", - ent->time, i, ent->trace_type, + m, "| 0x%016llx |%6d |%6s |%11d |%23s[%3d] |%19s[%2d] |%19s[%2d] |\n", + ent->time, i, ent->pid_name, ent->trace_type, event_name ? event_name : "UNKNOWN_EVENT", ent->event_type, sm->state_info[ent->initial_state].name, @@ -144,8 +147,8 @@ static void wlan_sm_print_fs_history_entry(struct wlan_sm *sm, ent->final_state); } else { qdf_debugfs_printf( - m, "| 0x%016llx |%6d |%11d |%28d |%19s[%2d] |%19s[%2d] |\n", - ent->time, i, ent->trace_type, + m, "| 0x%016llx |%6d |%6s |%11d |%28d |%19s[%2d] |%19s[%2d] |\n", + ent->time, i, ent->pid_name, ent->trace_type, ent->event_type, sm->state_info[ent->initial_state].name, ent->initial_state, @@ -165,8 +168,8 @@ void wlan_sm_print_fs_history(struct wlan_sm *sm, qdf_debugfs_file_t m) * Save a pointer to next write location and increment pointer. */ qdf_spin_lock_bh(&p_sm_history->sm_history_lock); - qdf_debugfs_printf(m, "|%19s |%6s |%11s |%28s |%23s |%23s |\n", "Time", - "Index", "Trace Type", "Event", + qdf_debugfs_printf(m, "|%19s |%6s |%6s |%11s |%28s |%23s |%23s |\n", "Time", + "Index", "PID", "Trace Type", "Event", "Initial State", "Final State"); for (i = 0; i < WLAN_SM_ENGINE_HISTORY_SIZE; i++) { diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c b/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c index 3b711a848c..eaa2d8ab1c 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c @@ -175,6 +175,7 @@ cm_ser_connect_cb(struct wlan_serialization_command *cmd, QDF_STATUS status = QDF_STATUS_SUCCESS; struct wlan_objmgr_vdev *vdev; struct cnx_mgr *cm_ctx; + enum qdf_hang_reason hang_reason = QDF_VDEV_ACTIVE_SER_CONNECT_TIMEOUT; if (!cmd) { mlme_err("cmd is NULL, reason: %d", reason); @@ -219,7 +220,7 @@ cm_ser_connect_cb(struct wlan_serialization_command *cmd, case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT: mlme_err(CM_PREFIX_FMT "Active command timeout", CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id)); - cm_trigger_panic_on_cmd_timeout(cm_ctx->vdev); + cm_trigger_panic_on_cmd_timeout(cm_ctx->vdev, hang_reason); cm_connect_cmd_timeout(cm_ctx, cmd->cmd_id); break; case WLAN_SER_CB_RELEASE_MEM_CMD: diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c b/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c index cbea1a4519..fe5957e6f0 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c @@ -158,6 +158,8 @@ cm_ser_disconnect_cb(struct wlan_serialization_command *cmd, QDF_STATUS status = QDF_STATUS_SUCCESS; struct wlan_objmgr_vdev *vdev; struct cnx_mgr *cm_ctx; + enum qdf_hang_reason hang_reason = + QDF_VDEV_ACTIVE_SER_DISCONNECT_TIMEOUT; if (!cmd) { mlme_err("cmd is NULL, reason: %d", reason); @@ -192,7 +194,7 @@ cm_ser_disconnect_cb(struct wlan_serialization_command *cmd, case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT: mlme_err(CM_PREFIX_FMT "Active command timeout", CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id)); - cm_trigger_panic_on_cmd_timeout(cm_ctx->vdev); + cm_trigger_panic_on_cmd_timeout(cm_ctx->vdev, hang_reason); cm_send_disconnect_resp(cm_ctx, cmd->cmd_id); break; case WLAN_SER_CB_RELEASE_MEM_CMD: diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_host_roam.c b/umac/mlme/connection_mgr/core/src/wlan_cm_host_roam.c index ba04e742f4..2fe03953c0 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_host_roam.c +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_host_roam.c @@ -571,6 +571,8 @@ cm_ser_reassoc_cb(struct wlan_serialization_command *cmd, QDF_STATUS status = QDF_STATUS_SUCCESS; struct wlan_objmgr_vdev *vdev; struct cnx_mgr *cm_ctx; + enum qdf_hang_reason hang_reason = + QDF_VDEV_ACTIVE_SER_REASSOC_TIMEOUT; if (!cmd) { mlme_err("cmd is NULL, reason: %d", reason); @@ -614,7 +616,7 @@ cm_ser_reassoc_cb(struct wlan_serialization_command *cmd, case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT: mlme_err(CM_PREFIX_FMT "Active command timeout", CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id)); - cm_trigger_panic_on_cmd_timeout(cm_ctx->vdev); + cm_trigger_panic_on_cmd_timeout(cm_ctx->vdev, hang_reason); cm_reassoc_cmd_timeout(cm_ctx, cmd->cmd_id); break; case WLAN_SER_CB_RELEASE_MEM_CMD: diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h b/umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h index 2e2cd6b577..05e6e80169 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h @@ -1007,10 +1007,12 @@ void cm_set_max_connect_attempts(struct wlan_objmgr_vdev *vdev, /** * cm_trigger_panic_on_cmd_timeout() - trigger panic on active command timeout * @vdev: vdev pointer + * @reason: Hang reason code * * Return: void */ -void cm_trigger_panic_on_cmd_timeout(struct wlan_objmgr_vdev *vdev); +void cm_trigger_panic_on_cmd_timeout(struct wlan_objmgr_vdev *vdev, + enum qdf_hang_reason reason); /** * cm_set_max_connect_timeout() - Set max connect timeout diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_util.c b/umac/mlme/connection_mgr/core/src/wlan_cm_util.c index 69907d5aeb..c2855444bb 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_util.c +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_util.c @@ -197,6 +197,24 @@ QDF_STATUS cm_set_key(struct cnx_mgr *cm_ctx, bool unicast, } #endif +static void cm_dump_sm_history(struct wlan_objmgr_vdev *vdev) +{ + struct vdev_mlme_obj *vdev_mlme; + struct wlan_sm *vdev_sm; + + vdev_mlme = wlan_objmgr_vdev_get_comp_private_obj(vdev, + WLAN_UMAC_COMP_MLME); + if (!vdev_mlme) + return; + + vdev_sm = vdev_mlme->sm_hdl; + if (!vdev_sm) + return; + + wlan_sm_print_history(vdev_sm); + cm_sm_history_print(vdev); +} + #ifdef CONN_MGR_ADV_FEATURE void cm_store_wep_key(struct cnx_mgr *cm_ctx, struct wlan_cm_connect_crypto_info *crypto, @@ -255,7 +273,8 @@ void cm_store_wep_key(struct cnx_mgr *cm_ctx, wep_keys->seq_len); } -void cm_trigger_panic_on_cmd_timeout(struct wlan_objmgr_vdev *vdev) +void cm_trigger_panic_on_cmd_timeout(struct wlan_objmgr_vdev *vdev, + enum qdf_hang_reason reason) { struct wlan_objmgr_psoc *psoc; @@ -266,32 +285,15 @@ void cm_trigger_panic_on_cmd_timeout(struct wlan_objmgr_vdev *vdev) if (qdf_is_recovering() || qdf_is_fw_down()) return; - qdf_trigger_self_recovery(psoc, QDF_ACTIVE_LIST_TIMEOUT); + cm_dump_sm_history(vdev); + qdf_trigger_self_recovery(psoc, reason); } #else -void cm_trigger_panic_on_cmd_timeout(struct wlan_objmgr_vdev *vdev) +void cm_trigger_panic_on_cmd_timeout(struct wlan_objmgr_vdev *vdev, + enum qdf_hang_reason reason) { - struct vdev_mlme_obj *vdev_mlme = NULL; - struct wlan_sm *vdev_sm = NULL; - - vdev_mlme = wlan_objmgr_vdev_get_comp_private_obj( - vdev, - WLAN_UMAC_COMP_MLME); - if (!vdev_mlme) { - mlme_err("VDEV MLME is null"); - goto error; - } - - vdev_sm = vdev_mlme->sm_hdl; - if (!vdev_sm) { - mlme_err("VDEV SM is null"); - goto error; - } - - wlan_sm_print_history(vdev_sm); - cm_sm_history_print(vdev); -error: + cm_dump_sm_history(vdev); QDF_ASSERT(0); } #endif diff --git a/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_api.h b/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_api.h index 838bc26a2b..7c1d787874 100644 --- a/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_api.h +++ b/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_api.h @@ -256,6 +256,16 @@ bool wlan_cm_is_link_switch_disconnect_resp(struct wlan_cm_discon_rsp *resp); */ bool wlan_cm_is_link_switch_connect_resp(struct wlan_cm_connect_resp *resp); +/** + * wlan_cm_trigger_panic_on_cmd_timeout() - Trigger recovery on CM command + * timeout. + * @vdev: VDEV object manager + * @reason: Hang reason code + * + * Return: void + */ +void wlan_cm_trigger_panic_on_cmd_timeout(struct wlan_objmgr_vdev *vdev, + enum qdf_hang_reason reason); #ifdef WLAN_FEATURE_ROAM_OFFLOAD /** * wlan_cm_is_vdev_roam_started() - check if vdev is in roaming state and diff --git a/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c b/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c index 9973e62f68..765531ad2d 100644 --- a/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c +++ b/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c @@ -265,6 +265,12 @@ bool wlan_cm_is_link_switch_connect_resp(struct wlan_cm_connect_resp *resp) return cm_is_link_switch_connect_resp(resp); } +void wlan_cm_trigger_panic_on_cmd_timeout(struct wlan_objmgr_vdev *vdev, + enum qdf_hang_reason reason) +{ + cm_trigger_panic_on_cmd_timeout(vdev, reason); +} + #ifdef WLAN_FEATURE_HOST_ROAM bool wlan_cm_get_active_reassoc_req(struct wlan_objmgr_vdev *vdev, struct wlan_cm_vdev_reassoc_req *req) diff --git a/umac/mlo_mgr/src/wlan_mlo_mgr_link_switch.c b/umac/mlo_mgr/src/wlan_mlo_mgr_link_switch.c index 550c903243..318b8cf84c 100644 --- a/umac/mlo_mgr/src/wlan_mlo_mgr_link_switch.c +++ b/umac/mlo_mgr/src/wlan_mlo_mgr_link_switch.c @@ -892,38 +892,17 @@ mlo_mgr_start_link_switch(struct wlan_objmgr_vdev *vdev, return status; } -/** - * mlo_mgr_trigger_recovery_on_link_switch_timeout() - trigger panic on link - * switch timeout - * @vdev: vdev pointer - * - * Return: void - */ -static void -mlo_mgr_trigger_recovery_on_link_switch_timeout(struct wlan_objmgr_vdev *vdev) -{ - struct wlan_objmgr_psoc *psoc; - - psoc = wlan_vdev_get_psoc(vdev); - if (!psoc) - return; - - if (qdf_is_recovering() || qdf_is_fw_down()) - return; - - qdf_trigger_self_recovery(psoc, QDF_ACTIVE_LIST_TIMEOUT); -} - static QDF_STATUS mlo_mgr_ser_link_switch_cb(struct wlan_serialization_command *cmd, - enum wlan_serialization_cb_reason reason) + enum wlan_serialization_cb_reason cb_reason) { struct wlan_objmgr_vdev *vdev; QDF_STATUS status = QDF_STATUS_SUCCESS; struct wlan_mlo_link_switch_req *req; + enum qdf_hang_reason reason = QDF_VDEV_ACTIVE_SER_LINK_SWITCH_TIMEOUT; if (!cmd) { - mlo_err("cmd is NULL, reason: %d", reason); + mlo_err("cmd is NULL, reason: %d", cb_reason); QDF_ASSERT(0); return QDF_STATUS_E_NULL_VALUE; } @@ -931,7 +910,7 @@ mlo_mgr_ser_link_switch_cb(struct wlan_serialization_command *cmd, vdev = cmd->vdev; req = &vdev->mlo_dev_ctx->link_ctx->last_req; - switch (reason) { + switch (cb_reason) { case WLAN_SER_CB_ACTIVATE_CMD: status = mlo_mgr_start_link_switch(vdev, cmd); if (QDF_IS_STATUS_ERROR(status)) { @@ -947,7 +926,7 @@ mlo_mgr_ser_link_switch_cb(struct wlan_serialization_command *cmd, break; case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT: mlo_err("Link switch active cmd timeout"); - mlo_mgr_trigger_recovery_on_link_switch_timeout(vdev); + wlan_cm_trigger_panic_on_cmd_timeout(vdev, reason); break; default: QDF_ASSERT(0);