Bläddra i källkod

qcacld-3.0: Send TX timeout event for TX data stall

For data stall continuous HDD tx timeout count of five
post HOST TX time out data stall event to handle it in
data detection module.

Change-Id: Ic6cf5e62f711cef5919a4a5e85e4232c622c04bb
CRs-Fixed: 2094393
Sravan Kumar Kairam 7 år sedan
förälder
incheckning
3a69831d44

+ 8 - 0
core/hdd/inc/wlan_hdd_main.h

@@ -127,6 +127,9 @@
 #else
 #define HDD_TX_TIMEOUT          msecs_to_jiffies(5000)
 #endif
+
+#define HDD_TX_STALL_THRESHOLD 4
+
 /** Hdd Default MTU */
 #define HDD_DEFAULT_MTU         (1500)
 
@@ -446,6 +449,11 @@ struct hdd_tx_rx_stats {
 	__u32    txflow_pause_cnt;
 	__u32    txflow_unpause_cnt;
 	__u32    txflow_timer_cnt;
+
+	/*tx timeout stats*/
+	__u32 tx_timeout_cnt;
+	__u32 cont_txtimeout_cnt;
+	u64 jiffies_last_txtimeout;
 };
 
 #ifdef WLAN_FEATURE_11W

+ 3 - 0
core/hdd/src/wlan_hdd_assoc.c

@@ -1780,6 +1780,9 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter,
 				adapter->sessionId);
 	}
 	wlan_hdd_clear_link_layer_stats(adapter);
+
+	adapter->hdd_stats.hddTxRxStats.cont_txtimeout_cnt = 0;
+
 	/* Unblock anyone waiting for disconnect to complete */
 	complete(&adapter->disconnect_comp_var);
 

+ 19 - 26
core/hdd/src/wlan_hdd_softap_tx_rx.c

@@ -45,7 +45,7 @@
 #include <cdp_txrx_peer_ops.h>
 #include <cds_utils.h>
 #include <cdp_txrx_flow_ctrl_v2.h>
-#include <cdp_txrx_handle.h>
+#include <cdp_txrx_misc.h>
 #include <wlan_hdd_object_manager.h>
 #include "wlan_p2p_ucfg_api.h"
 #ifdef IPA_OFFLOAD
