Browse Source

qcacmn: discard fragmented pkts if msdu count is greater than 1

discard fragmented pkts if msdu count is greater than 1
and also some code clean up

Change-Id: I1d0857b5e22f0e4763cfa355b8c92bde697d7540
CRs-Fixed: 2382353
Tallapragada Kalyan 6 years ago
parent
commit
fe278d5425
3 changed files with 92 additions and 126 deletions
  1. 69 123
      dp/wifi3.0/dp_rx_defrag.c
  2. 2 1
      dp/wifi3.0/dp_rx_defrag.h
  3. 21 2
      dp/wifi3.0/dp_rx_err.c

+ 69 - 123
dp/wifi3.0/dp_rx_defrag.c

@@ -95,9 +95,10 @@ static void dp_rx_return_head_frag_desc(struct dp_peer *peer,
 	union dp_rx_desc_list_elem_t *head = NULL;
 	union dp_rx_desc_list_elem_t *tail = NULL;
 
+	pdev = peer->vdev->pdev;
+	soc = pdev->soc;
+
 	if (peer->rx_tid[tid].head_frag_desc) {
-		pdev = peer->vdev->pdev;
-		soc = pdev->soc;
 		dp_rxdma_srng = &pdev->rx_refill_buf_ring;
 		rx_desc_pool = &soc->rx_desc_buf[pdev->pdev_id];
 
@@ -106,6 +107,15 @@ static void dp_rx_return_head_frag_desc(struct dp_peer *peer,
 		dp_rx_buffers_replenish(soc, 0, dp_rxdma_srng, rx_desc_pool,
 					1, &head, &tail);
 	}
+
+	if (peer->rx_tid[tid].dst_ring_desc) {
+		if (dp_rx_link_desc_return(soc,
+					   peer->rx_tid[tid].dst_ring_desc,
+					   HAL_BM_ACTION_PUT_IN_IDLE_LIST) !=
+		    QDF_STATUS_SUCCESS)
+			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+				  "%s: Failed to return link desc", __func__);
+	}
 }
 
 /*
@@ -120,8 +130,6 @@ static void dp_rx_return_head_frag_desc(struct dp_peer *peer,
 void dp_rx_reorder_flush_frag(struct dp_peer *peer,
 			 unsigned int tid)
 {
-	struct dp_soc *soc;
-
 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH,
 		  FL("Flushing TID %d"), tid);
 
@@ -131,18 +139,6 @@ void dp_rx_reorder_flush_frag(struct dp_peer *peer,
 		return;
 	}
 
-	soc = peer->vdev->pdev->soc;
-
-	if (peer->rx_tid[tid].dst_ring_desc) {
-		if (dp_rx_link_desc_return(soc,
-					peer->rx_tid[tid].dst_ring_desc,
-					HAL_BM_ACTION_PUT_IN_IDLE_LIST) !=
-					QDF_STATUS_SUCCESS)
-			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
-					"%s: Failed to return link desc",
-					__func__);
-	}
-
 	dp_rx_return_head_frag_desc(peer, tid);
 	dp_rx_defrag_cleanup(peer, tid);
 }
@@ -1405,11 +1401,7 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
 			"Unknown peer, dropping the fragment");
 
-		qdf_nbuf_free(frag);
-		dp_rx_add_to_free_desc_list(head, tail, rx_desc);
-		*rx_bfs = 1;
-
-		goto end;
+		goto discard_frag;
 	}
 
 	pdev = peer->vdev->pdev;
@@ -1422,12 +1414,9 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
 	if (!mpdu_sequence_control_valid) {
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
 			"Invalid MPDU seq control field, dropping MPDU");
-		qdf_nbuf_free(frag);
-		dp_rx_add_to_free_desc_list(head, tail, rx_desc);
-		*rx_bfs = 1;
 
 		qdf_assert(0);
-		goto end;
+		goto discard_frag;
 	}
 
 	mpdu_frame_control_valid =
@@ -1437,12 +1426,9 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
 	if (!mpdu_frame_control_valid) {
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
 			"Invalid frame control field, dropping MPDU");
-		qdf_nbuf_free(frag);
-		dp_rx_add_to_free_desc_list(head, tail, rx_desc);
-		*rx_bfs = 1;
 
 		qdf_assert(0);
-		goto end;
+		goto discard_frag;
 	}
 
 	/* Current mpdu sequence */
