Browse Source

qcacmn: Lithium LRO Support in the Data Path

Add support to extract LRO information provided by
the hardware and utilize the support provided by QDF to
perform LRO.

Change-Id: I00a26573a450e9c32586b3d5fb656dbfe802cfac
CRs-Fixed: 1107169
Dhanashri Atre 8 years ago
parent
commit
0da3122669
5 changed files with 179 additions and 6 deletions
  1. 15 1
      dp/wifi3.0/dp_main.c
  2. 68 3
      dp/wifi3.0/dp_rx.c
  3. 2 2
      dp/wifi3.0/dp_rx.h
  4. 3 0
      dp/wifi3.0/dp_types.h
  5. 91 0
      dp/wifi3.0/hal_rx.h

+ 15 - 1
dp/wifi3.0/dp_main.c

@@ -19,6 +19,7 @@
 #include <qdf_types.h>
 #include <qdf_lock.h>
 #include <qdf_net_types.h>
+#include <qdf_lro.h>
 #include <hal_api.h>
 #include <hif.h>
 #include <htt.h>
@@ -284,7 +285,7 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget)
 		for (ring = 0; ring < soc->num_reo_dest_rings; ring++) {
 			if (rx_mask & (1 << ring)) {
 				work_done =
-					dp_rx_process(soc,
+					dp_rx_process(int_ctx,
 					    soc->reo_dest_ring[ring].hal_srng,
 					    budget);
 				budget -=  work_done;
@@ -312,6 +313,8 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget)
 		}
 	}
 
+	qdf_lro_flush(int_ctx->lro_ctx);
+
 budget_done:
 	return dp_budget - budget;
 }
@@ -361,6 +364,7 @@ static QDF_STATUS dp_soc_interrupt_attach(void *txrx_soc)
 		soc->intr_ctx[i].rx_wbm_rel_ring_mask = 0x1;
 		soc->intr_ctx[i].reo_status_ring_mask = 0x1;
 		soc->intr_ctx[i].soc = soc;
+		soc->intr_ctx[i].lro_ctx = qdf_lro_init();
 	}
 
 	qdf_timer_init(soc->osdev, &soc->int_timer,
@@ -455,6 +459,7 @@ static QDF_STATUS dp_soc_interrupt_attach(void *txrx_soc)
 
 			return QDF_STATUS_E_FAILURE;
 		}
+		soc->intr_ctx[i].lro_ctx = qdf_lro_init();
 	}
 
 	hif_configure_ext_group_interrupts(soc->hif_handle);
@@ -477,6 +482,7 @@ static void dp_soc_interrupt_detach(void *txrx_soc)
 		soc->intr_ctx[i].tx_ring_mask = 0;
 		soc->intr_ctx[i].rx_ring_mask = 0;
 		soc->intr_ctx[i].rx_mon_ring_mask = 0;
+		qdf_lro_deinit(soc->intr_ctx[i].lro_ctx);
 	}
 }
 #endif
@@ -1623,6 +1629,14 @@ static struct cdp_vdev *dp_vdev_attach_wifi3(struct cdp_pdev *txrx_pdev,
 
 	dp_lro_hash_setup(soc);
 
+	/* LRO */
+	if (wlan_cfg_is_lro_enabled(soc->wlan_cfg_ctx) &&
+		wlan_op_mode_sta == vdev->opmode)
+		vdev->lro_enable = true;
+
+	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+		 "LRO: vdev_id %d lro_enable %d", vdev_id, vdev->lro_enable);
+
 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 		"Created vdev %p (%pM)", vdev, vdev->mac_addr.raw);
 	DP_STATS_INIT(vdev);

+ 68 - 3
dp/wifi3.0/dp_rx.c

@@ -568,6 +568,66 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf)
 }
 #endif
 
