diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h index e60ae4fd52..5b85fa1b0a 100644 --- a/core/cds/inc/cds_api.h +++ b/core/cds/inc/cds_api.h @@ -231,16 +231,25 @@ void cds_set_multicast_logging(uint8_t value); uint8_t cds_is_multicast_logging(void); QDF_STATUS cds_set_log_completion(uint32_t is_fatal, uint32_t type, - uint32_t sub_type); -void cds_get_log_completion(uint32_t *is_fatal, + uint32_t sub_type, + bool recovery_needed); +void cds_get_and_reset_log_completion(uint32_t *is_fatal, uint32_t *type, - uint32_t *sub_type); + uint32_t *sub_type, + bool *recovery_needed); bool cds_is_log_report_in_progress(void); +bool cds_is_fatal_event_enabled(void); +uint32_t cds_get_log_indicator(void); +void cds_set_fatal_event(bool value); +void cds_wlan_flush_host_logs_for_fatal(void); + void cds_init_log_completion(void); void cds_deinit_log_completion(void); QDF_STATUS cds_flush_logs(uint32_t is_fatal, uint32_t indicator, - uint32_t reason_code); + uint32_t reason_code, + bool dump_mac_trace, + bool recovery_needed); void cds_logging_set_fw_flush_complete(void); #ifdef FEATURE_WLAN_DIAG_SUPPORT diff --git a/core/cds/inc/cds_sched.h b/core/cds/inc/cds_sched.h index 4a26355e58..cc082411e1 100644 --- a/core/cds/inc/cds_sched.h +++ b/core/cds/inc/cds_sched.h @@ -209,6 +209,7 @@ typedef struct _cds_sched_context { * @indicator: Source of bug report * @reason_code: Reason code for bug report * @is_report_in_progress: If bug report is in progress + * @recovery_needed: if recovery is needed after report completion * * This structure internally stores the log related params */ @@ -217,6 +218,7 @@ struct cds_log_complete { uint32_t indicator; uint32_t reason_code; bool is_report_in_progress; + bool recovery_needed; }; /* @@ -292,6 +294,7 @@ typedef struct _cds_context_type { void (*sap_restart_chan_switch_cb)(void *, uint32_t, uint32_t); #endif bool do_hw_mode_change; + bool enable_fatal_event; } cds_context_type, *p_cds_contextType; /*--------------------------------------------------------------------------- diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index 8fe325c92a..684bdb5dae 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -1344,11 +1344,15 @@ QDF_STATUS cds_mq_post_message(CDS_MQ_ID msgQueueId, cds_msg_t *pMsg) if (NULL == pMsgWrapper) { debug_count = atomic_inc_return(&cds_wrapper_empty_count); - if (1 == debug_count) + if (1 == debug_count) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: CDS Core run out of message wrapper %d", __func__, debug_count); - + cds_flush_logs(WLAN_LOG_TYPE_FATAL, + WLAN_LOG_INDICATOR_HOST_ONLY, + WLAN_LOG_REASON_VOS_MSG_UNDER_RUN, + true, false); + } if (CDS_WRAPPER_MAX_FAIL_COUNT == debug_count) QDF_BUG(0); @@ -1921,6 +1925,7 @@ void cds_deinit_log_completion(void) * @is_fatal: Indicates if the event triggering bug report is fatal or not * @indicator: Source which trigerred the bug report * @reason_code: Reason for triggering bug report + * @recovery_needed: If recovery is needed after bug report * * This function is used to set the logging parameters based on the * caller @@ -1929,7 +1934,8 @@ void cds_deinit_log_completion(void) */ QDF_STATUS cds_set_log_completion(uint32_t is_fatal, uint32_t indicator, - uint32_t reason_code) + uint32_t reason_code, + bool recovery_needed) { p_cds_contextType p_cds_context; @@ -1944,24 +1950,27 @@ QDF_STATUS cds_set_log_completion(uint32_t is_fatal, p_cds_context->log_complete.is_fatal = is_fatal; p_cds_context->log_complete.indicator = indicator; p_cds_context->log_complete.reason_code = reason_code; + p_cds_context->log_complete.recovery_needed = recovery_needed; p_cds_context->log_complete.is_report_in_progress = true; qdf_spinlock_release(&p_cds_context->bug_report_lock); return QDF_STATUS_SUCCESS; } /** - * cds_get_log_completion() - Get the logging related params + * cds_get_and_reset_log_completion() - Get and reset logging related params * @is_fatal: Indicates if the event triggering bug report is fatal or not * @indicator: Source which trigerred the bug report * @reason_code: Reason for triggering bug report + * @recovery_needed: If recovery is needed after bug report * * This function is used to get the logging related parameters * * Return: None */ -void cds_get_log_completion(uint32_t *is_fatal, +void cds_get_and_reset_log_completion(uint32_t *is_fatal, uint32_t *indicator, - uint32_t *reason_code) + uint32_t *reason_code, + bool *recovery_needed) { p_cds_contextType p_cds_context; @@ -1976,7 +1985,14 @@ void cds_get_log_completion(uint32_t *is_fatal, *is_fatal = p_cds_context->log_complete.is_fatal; *indicator = p_cds_context->log_complete.indicator; *reason_code = p_cds_context->log_complete.reason_code; + *recovery_needed = p_cds_context->log_complete.recovery_needed; + + /* reset */ + p_cds_context->log_complete.indicator = WLAN_LOG_INDICATOR_UNUSED; + p_cds_context->log_complete.is_fatal = WLAN_LOG_TYPE_NON_FATAL; p_cds_context->log_complete.is_report_in_progress = false; + p_cds_context->log_complete.reason_code = WLAN_LOG_REASON_CODE_UNUSED; + p_cds_context->log_complete.recovery_needed = false; qdf_spinlock_release(&p_cds_context->bug_report_lock); } @@ -2000,11 +2016,80 @@ bool cds_is_log_report_in_progress(void) return p_cds_context->log_complete.is_report_in_progress; } +/** + * cds_is_fatal_event_enabled() - Return if fatal event is enabled + * + * Return true if fatal event is enabled. + */ +bool cds_is_fatal_event_enabled(void) +{ + p_cds_contextType p_cds_context; + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, + "%s: cds context is Invalid", __func__); + return false; + } + + + return p_cds_context->enable_fatal_event; +} + +/** + * cds_get_log_indicator() - Get the log flush indicator + * + * This function is used to get the log flush indicator + * + * Return: log indicator + */ +uint32_t cds_get_log_indicator(void) +{ + p_cds_contextType p_cds_context; + uint32_t indicator; + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, + "%s: cds context is Invalid", __func__); + return WLAN_LOG_INDICATOR_UNUSED; + } + + if (cds_is_load_or_unload_in_progress() || + cds_is_driver_recovering()) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, + "%s: vos context initialization is in progress" + , __func__); + return WLAN_LOG_INDICATOR_UNUSED; + } + + qdf_spinlock_acquire(&p_cds_context->bug_report_lock); + indicator = p_cds_context->log_complete.indicator; + qdf_spinlock_release(&p_cds_context->bug_report_lock); + return indicator; +} + +/** + * cds_wlan_flush_host_logs_for_fatal() - Wrapper to flush host logs + * + * This function is used to send signal to the logger thread to + * flush the host logs. + * + * Return: None + * + */ +void cds_wlan_flush_host_logs_for_fatal(void) +{ + wlan_flush_host_logs_for_fatal(); +} + /** * cds_flush_logs() - Report fatal event to userspace * @is_fatal: Indicates if the event triggering bug report is fatal or not * @indicator: Source which trigerred the bug report * @reason_code: Reason for triggering bug report + * @dump_mac_trace: If mac trace are needed in logs. + * @recovery_needed: If recovery is needed after bug report * * This function sets the log related params and send the WMI command to the * FW to flush its logs. On receiving the flush completion event from the FW @@ -2014,7 +2099,9 @@ bool cds_is_log_report_in_progress(void) */ QDF_STATUS cds_flush_logs(uint32_t is_fatal, uint32_t indicator, - uint32_t reason_code) + uint32_t reason_code, + bool dump_mac_trace, + bool recovery_needed) { uint32_t ret; QDF_STATUS status; @@ -2027,6 +2114,17 @@ QDF_STATUS cds_flush_logs(uint32_t is_fatal, "%s: cds context is Invalid", __func__); return QDF_STATUS_E_FAILURE; } + if (!p_cds_context->enable_fatal_event) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, + "%s: Fatal event not enabled", __func__); + return QDF_STATUS_E_FAILURE; + } + if (cds_is_load_or_unload_in_progress() || + cds_is_driver_recovering()) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, + "%s: un/Load/SSR in progress", __func__); + return QDF_STATUS_E_FAILURE; + } if (cds_is_log_report_in_progress() == true) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, @@ -2035,17 +2133,26 @@ QDF_STATUS cds_flush_logs(uint32_t is_fatal, return QDF_STATUS_E_FAILURE; } - status = cds_set_log_completion(is_fatal, indicator, reason_code); + status = cds_set_log_completion(is_fatal, indicator, + reason_code, recovery_needed); if (QDF_STATUS_SUCCESS != status) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: Failed to set log trigger params", __func__); return QDF_STATUS_E_FAILURE; } - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: Triggering bug report: type:%d, indicator=%d reason_code=%d", __func__, is_fatal, indicator, reason_code); + if (dump_mac_trace) + qdf_trace_dump_all(p_cds_context->pMACContext, 0, 0, 500, 0); + + if (WLAN_LOG_INDICATOR_HOST_ONLY == indicator) { + cds_wlan_flush_host_logs_for_fatal(); + return QDF_STATUS_SUCCESS; + } + ret = sme_send_flush_logs_cmd_to_fw(p_cds_context->pMACContext); if (0 != ret) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, @@ -2070,3 +2177,23 @@ void cds_logging_set_fw_flush_complete(void) { wlan_logging_set_fw_flush_complete(); } + +/** + * cds_set_fatal_event() - set fatal event status + * @value: pending statue to set + * + * Return: None + */ +void cds_set_fatal_event(bool value) +{ + p_cds_contextType p_cds_context; + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, + "%s: cds context is Invalid", __func__); + return; + } + p_cds_context->enable_fatal_event = value; +} + diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 70d4ad6309..fd581b48f6 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -2995,6 +2995,15 @@ enum dot11p_mode { #define CFG_ROAM_DENSE_MIN_APS_MAX (5) #define CFG_ROAM_DENSE_MIN_APS_DEFAULT (1) +/* + * Enable/Disable to initiate BUG report in case of fatal event + * Default: Enable + */ +#define CFG_ENABLE_FATAL_EVENT_TRIGGER "gEnableFatalEvent" +#define CFG_ENABLE_FATAL_EVENT_TRIGGER_MIN (0) +#define CFG_ENABLE_FATAL_EVENT_TRIGGER_MAX (1) +#define CFG_ENABLE_FATAL_EVENT_TRIGGER_DEFAULT (1) + /*--------------------------------------------------------------------------- Type declarations -------------------------------------------------------------------------*/ @@ -3595,6 +3604,7 @@ struct hdd_config { uint32_t roam_dense_rssi_thresh_offset; bool ignore_peer_ht_opmode; uint32_t roam_dense_min_aps; + bool enable_fatal_event; }; #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var)) diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 5bbae4c696..23513f5677 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -3772,6 +3772,15 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_ROAM_DENSE_MIN_APS_MIN, CFG_ROAM_DENSE_MIN_APS_MAX), + REG_VARIABLE(CFG_ENABLE_FATAL_EVENT_TRIGGER, WLAN_PARAM_Integer, + struct hdd_config, enable_fatal_event, + VAR_FLAGS_OPTIONAL | + VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_FATAL_EVENT_TRIGGER_DEFAULT, + CFG_ENABLE_FATAL_EVENT_TRIGGER_MIN, + CFG_ENABLE_FATAL_EVENT_TRIGGER_MAX), + + }; @@ -5362,6 +5371,9 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) hdd_info("Name = [%s] Value = [%u]", CFG_IGNORE_PEER_HT_MODE_NAME, pHddCtx->config->ignore_peer_ht_opmode); + hdd_info("Name = [%s] Value = [%u]", + CFG_ENABLE_FATAL_EVENT_TRIGGER, + pHddCtx->config->enable_fatal_event); hdd_info("Name = [%s] Value = [%u]", CFG_ROAM_DENSE_MIN_APS, pHddCtx->config->roam_dense_min_aps); @@ -6808,6 +6820,8 @@ QDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) pHddCtx->config->obss_passive_dwelltime; smeConfig->csrConfig.ignore_peer_ht_opmode = pConfig->ignore_peer_ht_opmode; + smeConfig->csrConfig.enable_fatal_event = + pConfig->enable_fatal_event; status = sme_update_config(pHddCtx->hHal, smeConfig); if (!QDF_IS_STATUS_SUCCESS(status)) { diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index c8af93844f..cc8427103c 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -3563,7 +3563,8 @@ static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy, status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL, WLAN_LOG_INDICATOR_FRAMEWORK, - WLAN_LOG_REASON_CODE_UNUSED); + WLAN_LOG_REASON_CODE_UNUSED, + true, false); if (QDF_STATUS_SUCCESS != status) { hddLog(LOGE, FL("Failed to trigger bug report")); return -EINVAL; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 6722d46778..552f7c9e04 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -5355,6 +5355,8 @@ hdd_context_t *hdd_init_context(struct device *dev, void *hif_sc) hdd_notice("Setting configuredMcastBcastFilter: %d", hdd_ctx->config->mcastBcastFilterSetting); + cds_set_fatal_event(hdd_ctx->config->enable_fatal_event); + hdd_override_ini_config(hdd_ctx); ret = wlan_hdd_cfg80211_init(dev, hdd_ctx->wiphy, hdd_ctx->config); diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index 24f572a0e9..ebdb11f0bf 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -319,6 +319,10 @@ void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter) hddLog(LOGE, "%s: timeout waiting for remain on channel ready indication", __func__); + cds_flush_logs(WLAN_LOG_TYPE_FATAL, + WLAN_LOG_INDICATOR_HOST_DRIVER, + WLAN_LOG_REASON_HDD_TIME_OUT, + true, false); } INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var); @@ -1171,6 +1175,10 @@ int __wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, cds_get_driver_state()); return -EAGAIN; } + cds_flush_logs(WLAN_LOG_TYPE_FATAL, + WLAN_LOG_INDICATOR_HOST_DRIVER, + WLAN_LOG_REASON_HDD_TIME_OUT, + true, false); } INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var); /* Issue abort remain on chan request to sme. diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index 878bf0f059..afc1fd62e4 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -3983,7 +3983,11 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, cds_get_driver_state()); return -EAGAIN; } - + if (rc <= 0) + cds_flush_logs(WLAN_LOG_TYPE_FATAL, + WLAN_LOG_INDICATOR_HOST_DRIVER, + WLAN_LOG_REASON_HDD_TIME_OUT, + true, false); pAdapter->mgmtTxCompletionStatus = false; return -EINVAL; } diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h index 8f68465306..05430a9bb9 100644 --- a/core/mac/inc/ani_global.h +++ b/core/mac/inc/ani_global.h @@ -131,6 +131,7 @@ enum log_event_type { * @WLAN_LOG_INDICATOR_FRAMEWORK: Framework triggers bug report * @WLAN_LOG_INDICATOR_HOST_DRIVER: Host driver triggers bug report * @WLAN_LOG_INDICATOR_FIRMWARE: FW initiates bug report + * @WLAN_LOG_INDICATOR_HOST_ONLY: Host triggers fatal event bug report * * Enum indicating the module that triggered the bug report */ @@ -139,52 +140,39 @@ enum log_event_indicator { WLAN_LOG_INDICATOR_FRAMEWORK, WLAN_LOG_INDICATOR_HOST_DRIVER, WLAN_LOG_INDICATOR_FIRMWARE, + WLAN_LOG_INDICATOR_HOST_ONLY, }; /** * enum log_event_host_reason_code - Reason code for bug report * @WLAN_LOG_REASON_CODE_UNUSED: Unused - * @WLAN_LOG_REASON_COMMAND_UNSUCCESSFUL: Command response status from FW - * is error * @WLAN_LOG_REASON_ROAM_FAIL: Driver initiated roam has failed - * @WLAN_LOG_REASON_THREAD_STUCK: Monitor Health of host threads and report - * fatal event if some thread is stuck * @WLAN_LOG_REASON_DATA_STALL: Unable to send/receive data due to low resource * scenario for a prolonged period * @WLAN_LOG_REASON_SME_COMMAND_STUCK: SME command is stuck in SME active queue - * @WLAN_LOG_REASON_ZERO_SCAN_RESULTS: Full scan resulted in zero scan results * @WLAN_LOG_REASON_QUEUE_FULL: Defer queue becomes full for a prolonged period * @WLAN_LOG_REASON_POWER_COLLAPSE_FAIL: Unable to allow apps power collapse * for a prolonged period - * @WLAN_LOG_REASON_SSR_FAIL: Unable to gracefully complete SSR - * @WLAN_LOG_REASON_DISCONNECT_FAIL: Disconnect from Supplicant is not - * successful - * @WLAN_LOG_REASON_CLEAN_UP_FAIL: Clean up of TDLS or Pre-Auth Sessions - * not successful * @WLAN_LOG_REASON_MALLOC_FAIL: Memory allocation Fails * @WLAN_LOG_REASON_VOS_MSG_UNDER_RUN: VOS Core runs out of message wrapper - * @WLAN_LOG_REASON_MSG_POST_FAIL: Unable to post msg - * + * @WLAN_LOG_REASON_HDD_TIME_OUT: Wait for event Timeout in HDD layer + @WLAN_LOG_REASON_SME_OUT_OF_CMD_BUFL sme out of cmd buffer * This enum contains the different reason codes for bug report */ enum log_event_host_reason_code { WLAN_LOG_REASON_CODE_UNUSED, - WLAN_LOG_REASON_COMMAND_UNSUCCESSFUL, WLAN_LOG_REASON_ROAM_FAIL, - WLAN_LOG_REASON_THREAD_STUCK, WLAN_LOG_REASON_DATA_STALL, WLAN_LOG_REASON_SME_COMMAND_STUCK, - WLAN_LOG_REASON_ZERO_SCAN_RESULTS, WLAN_LOG_REASON_QUEUE_FULL, WLAN_LOG_REASON_POWER_COLLAPSE_FAIL, - WLAN_LOG_REASON_SSR_FAIL, - WLAN_LOG_REASON_DISCONNECT_FAIL, - WLAN_LOG_REASON_CLEAN_UP_FAIL, WLAN_LOG_REASON_MALLOC_FAIL, WLAN_LOG_REASON_VOS_MSG_UNDER_RUN, - WLAN_LOG_REASON_MSG_POST_FAIL, + WLAN_LOG_REASON_HDD_TIME_OUT, + WLAN_LOG_REASON_SME_OUT_OF_CMD_BUF, }; + /** * enum userspace_log_level - Log level at userspace * @LOG_LEVEL_NO_COLLECTION: verbose_level 0 corresponds to no collection diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 45265686cd..3dbf1ff563 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -868,6 +868,10 @@ uint8_t lim_write_deferred_msg_q(tpAniSirGlobal mac_ctx, tpSirMsgQ lim_msg) FL("queue->MsgQ full Msg:%d Msgs Failed:%d"), lim_msg->type, ++mac_ctx->lim.deferredMsgCnt); + cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL, + WLAN_LOG_INDICATOR_HOST_DRIVER, + WLAN_LOG_REASON_QUEUE_FULL, + true, false); } else { mac_ctx->lim.deferredMsgCnt++; } diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index dd566f26ed..3071a777c1 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1221,6 +1221,7 @@ typedef struct tagCsrConfigParam { uint32_t obss_active_dwelltime; uint32_t obss_passive_dwelltime; bool ignore_peer_ht_opmode; + bool enable_fatal_event; } tCsrConfigParam; /* Tush */ diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 15ce478fd6..4ed2c5597b 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -639,6 +639,7 @@ typedef struct tagCsrConfig { uint32_t obss_active_dwelltime; uint32_t obss_passive_dwelltime; bool ignore_peer_ht_opmode; + bool enable_fatal_event; } tCsrConfig; typedef struct tagCsrChannelPowerInfo { diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 06ba472c1d..c691401beb 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -621,8 +621,16 @@ tSmeCmd *sme_get_command_buffer(tpAniSirGlobal pMac) sme_command_queue_full++; csr_ll_unlock(&pMac->roam.roamCmdPendingList); - /* panic with out-of-command */ - QDF_BUG(0); + if (pMac->roam.configParam.enable_fatal_event) + cds_flush_logs(WLAN_LOG_TYPE_FATAL, + WLAN_LOG_INDICATOR_HOST_DRIVER, + WLAN_LOG_REASON_SME_OUT_OF_CMD_BUF, + false, + pMac->sme.enableSelfRecovery ? true : false); + else if (pMac->sme.enableSelfRecovery) + cds_trigger_recovery(); + else + QDF_BUG(0); } /* memset to zero */ @@ -11682,19 +11690,41 @@ void sme_save_active_cmd_stats(tHalHandle hHal) void active_list_cmd_timeout_handle(void *userData) { - if (NULL == userData) - return; - QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, - "%s: Active List command timeout Cmd List Count %d", __func__, - csr_ll_count(&((tpAniSirGlobal) userData)->sme. - smeCmdActiveList)); - sme_get_command_q_status((tHalHandle) userData); + tHalHandle hal = (tHalHandle)userData; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); - if (((tpAniSirGlobal) userData)->sme.enableSelfRecovery) { - sme_save_active_cmd_stats((tHalHandle) userData); + if (NULL == mac_ctx) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + "%s: mac_ctx is null", __func__); + return; + } + /* Return if no cmd pending in active list as + * in this case we should not be here. + */ + if (0 == csr_ll_count(&mac_ctx->sme.smeCmdActiveList)) + return; + sms_log(mac_ctx, LOGE, + FL("Active List command timeout Cmd List Count %d"), + csr_ll_count(&mac_ctx->sme.smeCmdActiveList)); + sme_get_command_q_status(hal); + + if (mac_ctx->roam.configParam.enable_fatal_event) + cds_flush_logs(WLAN_LOG_TYPE_FATAL, + WLAN_LOG_INDICATOR_HOST_DRIVER, + WLAN_LOG_REASON_SME_COMMAND_STUCK, + false, + mac_ctx->sme.enableSelfRecovery ? true : false); + else + qdf_trace_dump_all(mac_ctx, 0, 0, 500, 0); + + if (mac_ctx->sme.enableSelfRecovery) { + sme_save_active_cmd_stats(hal); cds_trigger_recovery(); } else { - QDF_BUG(0); + if (!mac_ctx->roam.configParam.enable_fatal_event && + !(cds_is_load_or_unload_in_progress() || + cds_is_driver_recovering())) + QDF_BUG(0); } } diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 342ff292a2..d0b29e2129 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -2353,6 +2353,8 @@ QDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, pParam->early_stop_scan_min_threshold; pMac->roam.configParam.early_stop_scan_max_threshold = pParam->early_stop_scan_max_threshold; + pMac->roam.configParam.enable_fatal_event = + pParam->enable_fatal_event; } return status; @@ -2536,6 +2538,8 @@ QDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam) pParam->enableHtSmps = pMac->roam.configParam.enableHtSmps; pParam->htSmps = pMac->roam.configParam.htSmps; pParam->send_smps_action = pMac->roam.configParam.send_smps_action; + pParam->enable_fatal_event = + pMac->roam.configParam.enable_fatal_event; return QDF_STATUS_SUCCESS; } @@ -8672,6 +8676,10 @@ static void csr_roam_roaming_state_reassoc_rsp_processor(tpAniSirGlobal pMac, "CSR SmeReassocReq failed with statusCode= 0x%08X [%d]", pSmeJoinRsp->statusCode, pSmeJoinRsp->statusCode); result = eCsrReassocFailure; + cds_flush_logs(WLAN_LOG_TYPE_FATAL, + WLAN_LOG_INDICATOR_HOST_DRIVER, + WLAN_LOG_REASON_ROAM_FAIL, + true, false); if ((eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE == pSmeJoinRsp->statusCode) || (eSIR_SME_FT_REASSOC_FAILURE == diff --git a/core/utils/logging/inc/wlan_logging_sock_svc.h b/core/utils/logging/inc/wlan_logging_sock_svc.h index 1850a01384..d0b76d1aed 100644 --- a/core/utils/logging/inc/wlan_logging_sock_svc.h +++ b/core/utils/logging/inc/wlan_logging_sock_svc.h @@ -46,6 +46,7 @@ int wlan_log_to_user(QDF_TRACE_LEVEL log_level, char *to_be_sent, int length); void wlan_logging_set_per_pkt_stats(void); void wlan_logging_set_log_level(void); void wlan_logging_set_fw_flush_complete(void); +void wlan_flush_host_logs_for_fatal(void); #ifdef FEATURE_WLAN_DIAG_SUPPORT void wlan_report_log_completion(uint32_t is_fatal, uint32_t indicator, @@ -57,5 +58,9 @@ static inline void wlan_report_log_completion(uint32_t is_fatal, { return; } +static inline void wlan_flush_host_logs_for_fatal(void) +{ +} + #endif /* FEATURE_WLAN_DIAG_SUPPORT */ #endif /* WLAN_LOGGING_SOCK_SVC_H */ diff --git a/core/utils/logging/src/wlan_logging_sock_svc.c b/core/utils/logging/src/wlan_logging_sock_svc.c index 15687a2f7e..c0c854f05b 100644 --- a/core/utils/logging/src/wlan_logging_sock_svc.c +++ b/core/utils/logging/src/wlan_logging_sock_svc.c @@ -39,6 +39,7 @@ #include #include "pktlog_ac.h" #include +#include "cds_utils.h" #define LOGGING_TRACE(level, args ...) \ QDF_TRACE(QDF_MODULE_ID_HDD, level, ## args) @@ -505,14 +506,19 @@ void wlan_report_log_completion(uint32_t is_fatal, void send_flush_completion_to_user(void) { uint32_t is_fatal, indicator, reason_code; + bool recovery_needed; - cds_get_log_completion(&is_fatal, &indicator, &reason_code); + cds_get_and_reset_log_completion(&is_fatal, + &indicator, &reason_code, &recovery_needed); /* Error on purpose, so that it will get logged in the kmsg */ LOGGING_TRACE(QDF_TRACE_LEVEL_ERROR, "%s: Sending flush done to userspace", __func__); wlan_report_log_completion(is_fatal, indicator, reason_code); + + if (recovery_needed) + cds_trigger_recovery(); } /** @@ -525,6 +531,7 @@ static int wlan_logging_thread(void *Arg) { int ret_wait_status = 0; int ret = 0; + unsigned long flags; set_user_nice(current, -2); @@ -561,6 +568,10 @@ static int wlan_logging_thread(void *Arg) ret = send_filled_buffers_to_user(); if (-ENOMEM == ret) msleep(200); + if (WLAN_LOG_INDICATOR_HOST_ONLY == + cds_get_log_indicator()) { + send_flush_completion_to_user(); + } } if (test_and_clear_bit(HOST_LOG_PER_PKT_STATS, @@ -582,6 +593,12 @@ static int wlan_logging_thread(void *Arg) send_flush_completion_to_user(); } else { gwlan_logging.is_flush_complete = true; + /* Flush all current host logs*/ + spin_lock_irqsave(&gwlan_logging.spin_lock, + flags); + wlan_queue_logmsg_for_app(); + spin_unlock_irqrestore(&gwlan_logging.spin_lock, + flags); set_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); set_bit(HOST_LOG_PER_PKT_STATS, @@ -804,10 +821,35 @@ void wlan_logging_set_log_level(void) */ void wlan_logging_set_fw_flush_complete(void) { - if (gwlan_logging.is_active == false) + if (gwlan_logging.is_active == false || + !cds_is_fatal_event_enabled()) return; set_bit(HOST_LOG_FW_FLUSH_COMPLETE, &gwlan_logging.eventFlag); wake_up_interruptible(&gwlan_logging.wait_queue); } + +/** + * wlan_flush_host_logs_for_fatal() - Flush host logs + * + * This function is used to send signal to the logger thread to + * Flush the host logs + * + * Return: None + */ +void wlan_flush_host_logs_for_fatal(void) +{ + unsigned long flags; + + if (cds_is_log_report_in_progress()) { + pr_info("%s:flush all host logs Setting HOST_LOG_POST_MASK\n", + __func__); + spin_lock_irqsave(&gwlan_logging.spin_lock, flags); + wlan_queue_logmsg_for_app(); + spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); + set_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); + wake_up_interruptible(&gwlan_logging.wait_queue); + } +} + #endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */ diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index d679a6f9b0..d068183616 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -2269,7 +2269,7 @@ static int wma_flush_complete_evt_handler(void *handle, reason_code); status = cds_set_log_completion(WLAN_LOG_TYPE_FATAL, WLAN_LOG_INDICATOR_FIRMWARE, - reason_code); + reason_code, false); if (QDF_STATUS_SUCCESS != status) { WMA_LOGE("%s: Failed to set log trigger params", __func__);