Browse Source

qcacmn: Drain Rx monitor workqueue

Drain Rx monitor workqueue on wifi down

CRs-Fixed: 3186360
Change-Id: I524b08338da1f2a4567c17551a8b44d420ca3455
Amir Patel 3 years ago
parent
commit
0bfdc54393

+ 2 - 1
dp/wifi3.0/monitor/2.0/dp_mon_2.0.c

@@ -93,6 +93,7 @@ QDF_STATUS dp_mon_pdev_ext_deinit_2_0(struct dp_pdev *pdev)
 	if (!mon_pdev_be->rx_mon_workqueue)
 		return QDF_STATUS_E_FAILURE;
 
+	dp_rx_mon_drain_wq(pdev);
 	qdf_flush_workqueue(0, mon_pdev_be->rx_mon_workqueue);
 	qdf_destroy_workqueue(0, mon_pdev_be->rx_mon_workqueue);
 	qdf_flush_work(&mon_pdev_be->rx_mon_work);
@@ -430,7 +431,7 @@ void dp_vdev_set_monitor_mode_buf_rings_2_0(struct dp_pdev *pdev)
 	}
 
 	if (dp_rx_mon_buffers_alloc(soc,
-				    (rx_mon_max_entries - mon_soc_be->tx_mon_ring_fill_level))) {
+				    (rx_mon_max_entries - mon_soc_be->rx_mon_ring_fill_level))) {
 		dp_mon_err("%pK: Rx mon buffers allocation failed", soc);
 		return;
 	}

+ 76 - 4
dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.c

@@ -35,6 +35,70 @@
 #include "dp_lite_mon.h"
 #endif
 
+/**
+ * dp_rx_mon_free_ppdu_info () - Free PPDU info
+ * @pdev: DP pdev
+ * @ppdu_info: PPDU info
+ *
+ * Return: Void
+ */
+static void
+dp_rx_mon_free_ppdu_info(struct dp_pdev *pdev,
+			 struct hal_rx_ppdu_info *ppdu_info)
+{
+	uint8_t user;
+
+	for (user = 0; user < ppdu_info->com_info.num_users; user++) {
+		uint16_t mpdu_count  = ppdu_info->mpdu_count[user];
+		uint16_t mpdu_idx;
+		qdf_nbuf_t mpdu;
+
+		for (mpdu_idx = 0; mpdu_idx < mpdu_count; mpdu_idx++) {
+			mpdu = (qdf_nbuf_t)ppdu_info->mpdu_q[user][mpdu_idx];
+
+			if (!mpdu)
+				continue;
+			qdf_nbuf_free(mpdu);
+		}
+	}
+}
+
+void dp_rx_mon_drain_wq(struct dp_pdev *pdev)
+{
+	struct dp_mon_pdev *mon_pdev;
+	struct hal_rx_ppdu_info *ppdu_info = NULL;
+	struct hal_rx_ppdu_info *temp_ppdu_info = NULL;
+	struct dp_mon_pdev_be *mon_pdev_be;
+
+	if (qdf_unlikely(!pdev)) {
+		dp_mon_debug("Pdev is NULL");
+		return;
+	}
+
+	mon_pdev = (struct dp_mon_pdev *)pdev->monitor_pdev;
+	if (qdf_unlikely(!mon_pdev)) {
+		dp_mon_debug("monitor pdev is NULL");
+		return;
+	}
+
+	mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
+
+	qdf_spin_lock_bh(&mon_pdev_be->rx_mon_wq_lock);
+	if (!TAILQ_EMPTY(&mon_pdev_be->rx_mon_queue)) {
+		TAILQ_FOREACH_SAFE(ppdu_info,
+				   &mon_pdev_be->rx_mon_queue,
+				   ppdu_list_elem,
+				   temp_ppdu_info) {
+			TAILQ_REMOVE(&mon_pdev_be->rx_mon_queue,
+				     ppdu_info, ppdu_list_elem);
+
+			dp_rx_mon_free_ppdu_info(pdev, ppdu_info);
+			qdf_mem_free(ppdu_info);
+		}
+	}
+	qdf_spin_unlock_bh(&mon_pdev_be->rx_mon_wq_lock);
+}
+
 /**
  * dp_rx_mon_deliver_mpdu() - Deliver MPDU to osif layer
  *
@@ -613,8 +677,6 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
 	uint8_t user_id = ppdu_info->user_id;
 	uint8_t mpdu_idx = ppdu_info->mpdu_count[user_id];
 	uint16_t num_frags;
-	uint8_t *data;
-	struct ieee80211_frame *qwh;
 	uint8_t num_buf_reaped = 0;
 
 	if (!mon_pdev->monitor_configured &&
@@ -656,8 +718,6 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
 						     true);
 
 
-				data = (uint8_t *)qdf_nbuf_get_frag_addr(nbuf, 0);
-				qwh = (struct ieee80211_frame *)data;
 
 			} else {
 				dp_mon_err("num_frags exceeding MAX frags");
@@ -721,6 +781,18 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
 		nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx];
 
 		mpdu_info->full_pkt = true;
+		if (qdf_unlikely(!nbuf)) {
+			nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
+					      DP_RX_MON_MAX_MONITOR_HEADER,
+					      DP_RX_MON_MAX_MONITOR_HEADER,
+					      4, FALSE);
+
+			if (!nbuf) {
+				dp_mon_err("nbuf allocation failed ...");
+				qdf_frag_free(addr);
+				return num_buf_reaped;
+			}
+		}
 
 		if (mpdu_info->decap_type == HAL_HW_RX_DECAP_FORMAT_RAW) {
 			if (mpdu_info->first_rx_hdr_rcvd) {

+ 9 - 0
dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.h

@@ -191,4 +191,13 @@ dp_mon_rx_stats_update_rssi_dbm_params_2_0(struct dp_soc *soc,
 					   struct dp_mon_pdev *mon_pdev)
 { }
 #endif
+
+/**
+ * dp_rx_mon_drain_wq() - Drain monitor buffers from rxmon workqueue
+ *
+ * @pdev: DP pdev handle
+ *
+ * Return: Void
+ */
+void dp_rx_mon_drain_wq(struct dp_pdev *pdev);
 #endif /* _DP_RX_MON_2_0_H_ */

+ 5 - 0
dp/wifi3.0/monitor/dp_mon.c

@@ -5183,6 +5183,11 @@ QDF_STATUS dp_mon_pdev_deinit(struct dp_pdev *pdev)
 		return QDF_STATUS_SUCCESS;
 
 	dp_mon_filters_reset(pdev);
+
+	/* mon pdev extended deinit */
+	if (mon_ops->mon_pdev_ext_deinit)
+		mon_ops->mon_pdev_ext_deinit(pdev);
+
 	/* detach monitor function */
 	dp_monitor_tx_ppdu_stats_detach(pdev);