+/**
+ * dp_rx_lro() - LRO related processing
+ * @rx_tlv: TLV data extracted from the rx packet
+ * @peer: destination peer of the msdu
+ * @msdu: network buffer
+ * @ctx: LRO context
+ *
+ * This function performs the LRO related processing of the msdu
+ *
+ * Return: true: LRO enabled false: LRO is not enabled
+ */
+#if defined(FEATURE_LRO)
+static bool dp_rx_lro(uint8_t *rx_tlv, struct dp_peer *peer,
+	 qdf_nbuf_t msdu, qdf_lro_ctx_t ctx)
+{
+	qdf_assert(rx_tlv);
+	if (peer->vdev->lro_enable &&
+	 HAL_RX_TLV_GET_TCP_PROTO(rx_tlv)) {
+		QDF_NBUF_CB_RX_LRO_ELIGIBLE(msdu) =
+			 HAL_RX_TLV_GET_LRO_ELIGIBLE(rx_tlv) &&
+			 !HAL_RX_TLV_GET_TCP_PURE_ACK(rx_tlv);
+
+		if (QDF_NBUF_CB_RX_LRO_ELIGIBLE(msdu)) {
+			QDF_NBUF_CB_RX_LRO_CTX(msdu) = ctx;
+			QDF_NBUF_CB_RX_TCP_ACK_NUM(msdu) =
+				 HAL_RX_TLV_GET_TCP_ACK(rx_tlv);
+			QDF_NBUF_CB_RX_TCP_WIN(msdu) =
+				 HAL_RX_TLV_GET_TCP_WIN(rx_tlv);
+			QDF_NBUF_CB_RX_TCP_SEQ_NUM(msdu) =
+				 HAL_RX_TLV_GET_TCP_SEQ(rx_tlv);
+			QDF_NBUF_CB_RX_TCP_CHKSUM(msdu) =
+				 HAL_RX_TLV_GET_TCP_CHKSUM
+					(rx_tlv);
+			QDF_NBUF_CB_RX_FLOW_ID_TOEPLITZ(msdu) =
+				 HAL_RX_TLV_GET_FLOW_ID_TOEPLITZ
+					(rx_tlv);
+			QDF_NBUF_CB_RX_TCP_OFFSET(msdu) =
+				 HAL_RX_TLV_GET_TCP_OFFSET
+					(rx_tlv);
+			QDF_NBUF_CB_RX_IPV6_PROTO(msdu) =
+				 HAL_RX_TLV_GET_IPV6(rx_tlv);
+
+			QDF_NBUF_CB_RX_LRO_ELIGIBLE(msdu) =
+				 qdf_lro_update_info(ctx, msdu);
+		}
+		/* LRO 'enabled' packet, it may not be LRO 'eligible' */
+		return true;
+	}
+
+	/* LRO not supported on this vdev or a non-TCP packet */
+	return false;
+}
+#else
+static bool dp_rx_lro(uint8_t *rx_tlv, struct dp_peer *peer,
+	 qdf_nbuf_t msdu, qdf_lro_ctx_t ctx)
+{
+	return false;
+}
+#endif
+
 /**
  * dp_rx_process() - Brain of the Rx processing functionality
  *		     Called from the bottom half (tasklet/NET_RX_SOFTIRQ)
@@ -581,11 +641,11 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf)
  * Return: uint32_t: No. of elements processed
  */
 uint32_t
