From 87b38e339c61e8d80e956bcc553459f54dd56485 Mon Sep 17 00:00:00 2001 From: Prakash Dhavali Date: Mon, 14 Nov 2016 16:22:53 -0800 Subject: [PATCH] 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 --- core/hdd/inc/wlan_hdd_ipa.h | 12 +++++ core/hdd/src/wlan_hdd_ipa.c | 93 ++++++++++++++++++++++++------------- 2 files changed, 73 insertions(+), 32 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_ipa.h b/core/hdd/inc/wlan_hdd_ipa.h index 8b1272cc0c..6e68f4e01c 100644 --- a/core/hdd/inc/wlan_hdd_ipa.h +++ b/core/hdd/inc/wlan_hdd_ipa.h @@ -61,6 +61,18 @@ enum hdd_ipa_wlan_event { /* Include files */ #include /* 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 * diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 27736c9a41..0a572dc8ac 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/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