Преглед изворни кода

qcacmn: Drop mpdus received on non-monitor PMAC

Currently the monitor mode filter settings are set
for both the PMAC. Hence it is possible that the
non-monitor PMAC (the PMAC on which monitor vdev
is not running), can receive packets and forward them
to the monitor destination ring.

The above scenario will lead to a ppdu_id mismatch
when reaping the monitor status ring and comparing
the ppdu_id in status ring with the one in monitor
destination ring, since monitor status ring will
have ppdu_id from the PMAC on which monitor vdev is
running, whereas monitor destination ring will have
packets from both the PMAC.

In order to mitigate the above issue, detect the
packets in the monitor destination ring, which are
not from the PMAC where monitor vdev is running, and
drop them.

Change-Id: I32392ceeadffd9cb7a4dd76336004a9dcbb99404
CRs-Fixed: 3318036
Rakesh Pillai пре 2 година
родитељ
комит
f533809136

+ 172 - 0
dp/wifi3.0/monitor/1.0/dp_rx_mon_dest_1.0.c

@@ -463,6 +463,153 @@ next_msdu:
 	return rx_bufs_used;
 	return rx_bufs_used;
 }
 }
 
 
+#if !defined(DISABLE_MON_CONFIG) && defined(MON_ENABLE_DROP_FOR_NON_MON_PMAC)
+static int dp_rx_mon_drop_one_mpdu(struct dp_pdev *pdev,
+				   uint32_t mac_id,
+				   hal_rxdma_desc_t rxdma_dst_ring_desc,
+				   union dp_rx_desc_list_elem_t **head,
+				   union dp_rx_desc_list_elem_t **tail)
+{
+	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
+	struct dp_soc *soc = pdev->soc;
+	hal_soc_handle_t hal_soc = soc->hal_soc;
+	struct hal_buf_info buf_info;
+	uint32_t msdu_count = 0;
+	uint32_t rx_bufs_used = 0;
+	void *rx_msdu_link_desc;
+	struct hal_rx_msdu_list msdu_list;
+	uint16_t num_msdus;
+	qdf_nbuf_t nbuf;
+	uint32_t i;
+	uint8_t bm_action = HAL_BM_ACTION_PUT_IN_IDLE_LIST;
+	uint32_t rx_link_buf_info[HAL_RX_BUFFINFO_NUM_DWORDS];
+	struct rx_desc_pool *rx_desc_pool;
+
+	rx_desc_pool = dp_rx_get_mon_desc_pool(soc, mac_id, pdev->pdev_id);
+	hal_rx_reo_ent_buf_paddr_get(hal_soc, rxdma_dst_ring_desc,
+				     &buf_info, &msdu_count);
+
+	do {
+		rx_msdu_link_desc = dp_rx_cookie_2_mon_link_desc(pdev,
+								 buf_info,
+								 mac_id);
+		if (qdf_unlikely(!rx_msdu_link_desc)) {
+			mon_pdev->rx_mon_stats.mon_link_desc_invalid++;
+			return rx_bufs_used;
+		}
+
+		hal_rx_msdu_list_get(soc->hal_soc, rx_msdu_link_desc,
+				     &msdu_list, &num_msdus);
+
+		for (i = 0; i < num_msdus; i++) {
+			struct dp_rx_desc *rx_desc;
+			qdf_dma_addr_t buf_paddr;
+
+			rx_desc = dp_rx_get_mon_desc(soc,
+						     msdu_list.sw_cookie[i]);
+
+			if (qdf_unlikely(!rx_desc)) {
+				mon_pdev->rx_mon_stats.
+						mon_rx_desc_invalid++;
+				continue;
+			}
+
+			nbuf = DP_RX_MON_GET_NBUF_FROM_DESC(rx_desc);
+			buf_paddr =
+				 dp_rx_mon_get_paddr_from_desc(rx_desc);
+
+			if (qdf_unlikely(!rx_desc->in_use || !nbuf ||
+					 msdu_list.paddr[i] !=
+					 buf_paddr)) {
+				mon_pdev->rx_mon_stats.
+						mon_nbuf_sanity_err++;
+				continue;
+			}
+			rx_bufs_used++;
+
+			if (!rx_desc->unmapped) {
+				dp_rx_mon_buffer_unmap(soc, rx_desc,
+						       rx_desc_pool->buf_size);
+				rx_desc->unmapped = 1;
+			}
+
+			qdf_nbuf_free(nbuf);
+			dp_rx_add_to_free_desc_list(head, tail, rx_desc);
+
+			if (!(msdu_list.msdu_info[i].msdu_flags &
+			      HAL_MSDU_F_MSDU_CONTINUATION))
+				msdu_count--;
+		}
+
+		/*
+		 * Store the current link buffer into to the local
+		 * structure to be  used for release purpose.
+		 */
+		hal_rxdma_buff_addr_info_set(soc->hal_soc,
+					     rx_link_buf_info,
+					     buf_info.paddr,
+					     buf_info.sw_cookie,
+					     buf_info.rbm);
+
+		hal_rx_mon_next_link_desc_get(soc->hal_soc,
+					      rx_msdu_link_desc,
+					      &buf_info);
+		if (dp_rx_monitor_link_desc_return(pdev,
+						   (hal_buff_addrinfo_t)
+						   rx_link_buf_info,
+						   mac_id, bm_action) !=
+		    QDF_STATUS_SUCCESS)
+			dp_info_rl("monitor link desc return failed");
+	} while (buf_info.paddr && msdu_count);
+
+	return rx_bufs_used;
+}
+
+static QDF_STATUS
+dp_rx_mon_check_n_drop_mpdu(struct dp_pdev *pdev, uint32_t mac_id,
+			    hal_rxdma_desc_t rxdma_dst_ring_desc,
+			    union dp_rx_desc_list_elem_t **head,
+			    union dp_rx_desc_list_elem_t **tail,
+			    uint32_t *rx_bufs_dropped)
+{
+	struct dp_soc *soc = pdev->soc;
+	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
+	uint32_t lmac_id = DP_MON_INVALID_LMAC_ID;
+	uint8_t src_link_id;
+	QDF_STATUS status;
+
+	if (mon_pdev->mon_chan_band == REG_BAND_UNKNOWN)
+		return QDF_STATUS_E_INVAL;
+
+	lmac_id = pdev->ch_band_lmac_id_mapping[mon_pdev->mon_chan_band];
+
+	status = hal_rx_reo_ent_get_src_link_id(soc->hal_soc,
+						rxdma_dst_ring_desc,
+						&src_link_id);
+	if (QDF_IS_STATUS_ERROR(status))
+		return QDF_STATUS_E_INVAL;
+
+	if (src_link_id == lmac_id)
+		return QDF_STATUS_E_INVAL;
+
+	*rx_bufs_dropped = dp_rx_mon_drop_one_mpdu(pdev, mac_id,
+						   rxdma_dst_ring_desc,
+						   head, tail);
+
+	return QDF_STATUS_SUCCESS;
+}
+#else
+static inline QDF_STATUS
+dp_rx_mon_check_n_drop_mpdu(struct dp_pdev *pdev, uint32_t mac_id,
+			    hal_rxdma_desc_t rxdma_dst_ring_desc,
+			    union dp_rx_desc_list_elem_t **head,
+			    union dp_rx_desc_list_elem_t **tail,
+			    uint32_t *rx_bufs_dropped)
+{
+	return QDF_STATUS_E_FAILURE;
+}
+#endif
+
 void dp_rx_mon_dest_process(struct dp_soc *soc, struct dp_intr *int_ctx,
 void dp_rx_mon_dest_process(struct dp_soc *soc, struct dp_intr *int_ctx,
 			    uint32_t mac_id, uint32_t quota)
 			    uint32_t mac_id, uint32_t quota)
 {
 {
@@ -517,10 +664,23 @@ void dp_rx_mon_dest_process(struct dp_soc *soc, struct dp_intr *int_ctx,
 		hal_srng_dst_peek(hal_soc, mon_dst_srng))) {
 		hal_srng_dst_peek(hal_soc, mon_dst_srng))) {
 		qdf_nbuf_t head_msdu, tail_msdu;
 		qdf_nbuf_t head_msdu, tail_msdu;
 		uint32_t npackets;
 		uint32_t npackets;
+		uint32_t rx_bufs_dropped;
 
 
+		rx_bufs_dropped = 0;
 		head_msdu = (qdf_nbuf_t)NULL;
 		head_msdu = (qdf_nbuf_t)NULL;
 		tail_msdu = (qdf_nbuf_t)NULL;
 		tail_msdu = (qdf_nbuf_t)NULL;
 
 
+		if (QDF_STATUS_SUCCESS ==
+		    dp_rx_mon_check_n_drop_mpdu(pdev, mac_id,
+						rxdma_dst_ring_desc,
+						&head, &tail,
+						&rx_bufs_dropped)) {
+			/* Increment stats */
+			rx_bufs_used += rx_bufs_dropped;
+			hal_srng_dst_get_next(hal_soc, mon_dst_srng);
+			continue;
+		}
+
 		mpdu_rx_bufs_used =
 		mpdu_rx_bufs_used =
 			dp_rx_mon_mpdu_pop(soc, mac_id,
 			dp_rx_mon_mpdu_pop(soc, mac_id,
 					   rxdma_dst_ring_desc,
 					   rxdma_dst_ring_desc,
@@ -1037,6 +1197,18 @@ dp_mon_dest_srng_drop_for_mac(struct dp_pdev *pdev, uint32_t mac_id)
 	return 0;
 	return 0;
 }
 }
 #endif
 #endif
+
+#if !defined(DISABLE_MON_CONFIG) && defined(MON_ENABLE_DROP_FOR_NON_MON_PMAC)
+static QDF_STATUS
+dp_rx_mon_check_n_drop_mpdu(struct dp_pdev *pdev, uint32_t mac_id,
+			    hal_rxdma_desc_t rxdma_dst_ring_desc,
+			    union dp_rx_desc_list_elem_t **head,
+			    union dp_rx_desc_list_elem_t **tail,
+			    uint32_t *rx_bufs_dropped)
+{
+	return QDF_STATUS_E_FAILURE;
+}
+#endif
 #endif
 #endif
 
 
 static void
 static void

+ 20 - 0
hal/wifi3.0/hal_api_mon.h

@@ -342,6 +342,26 @@ enum {
 	DP_PPDU_STATUS_DONE,
 	DP_PPDU_STATUS_DONE,
 };
 };
 
 
