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
This commit is contained in:
Prakash Dhavali
2016-11-14 16:22:53 -08:00
committed by qcabuildsw
parent b0888ed295
commit 87b38e339c
2 changed files with 73 additions and 32 deletions

View File

@@ -61,6 +61,18 @@ enum hdd_ipa_wlan_event {
/* Include files */ /* Include files */
#include <wlan_hdd_assoc.h> /* hdd_context_t */ #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 * FIXME: Temporary hack - until IPA functionality gets restored
* *

View File

@@ -54,6 +54,7 @@
#include "wma.h" #include "wma.h"
#include "wma_api.h" #include "wma_api.h"
#include "wal_rx_desc.h"
#include "cdp_txrx_ipa.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 \ #define HDD_IPA_UC_WLAN_HDR_DES_MAC_OFFSET \
(HDD_IPA_WLAN_FRAG_HEADER + HDD_IPA_WLAN_IPA_HEADER) (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) \ #define HDD_IPA_GET_IFACE_ID(_data) \
(((struct hdd_ipa_cld_hdr *) (_data))->iface_id) (((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, static void hdd_ipa_forward(struct hdd_ipa_priv *hdd_ipa,
hdd_adapter_t *adapter, qdf_nbuf_t skb) hdd_adapter_t *adapter, qdf_nbuf_t skb)
{ {
qdf_nbuf_t copy;
struct hdd_ipa_pm_tx_cb *pm_tx_cb; 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); qdf_spin_lock_bh(&hdd_ipa->pm_lock);
/* WLAN subsystem is in suspend, put int queue */ /* WLAN subsystem is in suspend, put int queue */
if (hdd_ipa->suspended) { if (hdd_ipa->suspended) {
qdf_spin_unlock_bh(&hdd_ipa->pm_lock); qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
"TX in SUSPEND PUT QUEUE"); "TX in SUSPEND PUT QUEUE");
qdf_mem_set(copy->cb, sizeof(copy->cb), 0); qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
pm_tx_cb = (struct hdd_ipa_pm_tx_cb *)copy->cb; pm_tx_cb = (struct hdd_ipa_pm_tx_cb *)skb->cb;
pm_tx_cb->exception = true; pm_tx_cb->exception = true;
pm_tx_cb->adapter = adapter; pm_tx_cb->adapter = adapter;
qdf_spin_lock_bh(&hdd_ipa->pm_lock); 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); qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
hdd_ipa->stats.num_tx_queued++; hdd_ipa->stats.num_tx_queued++;
} else { } else {
/* Resume, put packet into WLAN TX */ /* Resume, put packet into WLAN TX */
qdf_spin_unlock_bh(&hdd_ipa->pm_lock); 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, HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
"packet tx fail"); "packet tx fail");
hdd_ipa->stats.num_tx_bcmc_err++;
} else { } else {
hdd_ipa->stats.num_tx_bcmc++; hdd_ipa->stats.num_tx_bcmc++;
hdd_ipa->ipa_tx_forward++; 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 * hdd_ipa_w2i_cb() - WLAN to IPA callback handler
* @priv: pointer to private data registered with IPA (we register a * @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. * only when DISCARD bit is not set.
*/ */
fw_desc = (uint8_t)skb->cb[1]; fw_desc = (uint8_t)skb->cb[1];
if (fw_desc & HDD_IPA_FW_RX_DESC_FORWARD_M) { if (HDD_IPA_FORWARD_PKT_DISCARD ==
HDD_IPA_DP_LOG( hdd_ipa_intrabss_forward(hdd_ipa, adapter,
QDF_TRACE_LEVEL_DEBUG, fw_desc, skb))
"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);
break; break;
}
} else { } else {
HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO_HIGH, HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO_HIGH,
"Intra-BSS FWD is disabled-skip forward to Tx"); "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; QDF_STATUS status = QDF_STATUS_SUCCESS;
iface_context = (struct hdd_ipa_iface_context *)priv; 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) { if (evt != IPA_RECEIVE) {
skb = (qdf_nbuf_t) data; HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Event is not IPA_RECEIVE");
dev_kfree_skb_any(skb); ipa_free_skb(ipa_tx_desc);
iface_context->stats.num_tx_drop++; iface_context->stats.num_tx_drop++;
return; 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. * 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 * During SSR, there is no use in queueing the packets as STA has to