@@ -1476,12 +1462,9 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
 		 */
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
 			"Rcvd unfragmented pkt on REO Err srng, dropping");
-		qdf_nbuf_free(frag);
-		dp_rx_add_to_free_desc_list(head, tail, rx_desc);
-		*rx_bfs = 1;
 
 		qdf_assert(0);
-		goto end;
+		goto discard_frag;
 	}
 
 	/* Check if the fragment is for the same sequence or a different one */
@@ -1529,25 +1512,26 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
 	if ((fragno == 0) && (status == QDF_STATUS_SUCCESS) &&
 			(rx_reorder_array_elem->head == frag)) {
 
+		qdf_assert_always(ring_desc);
 		status = dp_rx_defrag_save_info_from_ring_desc(ring_desc,
 					rx_desc, peer, tid);
 
 		if (status != QDF_STATUS_SUCCESS) {
 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 				"%s: Unable to store ring desc !", __func__);
-			goto end;
+			goto discard_frag;
 		}
 	} else {
 		dp_rx_add_to_free_desc_list(head, tail, rx_desc);
 		*rx_bfs = 1;
 
 		/* Return the non-head link desc */
-		if (dp_rx_link_desc_return(soc, ring_desc,
-					HAL_BM_ACTION_PUT_IN_IDLE_LIST) !=
-				QDF_STATUS_SUCCESS)
+		if (ring_desc &&
+		    dp_rx_link_desc_return(soc, ring_desc,
+					   HAL_BM_ACTION_PUT_IN_IDLE_LIST) !=
+		    QDF_STATUS_SUCCESS)
 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
-					"%s: Failed to return link desc",
-					__func__);
+				  "%s: Failed to return link desc", __func__);
 
 	}
 
@@ -1613,6 +1597,16 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
 
 	return QDF_STATUS_SUCCESS;
 
+discard_frag:
+	qdf_nbuf_free(frag);
+	dp_rx_add_to_free_desc_list(head, tail, rx_desc);
+	if (dp_rx_link_desc_return(soc, ring_desc,
+				   HAL_BM_ACTION_PUT_IN_IDLE_LIST) !=
+	    QDF_STATUS_SUCCESS)
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			  "%s: Failed to return link desc", __func__);
+	*rx_bfs = 1;
+
 end:
 	if (peer)
 		dp_peer_unref_del_find_by_id(peer);
