Jelajahi Sumber

qca-wifi: Fix for tx capture softlockup on mode change

In tx capture, while changing the tx capture we run into
soft lock up. The fix addressed the soft lock up issue.

Change-Id: I0cb6abb9ede2fb0a5d380e6986ec14dcaa31a13f
nobelj 5 tahun lalu
induk
melakukan
c42f615d91
2 mengubah file dengan 75 tambahan dan 22 penghapusan
  1. 74 22
      dp/wifi3.0/dp_tx_capture.c
  2. 1 0
      dp/wifi3.0/dp_tx_capture.h

+ 74 - 22
dp/wifi3.0/dp_tx_capture.c

@@ -525,7 +525,7 @@ bool is_dp_peer_mgmt_pkt_filter(struct dp_pdev *pdev,
 	bool found = false;
 
 	found = dp_peer_tx_cap_search(pdev, peer_id, mac_addr);
-	QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE, QDF_TRACE_LEVEL_INFO_LOW,
+	QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE, QDF_TRACE_LEVEL_INFO_HIGH,
 		  "%s: %d peer_id[%d] mac_addr[%pM] found[%d]!",
 		  __func__, __LINE__, peer_id, mac_addr, found);
 
@@ -545,6 +545,7 @@ void dp_tx_ppdu_stats_attach(struct dp_pdev *pdev)
 	int i, j;
 
 	tx_capture = &pdev->tx_capture;
+	tx_capture->tx_cap_mode_flag = true;
 	/* Work queue setup for HTT stats and tx capture handling */
 	qdf_create_work(0, &pdev->tx_capture.ppdu_stats_work,
 			dp_tx_ppdu_stats_process,
@@ -936,6 +937,44 @@ static void  dp_iterate_free_peer_msdu_q(void *pdev_hdl)
 	qdf_spin_unlock_bh(&soc->peer_ref_mutex);
 }
 