+static inline QDF_STATUS
+hal_rx_reo_ent_get_src_link_id(hal_soc_handle_t hal_soc_hdl,
+			       hal_rxdma_desc_t rx_desc,
+			       uint8_t *src_link_id)
+{
+	struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl;
+
+	if (!hal_soc || !hal_soc->ops) {
+		hal_err("hal handle is NULL");
+		QDF_BUG(0);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (hal_soc->ops->hal_rx_reo_ent_get_src_link_id)
+		return hal_soc->ops->hal_rx_reo_ent_get_src_link_id(rx_desc,
+								    src_link_id);
+
+	return QDF_STATUS_E_INVAL;
+}
+
 /**
 /**
  * hal_rx_reo_ent_buf_paddr_get: Gets the physical address and
  * hal_rx_reo_ent_buf_paddr_get: Gets the physical address and
  *			cookie from the REO entrance ring element
  *			cookie from the REO entrance ring element

+ 3 - 0
hal/wifi3.0/hal_internal.h

@@ -1148,6 +1148,9 @@ struct hal_hw_txrx_ops {
 					  uint8_t *buf);
 					  uint8_t *buf);
 	void (*hal_set_reo_ent_desc_reo_dest_ind)(uint8_t *desc,
 	void (*hal_set_reo_ent_desc_reo_dest_ind)(uint8_t *desc,
 						  uint32_t dst_ind);
 						  uint32_t dst_ind);
+	QDF_STATUS
+	(*hal_rx_reo_ent_get_src_link_id)(hal_rxdma_desc_t rx_desc,
+					  uint8_t *src_link_id);
 
 
 	/* REO CMD and STATUS */
 	/* REO CMD and STATUS */
 	int (*hal_reo_send_cmd)(hal_soc_handle_t hal_soc_hdl,
 	int (*hal_reo_send_cmd)(hal_soc_handle_t hal_soc_hdl,

+ 13 - 0
hal/wifi3.0/kiwi/hal_kiwi.c

@@ -2039,6 +2039,17 @@ hal_get_tsf_time_kiwi(hal_soc_handle_t hal_soc_hdl, uint32_t tsf_id,
 }
 }
 #endif
 #endif
 
 
+static QDF_STATUS hal_rx_reo_ent_get_src_link_id_kiwi(hal_rxdma_desc_t rx_desc,
+						      uint8_t *src_link_id)
+{
+	struct reo_entrance_ring *reo_ent_desc =
+					(struct reo_entrance_ring *)rx_desc;
+
+	*src_link_id = reo_ent_desc->src_link_id;
+
+	return QDF_STATUS_SUCCESS;
+}
+
 static void hal_hw_txrx_ops_attach_kiwi(struct hal_soc *hal_soc)
 static void hal_hw_txrx_ops_attach_kiwi(struct hal_soc *hal_soc)
 {
 {
 	/* init and setup */
 	/* init and setup */
@@ -2290,6 +2301,8 @@ static void hal_hw_txrx_ops_attach_kiwi(struct hal_soc *hal_soc)
 	hal_soc->ops->hal_tx_vdev_mcast_ctrl_set =
 	hal_soc->ops->hal_tx_vdev_mcast_ctrl_set =
 		hal_tx_vdev_mcast_ctrl_set_be;
 		hal_tx_vdev_mcast_ctrl_set_be;
 	hal_soc->ops->hal_get_tsf_time = hal_get_tsf_time_kiwi;
 	hal_soc->ops->hal_get_tsf_time = hal_get_tsf_time_kiwi;
+	hal_soc->ops->hal_rx_reo_ent_get_src_link_id =
+					hal_rx_reo_ent_get_src_link_id_kiwi;
 };
 };
 
 
 struct hal_hw_srng_config hw_srng_table_kiwi[] = {
 struct hal_hw_srng_config hw_srng_table_kiwi[] = {