Browse Source

qcacld-3.0: Optimize memory usage of intra BSS path

qcacld-2.0 to qcacld-3.0 propagation

Use SKB clone instead of using SKB copy for forward packets.
Addtional fix to release SKB to IPA when dropping Rx packets from IPA.

Change-Id: Ibfacf855b53148fd6b254e281f7163d03e3753ec
CRs-Fixed: 950379
Prakash Dhavali 8 years ago
parent
commit
87b38e339c
2 changed files with 73 additions and 32 deletions
  1. 12 0
      core/hdd/inc/wlan_hdd_ipa.h
  2. 61 32
      core/hdd/src/wlan_hdd_ipa.c

+ 12 - 0
core/hdd/inc/wlan_hdd_ipa.h

@@ -61,6 +61,18 @@ enum hdd_ipa_wlan_event {
 /* Include files */
 #include <wlan_hdd_assoc.h> /* hdd_context_t */
 
+/**
+ * enum hdd_ipa_forward_type: Type of forward packet received from IPA
+ * @HDD_IPA_FORWARD_PKT_NONE: No forward packet
+ * @HDD_IPA_FORWARD_PKT_LOCAL_STACK: Packet forwarded to kernel network stack
+ * @HDD_IPA_FORWARD_PKT_DISCARD: Discarded packet before sending to kernel stack
+ */
+enum hdd_ipa_forward_type {
+	HDD_IPA_FORWARD_PKT_NONE = 0,
+	HDD_IPA_FORWARD_PKT_LOCAL_STACK = 1,
+	HDD_IPA_FORWARD_PKT_DISCARD = 2
+};
+
 /**
  * FIXME: Temporary hack - until IPA functionality gets restored
  *

+ 61 - 32
core/hdd/src/wlan_hdd_ipa.c

@@ -54,6 +54,7 @@
 
 #include "wma.h"
 #include "wma_api.h"
+#include "wal_rx_desc.h"
 
 #include "cdp_txrx_ipa.h"
 
@@ -485,9 +486,6 @@ static uint32_t wlan_hdd_stub_addr_to_priv(void *ptr)
 #define HDD_IPA_UC_WLAN_HDR_DES_MAC_OFFSET \
 	(HDD_IPA_WLAN_FRAG_HEADER + HDD_IPA_WLAN_IPA_HEADER)
 
-#define HDD_IPA_FW_RX_DESC_DISCARD_M 0x1
-#define HDD_IPA_FW_RX_DESC_FORWARD_M 0x2
-
 #define HDD_IPA_GET_IFACE_ID(_data) \
 	(((struct hdd_ipa_cld_hdr *) (_data))->iface_id)
 
@@ -2647,35 +2645,29 @@ static void hdd_ipa_send_skb_to_network(qdf_nbuf_t skb,
 static void hdd_ipa_forward(struct hdd_ipa_priv *hdd_ipa,
 			    hdd_adapter_t *adapter, qdf_nbuf_t skb)
 {
-	qdf_nbuf_t copy;
 	struct hdd_ipa_pm_tx_cb *pm_tx_cb;
 
-	copy = qdf_nbuf_copy(skb);
-	if (!copy) {
-		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "copy packet alloc fail");
-		return;
-	}
-
 	qdf_spin_lock_bh(&hdd_ipa->pm_lock);
 	/* WLAN subsystem is in suspend, put int queue */
 	if (hdd_ipa->suspended) {
 		qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
 		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
 			"TX in SUSPEND PUT QUEUE");
-		qdf_mem_set(copy->cb, sizeof(copy->cb), 0);
-		pm_tx_cb = (struct hdd_ipa_pm_tx_cb *)copy->cb;
+		qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
+		pm_tx_cb = (struct hdd_ipa_pm_tx_cb *)skb->cb;
 		pm_tx_cb->exception = true;
 		pm_tx_cb->adapter = adapter;
 		qdf_spin_lock_bh(&hdd_ipa->pm_lock);
-		qdf_nbuf_queue_add(&hdd_ipa->pm_queue_head, copy);
+		qdf_nbuf_queue_add(&hdd_ipa->pm_queue_head, skb);
 		qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
 		hdd_ipa->stats.num_tx_queued++;
 	} else {
 		/* Resume, put packet into WLAN TX */
 		qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
-		if (hdd_softap_hard_start_xmit(copy, adapter->dev)) {
+		if (hdd_softap_hard_start_xmit(skb, adapter->dev)) {
 			HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
 			    "packet tx fail");
+			hdd_ipa->stats.num_tx_bcmc_err++;
 		} else {
 			hdd_ipa->stats.num_tx_bcmc++;
 			hdd_ipa->ipa_tx_forward++;
@@ -2683,6 +2675,53 @@ static void hdd_ipa_forward(struct hdd_ipa_priv *hdd_ipa,
 	}
 }
 
+/**
+ * hdd_ipa_intrabss_forward() - Forward intra bss packets.
+ * @hdd_ipa: pointer to HDD IPA struct
+ * @adapter: hdd adapter pointer
+ * @desc: Firmware descriptor
+ * @skb: Data buffer
+ *
+ * Return:
+ *      HDD_IPA_FORWARD_PKT_NONE
+ *      HDD_IPA_FORWARD_PKT_DISCARD
+ *      HDD_IPA_FORWARD_PKT_LOCAL_STACK
+ *
+ */
+
+static enum hdd_ipa_forward_type hdd_ipa_intrabss_forward(
+		struct hdd_ipa_priv *hdd_ipa,
+		hdd_adapter_t *adapter,
+		uint8_t desc,
+		qdf_nbuf_t skb)
+{
+	int ret = HDD_IPA_FORWARD_PKT_NONE;
+
+	if ((desc & FW_RX_DESC_FORWARD_M)) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
+				"Forward packet to Tx (fw_desc=%d)", desc);
+		hdd_ipa->ipa_tx_forward++;
+
+		if ((desc & FW_RX_DESC_DISCARD_M)) {
+			hdd_ipa_forward(hdd_ipa, adapter, skb);
+			hdd_ipa->ipa_rx_internel_drop_count++;
+			hdd_ipa->ipa_rx_discard++;
+			ret = HDD_IPA_FORWARD_PKT_DISCARD;
+		} else {
+			struct sk_buff *cloned_skb = skb_clone(skb, GFP_ATOMIC);
+			if (cloned_skb)
+				hdd_ipa_forward(hdd_ipa, adapter, cloned_skb);
+			else
+				HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+						"%s: tx skb alloc failed",
+						__func__);
+			ret = HDD_IPA_FORWARD_PKT_LOCAL_STACK;
+		}
+	}
+
+	return ret;
+}
+
 /**
  * hdd_ipa_w2i_cb() - WLAN to IPA callback handler
  * @priv: pointer to private data registered with IPA (we register a
@@ -2773,19 +2812,10 @@ static void __hdd_ipa_w2i_cb(void *priv, enum ipa_dp_evt_type evt,
 			 * only when DISCARD bit is not set.
 			 */
 			fw_desc = (uint8_t)skb->cb[1];
