Sfoglia il codice sorgente

qcacld-3.0: Add scenario based BUG report

qcacld-2.0 to qcacld-3.0 propagation

Change to initiate BUG report in case of fatal event
Add INI support to Enable/Disable it.

The fatal event handled are as below:
 - Roaming failed after successful preauth.
 - SME command timeout.
 - PE defer queue is full.
 - CDS run out of message wrapper.
 - HDD level wait for event timeout.

CRs-Fixed: 912560
Change-Id: I64dff8b7d0836340ce3bec5f5985d1919b600c23
Abhishek Singh 9 anni fa
parent
commit
5ea86536ef

+ 13 - 4
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

+ 3 - 0
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;
 
 /*---------------------------------------------------------------------------

+ 136 - 9
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;
+}
+

+ 10 - 0
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))

+ 14 - 0
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)) {

+ 2 - 1
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;

+ 2 - 0
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);

+ 8 - 0
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.

+ 5 - 1
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;
 	}

+ 7 - 19
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

+ 4 - 0
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++;
 		}

+ 1 - 0
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 */

+ 1 - 0
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 {

+ 42 - 12
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);
 	}
 }
 

+ 8 - 0
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 ==

+ 5 - 0
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 */

+ 44 - 2
core/utils/logging/src/wlan_logging_sock_svc.c

@@ -39,6 +39,7 @@
 #include <wlan_ptt_sock_svc.h>
 #include "pktlog_ac.h"
 #include <host_diag_core_event.h>
+#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 */

+ 1 - 1
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__);