-dp_rx_process(struct dp_soc *soc, void *hal_ring, uint32_t quota)
+dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, uint32_t quota)
 {
 	void *hal_soc;
 	void *ring_desc;
-	struct dp_rx_desc *rx_desc;
+	struct dp_rx_desc *rx_desc = NULL;
 	qdf_nbuf_t nbuf;
 	union dp_rx_desc_list_elem_t *head[MAX_PDEV_CNT] = { NULL };
 	union dp_rx_desc_list_elem_t *tail[MAX_PDEV_CNT] = { NULL };
@@ -611,6 +671,7 @@ dp_rx_process(struct dp_soc *soc, void *hal_ring, uint32_t quota)
 	struct dp_pdev *pdev;
 	struct dp_srng *dp_rxdma_srng;
 	struct rx_desc_pool *rx_desc_pool;
+	struct dp_soc *soc = int_ctx->soc;
 
 	DP_HIST_INIT();
 	/* Debug -- Remove later */
@@ -915,6 +976,10 @@ done:
 					continue; /* Get next descriptor */
 
 			rx_bufs_used++;
+
+			if (!dp_rx_lro(rx_tlv_hdr, peer, nbuf, int_ctx->lro_ctx))
+				QDF_NBUF_CB_RX_LRO_CTX(nbuf) = NULL;
+
 			DP_RX_LIST_APPEND(deliver_list_head,
 						deliver_list_tail,
 						nbuf);
@@ -951,8 +1016,8 @@ done:
 			dp_rx_deliver_raw(vdev, deliver_list_head);
 		else if (qdf_likely(vdev->osif_rx) && deliver_list_head)
 			vdev->osif_rx(vdev->osif_vdev, deliver_list_head);
-
 	}
+
 	return rx_bufs_used; /* Assume no scale factor for now */
 }
 

+ 2 - 2
dp/wifi3.0/dp_rx.h

@@ -163,8 +163,8 @@ QDF_STATUS dp_rx_pdev_attach(struct dp_pdev *pdev);
 void dp_rx_pdev_detach(struct dp_pdev *pdev);
 
 
-uint32_t dp_rx_process(struct dp_soc *soc, void *hal_ring, uint32_t quota);
-
+uint32_t
+dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, uint32_t quota);
 
 uint32_t dp_rx_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota);
 

+ 3 - 0
dp/wifi3.0/dp_types.h

@@ -25,6 +25,7 @@
 #include <qdf_atomic.h>
 #include <qdf_util.h>
 #include <qdf_list.h>
+#include <qdf_lro.h>
 #include <queue.h>
 #include <htt_common.h>
 
@@ -321,6 +322,7 @@ struct dp_intr {
 	uint8_t reo_status_ring_mask; /* REO command response ring */
 	struct dp_soc *soc;    /* Reference to SoC structure ,
 				to get DMA ring handles */
+	qdf_lro_ctx_t lro_ctx;
 };
 
 #define REO_DESC_FREELIST_SIZE 64
@@ -919,6 +921,7 @@ struct dp_vdev {
 
 	/* VDEV Stats */
 	struct cdp_vdev_stats stats;
+	bool lro_enable;
 };
 
 

+ 91 - 0
dp/wifi3.0/hal_rx.h

@@ -614,6 +614,97 @@ hal_rx_mpdu_peer_meta_data_get(uint8_t *buf)
 		RX_MSDU_END_9_L3_HEADER_PADDING_LSB))
 #endif
 