@@ -1641,30 +1635,21 @@ end:
  * Return: uint32_t: No. of elements processed
  */
 uint32_t dp_rx_frag_handle(struct dp_soc *soc, void *ring_desc,
-		struct hal_rx_mpdu_desc_info *mpdu_desc_info,
-		uint8_t *mac_id,
-		uint32_t quota)
+			   struct hal_rx_mpdu_desc_info *mpdu_desc_info,
+			   struct dp_rx_desc *rx_desc,
+			   uint8_t *mac_id,
+			   uint32_t quota)
 {
 	uint32_t rx_bufs_used = 0;
-	void *link_desc_va;
-	struct hal_buf_info buf_info;
-	struct hal_rx_msdu_list msdu_list; /* per MPDU list of MSDUs */
 	qdf_nbuf_t msdu = NULL;
 	uint32_t tid, msdu_len;
-	int idx, rx_bfs = 0;
+	int rx_bfs = 0;
 	struct dp_pdev *pdev;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	struct dp_rx_desc *rx_desc = NULL;
 
 	qdf_assert(soc);
 	qdf_assert(mpdu_desc_info);
-
-	/* Fragment from a valid peer */
-	hal_rx_reo_buf_paddr_get(ring_desc, &buf_info);
-
-	link_desc_va = dp_rx_cookie_2_link_desc_va(soc, &buf_info);
-
-	qdf_assert(link_desc_va);
+	qdf_assert(rx_desc);
 
 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH,
 		"Number of MSDUs to process, num_msdus: %d",
@@ -1677,82 +1662,39 @@ uint32_t dp_rx_frag_handle(struct dp_soc *soc, void *ring_desc,
 		return rx_bufs_used;
 	}
 
-	/* Get msdu_list for the given MPDU */
-	hal_rx_msdu_list_get(soc->hal_soc, link_desc_va, &msdu_list,
-			     &mpdu_desc_info->msdu_count);
+	/* all buffers in MSDU link belong to same pdev */
+	pdev = soc->pdev_list[rx_desc->pool_id];
+	*mac_id = rx_desc->pool_id;
 
-	/* Process all MSDUs in the current MPDU */
-	for (idx = 0; (idx < mpdu_desc_info->msdu_count); idx++) {
-		struct dp_rx_desc *rx_desc =
-			dp_rx_cookie_2_va_rxdma_buf(soc,
-				msdu_list.sw_cookie[idx]);
+	msdu = rx_desc->nbuf;
 
-		qdf_assert_always(rx_desc);
+	qdf_nbuf_unmap_single(soc->osdev, msdu,	QDF_DMA_BIDIRECTIONAL);
 
-		/* all buffers in MSDU link belong to same pdev */
-		pdev = soc->pdev_list[rx_desc->pool_id];
-		*mac_id = rx_desc->pool_id;
+	rx_desc->rx_buf_start = qdf_nbuf_data(msdu);
 
-		msdu = rx_desc->nbuf;
+	msdu_len = hal_rx_msdu_start_msdu_len_get(rx_desc->rx_buf_start);
 
-		qdf_nbuf_unmap_single(soc->osdev, msdu,
-				QDF_DMA_BIDIRECTIONAL);
+	qdf_nbuf_set_pktlen(msdu, (msdu_len + RX_PKT_TLVS_LEN));
+	qdf_nbuf_append_ext_list(msdu, NULL, 0);
 
-		rx_desc->rx_buf_start = qdf_nbuf_data(msdu);
+	tid = hal_rx_mpdu_start_tid_get(soc->hal_soc, rx_desc->rx_buf_start);
 
-		msdu_len = hal_rx_msdu_start_msdu_len_get(
-				rx_desc->rx_buf_start);
+	/* Process fragment-by-fragment */
+	status = dp_rx_defrag_store_fragment(soc, ring_desc,
+					     &pdev->free_list_head,
+					     &pdev->free_list_tail,
+					     mpdu_desc_info,
+					     tid, rx_desc, &rx_bfs);
 
-		qdf_nbuf_set_pktlen(msdu, (msdu_len + RX_PKT_TLVS_LEN));
-		qdf_nbuf_append_ext_list(msdu, NULL, 0);
+	if (rx_bfs)
+		rx_bufs_used++;
 
-		tid = hal_rx_mpdu_start_tid_get(soc->hal_soc,
-						rx_desc->rx_buf_start);
-
-		/* Process fragment-by-fragment */
-		status = dp_rx_defrag_store_fragment(soc, ring_desc,
-						     &pdev->free_list_head,
-						     &pdev->free_list_tail,
-						     mpdu_desc_info,
-						     tid, rx_desc, &rx_bfs);
-
-		if (rx_bfs)
-			rx_bufs_used++;
-
-		if (!QDF_IS_STATUS_SUCCESS(status)) {
-			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
-				"Rx Defrag err seq#:0x%x msdu_count:%d flags:%d",
-				mpdu_desc_info->mpdu_seq,
-				mpdu_desc_info->msdu_count,
-				mpdu_desc_info->mpdu_flags);
-
-			/* No point in processing rest of the fragments */
-			break;
-		}
-	}
-
-	if (!QDF_IS_STATUS_SUCCESS(status)) {
-		/* drop any remaining buffers in current descriptor */
-		idx++;
-		for (; (idx < mpdu_desc_info->msdu_count); idx++) {
-			rx_desc =
-				dp_rx_cookie_2_va_rxdma_buf(soc,
-							    msdu_list.sw_cookie[idx]);
-			qdf_assert(rx_desc);
-			msdu = rx_desc->nbuf;
-			qdf_nbuf_unmap_single(soc->osdev, msdu,
-					      QDF_DMA_BIDIRECTIONAL);
-			qdf_nbuf_free(msdu);
-			dp_rx_add_to_free_desc_list(&pdev->free_list_head,
-						    &pdev->free_list_tail,
-						    rx_desc);
-			rx_bufs_used++;
-		}
-		if (dp_rx_link_desc_return(soc, ring_desc,
-					   HAL_BM_ACTION_PUT_IN_IDLE_LIST) !=
-					   QDF_STATUS_SUCCESS)
-			dp_err("Failed to return link desc");
-	}
+	if (!QDF_IS_STATUS_SUCCESS(status))
+		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+			  "Rx Defrag err seq#:0x%x msdu_count:%d flags:%d",
+			  mpdu_desc_info->mpdu_seq,
+			  mpdu_desc_info->msdu_count,
+			  mpdu_desc_info->mpdu_flags);
 
 	return rx_bufs_used;
 }