-			if (fw_desc & HDD_IPA_FW_RX_DESC_FORWARD_M) {
-				HDD_IPA_DP_LOG(
-					QDF_TRACE_LEVEL_DEBUG,
-					"Forward packet to Tx (fw_desc=%d)",
-					fw_desc);
-				hdd_ipa_forward(hdd_ipa, adapter, skb);
-			}
-			if (fw_desc & HDD_IPA_FW_RX_DESC_DISCARD_M) {
-				HDD_IPA_INCREASE_INTERNAL_DROP_COUNT(hdd_ipa);
-				hdd_ipa->ipa_rx_discard++;
-				kfree_skb(skb);
+			if (HDD_IPA_FORWARD_PKT_DISCARD ==
+			    hdd_ipa_intrabss_forward(hdd_ipa, adapter,
+						     fw_desc, skb))
 				break;
-			}
 		} else {
 			HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO_HIGH,
 				"Intra-BSS FWD is disabled-skip forward to Tx");
@@ -3008,17 +3038,16 @@ static void hdd_ipa_i2w_cb(void *priv, enum ipa_dp_evt_type evt,
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
 	iface_context = (struct hdd_ipa_iface_context *)priv;
+	ipa_tx_desc = (struct ipa_rx_data *)data;
+	hdd_ipa = iface_context->hdd_ipa;
+
 	if (evt != IPA_RECEIVE) {
-		skb = (qdf_nbuf_t) data;
-		dev_kfree_skb_any(skb);
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Event is not IPA_RECEIVE");
+		ipa_free_skb(ipa_tx_desc);
 		iface_context->stats.num_tx_drop++;
 		return;
 	}
 
-	ipa_tx_desc = (struct ipa_rx_data *)data;
-
-	hdd_ipa = iface_context->hdd_ipa;
-
 	/*
 	 * When SSR is going on or driver is unloading, just drop the packets.
 	 * During SSR, there is no use in queueing the packets as STA has to