+/**
+* LRO information needed from the TLVs
+*/
+#define HAL_RX_TLV_GET_LRO_ELIGIBLE(buf) \
+	(_HAL_MS( \
+		 (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\
+			 msdu_end_tlv.rx_msdu_end), \
+			 RX_MSDU_END_9_LRO_ELIGIBLE_OFFSET)), \
+		RX_MSDU_END_9_LRO_ELIGIBLE_MASK, \
+		RX_MSDU_END_9_LRO_ELIGIBLE_LSB))
+
+#define HAL_RX_TLV_GET_TCP_CHKSUM(buf) \
+	(_HAL_MS( \
+		 (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\
+			 msdu_end_tlv.rx_msdu_end), \
+			 RX_MSDU_END_1_TCP_UDP_CHKSUM_OFFSET)), \
+		RX_MSDU_END_1_TCP_UDP_CHKSUM_MASK, \
+		RX_MSDU_END_1_TCP_UDP_CHKSUM_LSB))
+
+#define HAL_RX_TLV_GET_TCP_ACK(buf) \
+	(_HAL_MS( \
+		 (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\
+			 msdu_end_tlv.rx_msdu_end), \
+			 RX_MSDU_END_8_TCP_ACK_NUMBER_OFFSET)), \
+		RX_MSDU_END_8_TCP_ACK_NUMBER_MASK, \
+		RX_MSDU_END_8_TCP_ACK_NUMBER_LSB))
+
+#define HAL_RX_TLV_GET_TCP_SEQ(buf) \
+	(_HAL_MS( \
+		 (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\
+			 msdu_end_tlv.rx_msdu_end), \
+			 RX_MSDU_END_7_TCP_SEQ_NUMBER_OFFSET)), \
+		RX_MSDU_END_7_TCP_SEQ_NUMBER_MASK, \
+		RX_MSDU_END_7_TCP_SEQ_NUMBER_LSB))
+
+#define HAL_RX_TLV_GET_TCP_WIN(buf) \
+	(_HAL_MS( \
+		 (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\
+			 msdu_end_tlv.rx_msdu_end), \
+			 RX_MSDU_END_9_WINDOW_SIZE_OFFSET)), \
+		RX_MSDU_END_9_WINDOW_SIZE_MASK, \
+		RX_MSDU_END_9_WINDOW_SIZE_LSB))
+
+#define HAL_RX_TLV_GET_TCP_PURE_ACK(buf) \
+	(_HAL_MS( \
+		 (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\
+			 msdu_start_tlv.rx_msdu_start), \
+			 RX_MSDU_START_2_TCP_ONLY_ACK_OFFSET)), \
+		RX_MSDU_START_2_TCP_ONLY_ACK_MASK, \
+		RX_MSDU_START_2_TCP_ONLY_ACK_LSB))
+
+#define HAL_RX_TLV_GET_TCP_PROTO(buf) \
+	(_HAL_MS( \
+		 (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\
+			 msdu_start_tlv.rx_msdu_start), \
+			 RX_MSDU_START_2_TCP_PROTO_OFFSET)), \
+		RX_MSDU_START_2_TCP_PROTO_MASK, \
+		RX_MSDU_START_2_TCP_PROTO_LSB))
+
+#define HAL_RX_TLV_GET_IPV6(buf) \
+	(_HAL_MS( \
+		 (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\
+			 msdu_start_tlv.rx_msdu_start), \
+			 RX_MSDU_START_2_IPV6_PROTO_OFFSET)), \
+		RX_MSDU_START_2_IPV6_PROTO_MASK, \
+		RX_MSDU_START_2_IPV6_PROTO_LSB))
+
+#define HAL_RX_TLV_GET_IP_OFFSET(buf) \
+	(_HAL_MS( \
+		 (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\
+			 msdu_start_tlv.rx_msdu_start), \
+			 RX_MSDU_START_1_L3_OFFSET_OFFSET)), \
+		RX_MSDU_START_1_L3_OFFSET_MASK, \
+		RX_MSDU_START_1_L3_OFFSET_LSB))
+
+#define HAL_RX_TLV_GET_TCP_OFFSET(buf) \
+	(_HAL_MS( \
+		 (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\
+			 msdu_start_tlv.rx_msdu_start), \
+			 RX_MSDU_START_1_L4_OFFSET_OFFSET)), \
+		RX_MSDU_START_1_L4_OFFSET_MASK, \
+		RX_MSDU_START_1_L4_OFFSET_LSB))
+
+#define HAL_RX_TLV_GET_FLOW_ID_TOEPLITZ(buf) \
+	(_HAL_MS( \
+		 (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\
+			 msdu_start_tlv.rx_msdu_start), \
+			 RX_MSDU_START_4_FLOW_ID_TOEPLITZ_OFFSET)), \
+		RX_MSDU_START_4_FLOW_ID_TOEPLITZ_MASK, \
+		RX_MSDU_START_4_FLOW_ID_TOEPLITZ_LSB))
+
  /**
  * hal_rx_msdu_end_l3_hdr_padding_get(): API to get the
  * l3_header padding from rx_msdu_end TLV