+/*
+ * dp_enh_tx_capture_disable()- API to disable enhanced tx capture
+ * @pdev_handle: DP_PDEV handle
+ *
+ * Return: void
+ */
+void
+dp_enh_tx_capture_disable(struct dp_pdev *pdev)
+{
+	int i, j;
+
+	dp_soc_set_txrx_ring_map(pdev->soc);
+	dp_h2t_cfg_stats_msg_send(pdev,
+				  DP_PPDU_STATS_CFG_ENH_STATS,
+				  pdev->pdev_id);
+	dp_iterate_free_peer_msdu_q(pdev);
+	for (i = 0; i < TXCAP_MAX_TYPE; i++) {
+		for (j = 0; j < TXCAP_MAX_SUBTYPE; j++) {
+			qdf_nbuf_queue_t *retries_q;
+
+			qdf_spin_lock_bh(
+				&pdev->tx_capture.ctl_mgmt_lock[i][j]);
+			qdf_nbuf_queue_free(
+				&pdev->tx_capture.ctl_mgmt_q[i][j]);
+			qdf_spin_unlock_bh(
+				&pdev->tx_capture.ctl_mgmt_lock[i][j]);
+			retries_q = &pdev->tx_capture.retries_ctl_mgmt_q[i][j];
+			if (!qdf_nbuf_is_queue_empty(retries_q))
+				qdf_nbuf_queue_free(retries_q);
+		}
+	}
+	dp_peer_tx_cap_del_all_filter(pdev);
+	pdev->tx_capture.tx_cap_mode_flag = true;
+	QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE, QDF_TRACE_LEVEL_INFO_LOW,
+		  "Mode change request done cur mode - %d\n",
+		  pdev->tx_capture_enabled);
+}
+
 /*
  * dp_config_enh_tx_capture()- API to enable/disable enhanced tx capture
  * @pdev_handle: DP_PDEV handle
@@ -946,10 +985,28 @@ static void  dp_iterate_free_peer_msdu_q(void *pdev_hdl)
 QDF_STATUS
 dp_config_enh_tx_capture(struct dp_pdev *pdev, uint8_t val)
 {
-	int i, j;
-
 	qdf_spin_lock(&pdev->tx_capture.config_lock);
-	pdev->tx_capture_enabled = val;
+	if (pdev->tx_capture.tx_cap_mode_flag) {
+		pdev->tx_capture.tx_cap_mode_flag = false;
+		pdev->tx_capture_enabled = val;
+		QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE, QDF_TRACE_LEVEL_INFO_LOW,
+			  "Mode change requested - %d\n",
+			  pdev->tx_capture_enabled);
+	} else if (!pdev->tx_capture.tx_cap_mode_flag &&
+		   !val && !!pdev->tx_capture_enabled) {
+		/* here the val is always 0 which is disable */
+		pdev->tx_capture_enabled = val;
+		pdev->tx_capture.tx_cap_mode_flag = false;
+		QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE, QDF_TRACE_LEVEL_INFO_LOW,
+			  "Mode change requested - %d\n",
+			  pdev->tx_capture_enabled);
+	} else {
+		QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE, QDF_TRACE_LEVEL_INFO_LOW,
+			  "Mode change request pending prev mode - %d\n",
+			  pdev->tx_capture_enabled);
+		qdf_spin_unlock(&pdev->tx_capture.config_lock);
+		return QDF_STATUS_E_BUSY;
+	}
 
 	if (pdev->tx_capture_enabled == CDP_TX_ENH_CAPTURE_ENABLE_ALL_PEERS ||
 	    pdev->tx_capture_enabled == CDP_TX_ENH_CAPTURE_ENDIS_PER_PEER) {
@@ -958,26 +1015,13 @@ dp_config_enh_tx_capture(struct dp_pdev *pdev, uint8_t val)
 			dp_h2t_cfg_stats_msg_send(pdev,
 						  DP_PPDU_STATS_CFG_SNIFFER,
 						  pdev->pdev_id);
-	} else {
-		dp_soc_set_txrx_ring_map(pdev->soc);
-		dp_h2t_cfg_stats_msg_send(pdev,
-					  DP_PPDU_STATS_CFG_ENH_STATS,
-					  pdev->pdev_id);
-		dp_iterate_free_peer_msdu_q(pdev);
-		for (i = 0; i < TXCAP_MAX_TYPE; i++) {
-			for (j = 0; j < TXCAP_MAX_SUBTYPE; j++) {
-				qdf_spin_lock_bh(
-					&pdev->tx_capture.ctl_mgmt_lock[i][j]);
-				qdf_nbuf_queue_free(
-					&pdev->tx_capture.ctl_mgmt_q[i][j]);
-				qdf_spin_unlock_bh(
-					&pdev->tx_capture.ctl_mgmt_lock[i][j]);
-			}
-		}
-		dp_peer_tx_cap_del_all_filter(pdev);
+		pdev->tx_capture.tx_cap_mode_flag = true;
+		QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE, QDF_TRACE_LEVEL_INFO_LOW,
+			  "Mode change request done cur mode - %d\n",
+			  pdev->tx_capture_enabled);
 	}
-
 	qdf_spin_unlock(&pdev->tx_capture.config_lock);
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -3152,6 +3196,9 @@ void dp_tx_ppdu_stats_process(void *context)
 			/* send WDI event */
 			if (pdev->tx_capture_enabled ==
 			    CDP_TX_ENH_CAPTURE_DISABLED) {
+				if (!pdev->tx_capture.tx_cap_mode_flag)
+					dp_enh_tx_capture_disable(pdev);
+
 				/**
 				 * Deliver PPDU stats only for valid (acked)
 				 * data frames if sniffer mode is not enabled.
@@ -3340,6 +3387,11 @@ dequeue_msdu_again:
 
 		qdf_spin_unlock(&ptr_tx_cap->config_lock);
 		qdf_mem_free(nbuf_ppdu_desc_list);
+
+		qdf_spin_lock(&pdev->tx_capture.config_lock);
+		if (!pdev->tx_capture.tx_cap_mode_flag)
+			dp_enh_tx_capture_disable(pdev);
+		qdf_spin_unlock(&pdev->tx_capture.config_lock);
 	}
 }
 

+ 1 - 0
dp/wifi3.0/dp_tx_capture.h

@@ -71,6 +71,7 @@ struct dp_pdev_tx_capture {
 	uint32_t htt_frame_type[TX_CAP_HTT_MAX_FTYPE];
 	struct cdp_tx_completion_ppdu dummy_ppdu_desc;
 	struct dp_peer_mgmt_list *ptr_peer_mgmt_list;
+	bool tx_cap_mode_flag;
 };
 
 /* Tx TID */