@@ -1771,6 +1713,11 @@ QDF_STATUS dp_rx_defrag_add_last_frag(struct dp_soc *soc,
 
 	if (rx_reorder_array_elem->head &&
 	    rxseq != rx_tid->curr_seq_num) {
+		/* Drop stored fragments if out of sequence
+		 * fragment is received
+		 */
+		dp_rx_reorder_flush_frag(peer, tid);
+
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 			  "%s: No list found for TID %d Seq# %d",
 				__func__, tid, rxseq);
@@ -1833,8 +1780,7 @@ QDF_STATUS dp_rx_defrag_add_last_frag(struct dp_soc *soc,
 			__func__);
 	} else {
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
-			  "%s: Frag seq reinjection failed",
-			__func__);
+			  "%s: Frag seq reinjection failed", __func__);
 		dp_rx_return_head_frag_desc(peer, tid);
 	}
 

+ 2 - 1
dp/wifi3.0/dp_rx_defrag.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -57,6 +57,7 @@ struct dp_rx_defrag_cipher {
 
 uint32_t dp_rx_frag_handle(struct dp_soc *soc, void *ring_desc,
 		struct hal_rx_mpdu_desc_info *mpdu_desc_info,
+		struct dp_rx_desc *rx_desc,
 		uint8_t *mac_id,
 		uint32_t quota);
 

+ 21 - 2
dp/wifi3.0/dp_rx_err.c

@@ -1084,6 +1084,7 @@ dp_rx_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota)
 	void *link_desc_va;
 	struct hal_rx_msdu_list msdu_list; /* MSDU's per MPDU */
 	uint16_t num_msdus;
+	struct dp_rx_desc *rx_desc = NULL;
 
 	/* Debug -- Remove later */
 	qdf_assert(soc && hal_ring);
@@ -1138,6 +1139,12 @@ dp_rx_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota)
 		hal_rx_msdu_list_get(soc->hal_soc, link_desc_va, &msdu_list,
 				     &num_msdus);
 
+		rx_desc = dp_rx_cookie_2_va_rxdma_buf(soc,
+						      msdu_list.sw_cookie[0]);
+		qdf_assert_always(rx_desc);
+
+		mac_id = rx_desc->pool_id;
+
 		if (qdf_unlikely((msdu_list.rbm[0] != DP_WBM2SW_RBM) &&
 				(msdu_list.rbm[0] !=
 					HAL_RX_BUF_RBM_WBM_IDLE_DESC_LIST))) {
@@ -1157,10 +1164,22 @@ dp_rx_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota)
 		hal_rx_mpdu_desc_info_get(ring_desc, &mpdu_desc_info);
 
 		if (mpdu_desc_info.mpdu_flags & HAL_MPDU_F_FRAGMENT) {
-			/* TODO */
+			/*
+			 * We only handle one msdu per link desc for fragmented
+			 * case. We drop the msdus and release the link desc
+			 * back if there are more than one msdu in link desc.
+			 */
+			if (qdf_unlikely(num_msdus > 1)) {
+				count = dp_rx_msdus_drop(soc, ring_desc,
+							 &mpdu_desc_info,
+							 &mac_id, quota);
+				rx_bufs_reaped[mac_id] += count;
+				continue;
+			}
+
 			count = dp_rx_frag_handle(soc,
 						  ring_desc, &mpdu_desc_info,
-						  &mac_id, quota);
+						  rx_desc, &mac_id, quota);
 
 			rx_bufs_reaped[mac_id] += count;
 			DP_STATS_INC(soc, rx.rx_frags, 1);