@@ -293,6 +293,8 @@ static int __hdd_softap_hard_start_xmit(struct sk_buff *skb,
 	uint32_t num_seg;
 
 	++adapter->hdd_stats.hddTxRxStats.txXmitCalled;
+	adapter->hdd_stats.hddTxRxStats.cont_txtimeout_cnt = 0;
+
 	/* Prevent this function from being called during SSR since TL
 	 * context may not be reinitialized at this time which may
 	 * lead to a crash.
@@ -503,30 +505,6 @@ int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	return ret;
 }
 
-#ifdef FEATURE_WLAN_DIAG_SUPPORT
-/**
- * hdd_wlan_datastall_sap_event()- Send SAP datastall information
- *
- * This Function send send SAP datastall diag event
- *
- * Return: void.
- */
-static void hdd_wlan_datastall_sap_event(void)
-{
-	WLAN_HOST_DIAG_EVENT_DEF(sap_data_stall,
-					struct host_event_wlan_datastall);
-	qdf_mem_zero(&sap_data_stall, sizeof(sap_data_stall));
-	sap_data_stall.reason = SOFTAP_TX_TIMEOUT;
-	WLAN_HOST_DIAG_EVENT_REPORT(&sap_data_stall,
-						EVENT_WLAN_SOFTAP_DATASTALL);
-}
-#else
-static inline void hdd_wlan_datastall_sap_event(void)
-{
-
-}
-#endif
-
 /**
  * __hdd_softap_tx_timeout() - TX timeout handler
  * @dev: pointer to network device
@@ -542,6 +520,7 @@ static void __hdd_softap_tx_timeout(struct net_device *dev)
 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
 	struct hdd_context *hdd_ctx;
 	struct netdev_queue *txq;
+	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
 	int i;
 
 	DPTRACE(qdf_dp_trace(NULL, QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT,
@@ -574,7 +553,21 @@ static void __hdd_softap_tx_timeout(struct net_device *dev)
 	cdp_dump_flow_pool_info(cds_get_context(QDF_MODULE_ID_SOC));
 	QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_DEBUG,
 			"carrier state: %d", netif_carrier_ok(dev));
-	hdd_wlan_datastall_sap_event();
+
+	++adapter->hdd_stats.hddTxRxStats.tx_timeout_cnt;
+	++adapter->hdd_stats.hddTxRxStats.cont_txtimeout_cnt;
+
+	if (adapter->hdd_stats.hddTxRxStats.cont_txtimeout_cnt >
+	    HDD_TX_STALL_THRESHOLD) {
+		QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
+			  "Detected data stall due to continuous TX timeouts");
+		adapter->hdd_stats.hddTxRxStats.cont_txtimeout_cnt = 0;
+		cdp_post_data_stall_event(soc,
+					  DATA_STALL_LOG_INDICATOR_HOST_DRIVER,
+					  DATA_STALL_LOG_HOST_SOFTAP_TX_TIMEOUT,
+					  0xFF, 0xFF,
+					  DATA_STALL_LOG_RECOVERY_TRIGGER_PDR);
+	}
 }
 
 /**

+ 44 - 24
core/hdd/src/wlan_hdd_tx_rx.c

@@ -60,7 +60,7 @@
 #include <cdp_txrx_flow_ctrl_v2.h>
 #include "wlan_hdd_nan_datapath.h"
 #include "pld_common.h"
-#include <cdp_txrx_handle.h>
+#include <cdp_txrx_misc.h>
 #include "wlan_hdd_rx_monitor.h"
 #include "wlan_hdd_power.h"
 #include <wlan_hdd_tsf.h>
@@ -583,6 +583,8 @@ static int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 #endif
 
 	++adapter->hdd_stats.hddTxRxStats.txXmitCalled;
+	adapter->hdd_stats.hddTxRxStats.cont_txtimeout_cnt = 0;
+
 	if (cds_is_driver_recovering() || cds_is_driver_in_bad_state()) {
 		QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_INFO_HIGH,
 			"Recovery in progress, dropping the packet");
@@ -849,28 +851,6 @@ QDF_STATUS hdd_get_peer_sta_id(struct hdd_station_ctx *sta_ctx,
 	return QDF_STATUS_E_FAILURE;
 }
 
-#ifdef FEATURE_WLAN_DIAG_SUPPORT
-/**
- * hdd_wlan_datastall_sta_event()- send sta datastall information
- *
- * This Function send send sta datastall status diag event
- *
- * Return: void.
- */
-static void hdd_wlan_datastall_sta_event(void)
-{
-	WLAN_HOST_DIAG_EVENT_DEF(sta_data_stall,
-				struct host_event_wlan_datastall);
-	qdf_mem_zero(&sta_data_stall, sizeof(sta_data_stall));
-	sta_data_stall.reason = STA_TX_TIMEOUT;
-	WLAN_HOST_DIAG_EVENT_REPORT(&sta_data_stall, EVENT_WLAN_STA_DATASTALL);
-}
-#else
-static inline void hdd_wlan_datastall_sta_event(void)
-{
-}
-#endif
-
 /**
  * __hdd_tx_timeout() - TX timeout handler
  * @dev: pointer to network device
@@ -886,6 +866,8 @@ static void __hdd_tx_timeout(struct net_device *dev)
 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
 	struct hdd_context *hdd_ctx;
 	struct netdev_queue *txq;
+	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
+	u64 diff_jiffies;
 	int i = 0;
 
 	TX_TIMEOUT_TRACE(dev, QDF_MODULE_ID_HDD_DATA);
@@ -912,7 +894,45 @@ static void __hdd_tx_timeout(struct net_device *dev)
 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 	wlan_hdd_display_netif_queue_history(hdd_ctx);
 	cdp_dump_flow_pool_info(cds_get_context(QDF_MODULE_ID_SOC));
-	hdd_wlan_datastall_sta_event();
+
+	++adapter->hdd_stats.hddTxRxStats.tx_timeout_cnt;
+	++adapter->hdd_stats.hddTxRxStats.cont_txtimeout_cnt;
+
+	diff_jiffies = jiffies -
+		       adapter->hdd_stats.hddTxRxStats.jiffies_last_txtimeout;
+
+	if ((adapter->hdd_stats.hddTxRxStats.cont_txtimeout_cnt > 1) &&
+	    (diff_jiffies > (HDD_TX_TIMEOUT * 2))) {
+		/*
+		 * In case when there is no traffic is running, it may
+		 * possible tx time-out may once happen and later system
+		 * recovered then continuous tx timeout count has to be
+		 * reset as it is gets modified only when traffic is running.
+		 * If over a period of time if this count reaches to threshold
+		 * then host triggers a false subsystem restart. In genuine
+		 * time out case kernel will call the tx time-out back to back
+		 * at interval of HDD_TX_TIMEOUT. Here now check if previous
+		 * TX TIME out has occurred more than twice of HDD_TX_TIMEOUT
+		 * back then host may recovered here from data stall.
+		 */
+		adapter->hdd_stats.hddTxRxStats.cont_txtimeout_cnt = 0;
+		QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_DEBUG,
+			  "Reset continous tx timeout stat");
+	}
+
+	adapter->hdd_stats.hddTxRxStats.jiffies_last_txtimeout = jiffies;
+
+	if (adapter->hdd_stats.hddTxRxStats.cont_txtimeout_cnt >
+	    HDD_TX_STALL_THRESHOLD) {
+		QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
+			  "Data stall due to continuous TX timeouts");
+		adapter->hdd_stats.hddTxRxStats.cont_txtimeout_cnt = 0;
+		cdp_post_data_stall_event(soc,
+					  DATA_STALL_LOG_INDICATOR_HOST_DRIVER,
+					  DATA_STALL_LOG_HOST_STA_TX_TIMEOUT,
+					  0xFF, 0xFF,
+					  DATA_STALL_LOG_RECOVERY_TRIGGER_PDR);
+	}
 }
 
 /**