qcacld-3.0: Lithium LRO Support

Add changes needed to support Receive Offload (LRO) on Lithium.

CRs-Fixed: 1107169
Change-Id: I2fb00fa83a52b039e6ad9aea9a98576f2c36d6fa
diff --git a/Kbuild b/Kbuild
index d52c7ac..45e4ed6 100644
--- a/Kbuild
+++ b/Kbuild
@@ -802,6 +802,10 @@
 		-I$(WLAN_COMMON_INC)/umac/cmn_services/utils/inc
 UMAC_COMMON_OBJS := $(WLAN_COMMON_ROOT)/umac/cmn_services/utils/src/wlan_utility.o
 
+ifeq ($(CONFIG_WLAN_LRO), y)
+QDF_OBJS +=     $(QDF_OBJ_DIR)/qdf_lro.o
+endif
+
 ############ CDS (Connectivity driver services) ############
 CDS_DIR :=	core/cds
 CDS_INC_DIR :=	$(CDS_DIR)/inc
diff --git a/core/dp/htt/htt_internal.h b/core/dp/htt/htt_internal.h
index c12bb5c..30ad41a 100644
--- a/core/dp/htt/htt_internal.h
+++ b/core/dp/htt/htt_internal.h
@@ -156,7 +156,7 @@
 		~HTT_RX_DESC_ALIGN_MASK);
 }
 
-#if defined(FEATURE_LRO)
+#if defined(FEATURE_LRO) && defined(HELIUMPLUS_PADDR64)
 /**
  * htt_print_rx_desc_lro() - print LRO information in the rx
  * descriptor
diff --git a/core/hdd/src/wlan_hdd_lro.c b/core/hdd/src/wlan_hdd_lro.c
index 90eba98..a395d9f 100644
--- a/core/hdd/src/wlan_hdd_lro.c
+++ b/core/hdd/src/wlan_hdd_lro.c
@@ -32,6 +32,7 @@
 
 #include <wlan_hdd_includes.h>
 #include <qdf_types.h>
+#include <qdf_lro.h>
 #include <wlan_hdd_lro.h>
 #include <wlan_hdd_napi.h>
 #include <wma_api.h>
@@ -42,12 +43,109 @@
 #include <linux/random.h>
 #include <net/tcp.h>
 
-#define LRO_MAX_AGGR_SIZE 100
-
 #define LRO_VALID_FIELDS \
 	(LRO_DESC | LRO_ELIGIBILITY_CHECKED | LRO_TCP_ACK_NUM | \
 	 LRO_TCP_DATA_CSUM | LRO_TCP_SEQ_NUM | LRO_TCP_WIN)
 
+#if defined(QCA_WIFI_NAPIER_EMULATION)
+/**
+ * hdd_lro_init() - initialization for LRO
+ * @hdd_ctx: HDD context
+ *
+ * This function sends the LRO configuration to the firmware
+ * via WMA
+ * Make sure that this function gets called after NAPI
+ * instances have been created.
+ *
+ * Return: 0 - success, < 0 - failure
+ */
+int hdd_lro_init(hdd_context_t *hdd_ctx)
+{
+	return 0;
+}
+
+/**
+ * hdd_lro_enable() - enable LRO
+ * @hdd_ctx: HDD context
+ * @adapter: HDD adapter
+ *
+ * This function enables LRO in the network device attached to
+ * the HDD adapter. It also allocates the HDD LRO instance for
+ * that network device
+ *
+ * Return: 0 - success, < 0 - failure
+ */
+int hdd_lro_enable(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * hdd_lro_rx() - LRO receive function
+ * @hdd_ctx: HDD context
+ * @adapter: HDD adapter
+ * @skb: network buffer
+ *
+ * Delivers LRO eligible frames to the LRO manager
+ *
+ * Return: HDD_LRO_RX - frame delivered to LRO manager
+ * HDD_LRO_NO_RX - frame not delivered
+ */
+enum hdd_lro_rx_status hdd_lro_rx(hdd_context_t *hdd_ctx,
+	 hdd_adapter_t *adapter, struct sk_buff *skb)
+{
+	struct net_lro_mgr *lro_mgr;
+	qdf_lro_ctx_t ctx = (qdf_lro_ctx_t)QDF_NBUF_CB_RX_LRO_CTX(skb);
+	/* LRO is not supported or non-TCP packet */
+	if (!ctx)
+		return HDD_LRO_NO_RX;
+
+	lro_mgr = ctx->lro_mgr;
+
+	if (QDF_NBUF_CB_RX_LRO_ELIGIBLE(skb)) {
+		struct net_lro_info hdd_lro_info;
+
+		hdd_lro_info.valid_fields = LRO_VALID_FIELDS;
+
+		hdd_lro_info.lro_desc = QDF_NBUF_CB_RX_LRO_DESC(skb);
+		hdd_lro_info.lro_eligible = 1;
+		hdd_lro_info.tcp_ack_num = QDF_NBUF_CB_RX_TCP_ACK_NUM(skb);
+		hdd_lro_info.tcp_data_csum =
+			 csum_unfold(QDF_NBUF_CB_RX_TCP_CHKSUM(skb));
+		hdd_lro_info.tcp_seq_num = QDF_NBUF_CB_RX_TCP_SEQ_NUM(skb);
+		hdd_lro_info.tcp_win = QDF_NBUF_CB_RX_TCP_WIN(skb);
+
+		lro_receive_skb_ext(lro_mgr, skb,
+			 (void *)adapter, &hdd_lro_info);
+
+		if (!hdd_lro_info.lro_desc->active)
+			qdf_lro_flow_free(skb);
+
+		return HDD_LRO_RX;
+	} else {
+		lro_flush_desc(lro_mgr, QDF_NBUF_CB_RX_LRO_DESC(skb));
+		return HDD_LRO_NO_RX;
+	}
+}
+/**
+ * hdd_lro_disable() - disable LRO
+ * @hdd_ctx: HDD context
+ * @adapter: HDD adapter
+ *
+ * This function frees the HDD LRO instance for the network
+ * device attached to the HDD adapter
+ *
+ * Return: none
+ */
+void hdd_lro_disable(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
+{
+	return;
+}
+
+#else
+
+#define LRO_MAX_AGGR_SIZE 100
+
 /**
  * hdd_lro_get_skb_header() - LRO callback function
  * @skb: network buffer
@@ -639,6 +737,8 @@
 	return status;
 }
 
+#endif
+
 /**
  * wlan_hdd_display_lro_stats() - display LRO statistics
  * @hdd_ctx: hdd context
diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c
index c48258d..34d0a24 100644
--- a/core/hdd/src/wlan_hdd_tx_rx.c
+++ b/core/hdd/src/wlan_hdd_tx_rx.c
@@ -1125,6 +1125,13 @@
 								  rx_wakelock_timeout);
 		}
 
+	if (HDD_LRO_NO_RX == hdd_lro_rx(pHddCtx, pAdapter, skb)) {
+		if (hdd_napi_enabled(HDD_NAPI_ANY) &&
+		    !pHddCtx->enableRxThread)
+			rxstat = netif_receive_skb(skb);
+		else
+			rxstat = netif_rx_ni(skb);
+	}
 		/* Remove SKB from internal tracking table before submitting
 		 * it to stack
 		 */