Merge "qcacld-3.0: Do RX packet aggregation for every 16th packet" into wlan-cld3.driver.lnx.2.0-dev
diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c
index 78d7aa8..e513a06 100644
--- a/core/hdd/src/wlan_hdd_ipa.c
+++ b/core/hdd/src/wlan_hdd_ipa.c
@@ -91,6 +91,8 @@
 
 #define HDD_IPA_MAX_PENDING_EVENT_COUNT    20
 
+#define IPA_WLAN_RX_SOFTIRQ_THRESH 16
+
 enum hdd_ipa_uc_op_code {
 	HDD_IPA_UC_OPCODE_TX_SUSPEND = 0,
 	HDD_IPA_UC_OPCODE_TX_RESUME = 1,
@@ -4076,6 +4078,40 @@
 			    "RM CONS resource delete failed %d", ret);
 }
 
+#ifdef QCA_CONFIG_SMP
+static int hdd_ipa_aggregated_rx_ind(qdf_nbuf_t skb)
+{
+	return netif_rx_ni(skb);
+}
+#else
+static int hdd_ipa_aggregated_rx_ind(qdf_nbuf_t skb)
+{
+	struct iphdr *ip_h;
+	static atomic_t softirq_mitigation_cntr =
+		ATOMIC_INIT(IPA_WLAN_RX_SOFTIRQ_THRESH);
+	int result;
+
+	ip_h = (struct iphdr *)(skb->data);
+	if ((skb->protocol == htons(ETH_P_IP)) &&
+		(ip_h->protocol == IPPROTO_ICMP)) {
+		result = netif_rx_ni(skb);
+	} else {
+		/* Call netif_rx_ni for every IPA_WLAN_RX_SOFTIRQ_THRESH packets
+		 * to avoid excessive softirq's.
+		 */
+		if (atomic_dec_and_test(&softirq_mitigation_cntr)) {
+			result = netif_rx_ni(skb);
+			atomic_set(&softirq_mitigation_cntr,
+					IPA_WLAN_RX_SOFTIRQ_THRESH);
+		} else {
+			result = netif_rx(skb);
+		}
+	}
+
+	return result;
+}
+#endif
+
 /**
  * hdd_ipa_send_skb_to_network() - Send skb to kernel
  * @skb: network buffer
@@ -4089,6 +4125,7 @@
 static void hdd_ipa_send_skb_to_network(qdf_nbuf_t skb,
 	hdd_adapter_t *adapter)
 {
+	int result;
 	struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
 	unsigned int cpu_index;
 
@@ -4114,7 +4151,8 @@
 	cpu_index = wlan_hdd_get_cpu();
 
 	++adapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index];
-	if (netif_rx_ni(skb) == NET_RX_SUCCESS)
+	result = hdd_ipa_aggregated_rx_ind(skb);
+	if (result == NET_RX_SUCCESS)
 		++adapter->hdd_stats.hddTxRxStats.rxDelivered[cpu_index];
 	else
 		++adapter->hdd_stats.hddTxRxStats.rxRefused[cpu_index];