summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPrakash Dhavali <pdhavali@qca.qualcomm.com>2014-01-31 11:57:25 -0800
committerPrakash Dhavali <pdhavali@qca.qualcomm.com>2014-01-31 17:28:12 -0800
commit2356510be4eb29bb83d803483cf9669a23e8217a (patch)
tree3bac207b2258c48b9a3b533519a360d9e5b7bff6
parente3ecf322a421590b47f208bbeea2be278e16d448 (diff)
Revert "qcacld:ipa: WLAN-IPA TX Optimization"
This reverts commit 85003f4d407e65c8154d2686810e68d894646339 This got a duplicate commit due to missing change-id from git merge from detached head. This is actually revert of this change which actually reverted: https://review-android.quicinc.com/#/c/583655/ Change-Id: I3dc379d9f9deb00d8eb1177a3690d11b5a90a5e4
-rw-r--r--CORE/CLD_TXRX/TLSHIM/tl_shim.c38
-rw-r--r--CORE/HDD/src/wlan_hdd_ipa.c692
-rw-r--r--CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h7
-rw-r--r--CORE/TL/inc/wlan_qct_tl.h33
4 files changed, 486 insertions, 284 deletions
diff --git a/CORE/CLD_TXRX/TLSHIM/tl_shim.c b/CORE/CLD_TXRX/TLSHIM/tl_shim.c
index 53e6d91e6395..9e312854d4b5 100644
--- a/CORE/CLD_TXRX/TLSHIM/tl_shim.c
+++ b/CORE/CLD_TXRX/TLSHIM/tl_shim.c
@@ -862,19 +862,7 @@ adf_nbuf_t WLANTL_SendSTA_DataFrame(void *vos_ctx, u_int8_t sta_id,
}
/* Zero out skb's context buffer for the driver to use */
-#ifdef IPA_OFFLOAD
- if ((NBUF_OWNER_ID(skb) == IPA_NBUF_OWNER_ID)
- && NBUF_CALLBACK_FN(skb)) {
- uint32_t skb_owner_id = NBUF_OWNER_ID(skb);
- __adf_nbuf_callback_fn skb_cb_fn = NBUF_CALLBACK_FN(skb);
- adf_os_mem_set(skb->cb, 0, sizeof(skb->cb));
- NBUF_OWNER_ID(skb) = skb_owner_id;
- NBUF_CALLBACK_FN(skb) = skb_cb_fn;
- } else
- adf_os_mem_set(skb->cb, 0, sizeof(skb->cb));
-#else
adf_os_mem_set(skb->cb, 0, sizeof(skb->cb));
-#endif
adf_nbuf_map_single(adf_ctx, skb, ADF_OS_DMA_TO_DEVICE);
if ((tl_shim->ip_checksum_offload) && (skb->protocol == htons(ETH_P_IP))
@@ -893,6 +881,32 @@ adf_nbuf_t WLANTL_SendSTA_DataFrame(void *vos_ctx, u_int8_t sta_id,
return NULL;
}
+#ifdef IPA_OFFLOAD
+adf_nbuf_t WLANTL_SendIPA_DataFrame(void *vos_ctx, void *vdev,
+ adf_nbuf_t skb)
+{
+ struct txrx_tl_shim_ctx *tl_shim = vos_get_context(VOS_MODULE_ID_TL,
+ vos_ctx);
+ adf_nbuf_t ret;
+
+ ENTER();
+
+ if ((tl_shim->ip_checksum_offload) && (skb->protocol == htons(ETH_P_IP))
+ && (skb->ip_summed == CHECKSUM_PARTIAL))
+ skb->ip_summed = CHECKSUM_COMPLETE;
+
+ /* Terminate the (single-element) list of tx frames */
+ skb->next = NULL;
+ ret = tl_shim->tx((struct ol_txrx_vdev_t *)vdev, skb);
+ if (ret) {
+ TLSHIM_LOGW("Failed to tx");
+ return ret;
+ }
+
+ return NULL;
+}
+#endif
+
VOS_STATUS WLANTL_ResumeDataTx(void *vos_ctx, u_int8_t *sta_id)
{
return VOS_STATUS_SUCCESS;
diff --git a/CORE/HDD/src/wlan_hdd_ipa.c b/CORE/HDD/src/wlan_hdd_ipa.c
index 4c065c248275..2b4e5b301738 100644
--- a/CORE/HDD/src/wlan_hdd_ipa.c
+++ b/CORE/HDD/src/wlan_hdd_ipa.c
@@ -47,65 +47,68 @@ Include Files
#include <linux/skbuff.h>
#include <linux/list.h>
#include <linux/debugfs.h>
+#include <wlan_hdd_softap_tx_rx.h>
+
+#include "vos_sched.h"
+#include "wlan_qct_tl.h"
+#include "ol_txrx_peer_find.h"
+#include "tl_shim.h"
#define HDD_IPA_DESC_BUFFER_RATIO 4
#define HDD_IPA_IPV4_NAME_EXT "_ipv4"
#define HDD_IPA_IPV6_NAME_EXT "_ipv6"
#define HDD_IPA_RX_INACTIVITY_MSEC_DELAY 2000
-
-const uint8_t ipa_set_tx_hdr[] = {
-/*IPA-WLAN HDR */
- 0x00, 0x00, /* Reserved */
-#define HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET 2
-#define HDD_IPA_WLAN_HDR_DEV_TYPE_MASK 0x80
-#define HDD_IPA_WLAN_HDR_DEV_TYPE_AP 0x80
-#define HDD_IPA_WLAN_HDR_DEV_TYPE_STA 0x00
-#define HDD_IPA_WLAN_HDR_DEV_ID_MASK 0x7F
+#define HDD_IPA_WLAN_HDR_ONLY_LEN 4
#define HDD_IPA_WLAN_HDR_STA_ID_OFFSET 3
- 0x00, 0x00,
- /* dev_id and sta_id filled by wlan*/
-
- /* 802.3 header - 14 bytes*/
-#define HDD_IPA_WLAN_HDR_DES_MAC_OFFSET 4
- 0x00, 0x03, 0x7f, 0xaa, 0xbb, 0xcc,
- /* Des_MAC filled by IPA */
-#define HDD_IPA_WLAN_HDR_SRC_MAC_OFFSET 10
- 0x00, 0x03, 0x7f, 0xdd, 0xee, 0xff,
- /* Src. MAC filled by IPA */
- 0x00, 0x00,
- /* length can be zero */
-
- 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00,
+#define HDD_IPA_WLAN_HDR_DES_MAC_OFFSET 0
+
+struct llc_snap_hdr {
+ uint8_t dsap;
+ uint8_t ssap;
+ uint8_t resv[4];
+ __be16 eth_type;
+} __packed;
+
+struct ipa_tx_hdr {
+ struct ethhdr eth;
+ struct llc_snap_hdr llc_snap;
+} __packed;
+
+/* For Tx pipes, use 802.3 Header format */
+struct ipa_tx_hdr ipa_set_tx_hdr = {
+ {
+ {0x00, 0x03, 0x7f, 0xaa, 0xbb, 0xcc}, /* Des_MAC filled by IPA */
+ {0x00, 0x03, 0x7f, 0xdd, 0xee, 0xff}, /* Src. MAC filled by IPA */
+ 0x00 /* length can be zero */
+ },
+ {
/* LLC SNAP header 8 bytes */
-#define HDD_IPA_WLAN_TX_HDR_IP_VER_OFFSET 24
- 0x08, 0x00
- /* type value(2 bytes) ,filled by wlan */
- /* 0x0800 - IPV4, 0x86dd - IPV6 */
+ 0xaa, 0xaa,
+ {0x03, 0x00, 0x00, 0x00},
+ 0x0008 /* type value(2 bytes) ,filled by wlan */
+ /* 0x0800 - IPV4, 0x86dd - IPV6 */
+ }
};
-// For Rx pipe, use Ethernet-II Header format
-const uint8_t ipa_set_rx_hdr[] = {
- 0x00, 0x00, /* Reserved */
- 0x00, 0x00,
- /* dev_id and sta_id filled by wlan*/
-
- /* 802.3 header - 14 bytes*/
- 0x00, 0x03, 0x7f, 0xaa, 0xbb, 0xcc,
- /* Des_MAC filled by IPA */
- 0x00, 0x03, 0x7f, 0xdd, 0xee, 0xff,
- /* Src. MAC filled by IPA */
-#define HDD_IPA_WLAN_RX_HDR_IP_VER_OFFSET 16
- 0x08, 0x00
- /* type value(2 bytes) ,filled by wlan */
- /* 0x0800 - IPV4, 0x86dd - IPV6 */
+struct ipa_rx_hdr {
+ uint8_t hdr[HDD_IPA_WLAN_HDR_ONLY_LEN];
+ struct ethhdr eth;
+} __packed;
+
+/* For Rx pipe, use Ethernet-II Header format */
+struct ipa_rx_hdr ipa_set_rx_hdr = {
+ {0x00, 0x00, 0x00, 0x00}, /* 4 bytes header */
+ {
+ {0x00, 0x03, 0x7f, 0xaa, 0xbb, 0xcc}, /* Des_MAC filled by IPA */
+ {0x00, 0x03, 0x7f, 0xdd, 0xee, 0xff}, /* Src. MAC filled by IPA */
+ 0x0008 /* type value(2 bytes) ,filled by wlan */
+ /* 0x0800 - IPV4, 0x86dd - IPV6 */
+ }
};
-
#define HDD_IPA_WLAN_TX_HDR_LEN sizeof(ipa_set_tx_hdr)
#define HDD_IPA_WLAN_RX_HDR_LEN sizeof(ipa_set_rx_hdr)
-#define HDD_IPA_WLAN_HDR_ONLY_LEN 4
-#define HDD_IPA_MAX_TX_PIPE_MAP 8
#define HDD_IPA_WLAN_HDR_PARTIAL 1
#define HDD_IPA_LOG(LVL, fmt, args...) VOS_TRACE(VOS_MODULE_ID_HDD, LVL, \
@@ -119,10 +122,9 @@ enum hdd_ipa_rm_state {
};
enum hdd_ipa_pipe_index {
- HDD_IPA_TX_VI_PIPE,
- HDD_IPA_TX_VO_PIPE,
- HDD_IPA_TX_BE_PIPE,
- HDD_IPA_TX_BK_PIPE,
+ HDD_IPA_TX_WLAN0_PIPE,
+ HDD_IPA_TX_WLAN1_PIPE,
+ HDD_IPA_TX_WLAN2_PIPE,
HDD_IPA_RX_PIPE,
HDD_IPA_MAX_PIPE
};
@@ -132,38 +134,22 @@ enum hdd_ipa_ip_ver {
HDD_IPA_IPV6 = 2
};
-uint8_t hdd_ipa_pipe_client[HDD_IPA_MAX_PIPE] = {
+#define HDD_IPA_WLAN_MAX_STA_ID 255
+
+uint8_t wlan_sta_id_2_hdd_pipe_id[HDD_IPA_WLAN_MAX_STA_ID] = {0xFF};
+
+uint8_t hdd_pipe_id_2_ipa_client_id[HDD_IPA_MAX_PIPE] = {
IPA_CLIENT_WLAN1_CONS,
IPA_CLIENT_WLAN2_CONS,
IPA_CLIENT_WLAN3_CONS,
- IPA_CLIENT_WLAN4_CONS,
IPA_CLIENT_WLAN1_PROD
};
-uint8_t hdd_ipa_pipe_client_AC[] = {
- HDD_LINUX_AC_VI,
- HDD_LINUX_AC_VO,
- HDD_LINUX_AC_BE,
- HDD_LINUX_AC_BK
-};
-
-static struct hdd_ipa_tx_pipe_map{
- uint8_t tos_value;
- enum ipa_client_type client;
- uint8_t ac;
-} hdd_ipa_tx_pipe_map_info[HDD_IPA_MAX_TX_PIPE_MAP] = {
- /* BK */
- {1, IPA_CLIENT_WLAN1_CONS, HDD_LINUX_AC_BK},
- {2, IPA_CLIENT_WLAN1_CONS, HDD_LINUX_AC_BK},
- /* BE */
- {0, IPA_CLIENT_WLAN2_CONS, HDD_LINUX_AC_BE},
- {3, IPA_CLIENT_WLAN2_CONS, HDD_LINUX_AC_BE},
- /* VI */
- {4, IPA_CLIENT_WLAN3_CONS, HDD_LINUX_AC_VI},
- {5, IPA_CLIENT_WLAN3_CONS, HDD_LINUX_AC_VI},
- /* VO */
- {6, IPA_CLIENT_WLAN4_CONS, HDD_LINUX_AC_VO},
- {7, IPA_CLIENT_WLAN4_CONS, HDD_LINUX_AC_VO},
+uint8_t ipa_client_id_2_hdd_pipe_id[IPA_CLIENT_MAX] = {
+ [IPA_CLIENT_WLAN1_CONS] = HDD_IPA_TX_WLAN0_PIPE,
+ [IPA_CLIENT_WLAN2_CONS] = HDD_IPA_TX_WLAN1_PIPE,
+ [IPA_CLIENT_WLAN3_CONS] = HDD_IPA_TX_WLAN2_PIPE,
+ [IPA_CLIENT_WLAN1_PROD] = HDD_IPA_RX_PIPE
};
struct hdd_ipa_sys_pipe {
@@ -185,6 +171,8 @@ struct hdd_ipa_priv {
struct list_head free_desc_head;
struct list_head pend_desc_head;
+ struct ol_txrx_vdev_t *pipe_to_vdev[HDD_IPA_MAX_PIPE];
+
hdd_context_t *hdd_ctx;
struct dentry *debugfs_dir;
@@ -201,7 +189,6 @@ struct hdd_ipa_priv {
uint64_t rx_ipa_hw_maxed_out;
- uint64_t tx_ipa_recv;
uint64_t freeq_empty;
uint64_t freeq_cnt;
@@ -224,7 +211,11 @@ struct hdd_ipa_priv {
uint64_t rx_ipa_dh_reclaim;
uint64_t rx_ipa_dh_not_used;
#endif
- }stats;
+ uint64_t ipa_lb_cnt;
+ uint64_t tx_ipa_recv;
+ uint64_t tx_comp_cnt;
+ uint64_t tx_dp_err_cnt;
+ } stats;
};
enum hdd_ipa_evt {
@@ -256,13 +247,13 @@ static inline void *hdd_ipa_kzalloc(uint32_t size)
return data;
}
-static inline struct ipa_tx_data_desc * hdd_ipa_get_desc_from_freeq(void)
+static inline struct ipa_tx_data_desc *hdd_ipa_get_desc_from_freeq(void)
{
struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
struct ipa_tx_data_desc *desc = NULL;
spin_lock_bh(&ghdd_ipa->q_lock);
- if(!list_empty(&ghdd_ipa->free_desc_head)) {
+ if (!list_empty(&ghdd_ipa->free_desc_head)) {
desc = list_first_entry(&ghdd_ipa->free_desc_head, struct ipa_tx_data_desc, link);
list_del(&desc->link);
hdd_ipa->stats.freeq_cnt--;
@@ -417,7 +408,9 @@ void hdd_ipa_send_skb_to_network(adf_nbuf_t skb, hdd_adapter_t *adap_dev)
{
if (!adap_dev || (adap_dev &&
adap_dev->magic != WLAN_HDD_ADAPTER_MAGIC)) {
- HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Invalid sta_id");
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Invalid adapter: adap=0x%x",
+ adap_dev);
+
adf_nbuf_free(skb);
return;
}
@@ -438,8 +431,10 @@ static void hdd_ipa_send_pkt_to_ipa(struct ipa_tx_data_desc *send_desc_head,
int send_desc_cnt)
{
struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
- struct ipa_tx_data_desc *send_desc;
+ struct ipa_tx_data_desc *send_desc, *desc, *tmp;
uint32_t cur_send_cnt = 0;
+ adf_nbuf_t buf;
+
#ifndef HDD_IPA_USE_IPA_RM_TIMER
if (hdd_ipa->rm_timer_on) {
del_timer(&hdd_ipa->rm_timer);
@@ -480,12 +475,42 @@ static void hdd_ipa_send_pkt_to_ipa(struct ipa_tx_data_desc *send_desc_head,
cur_send_cnt = send_desc_cnt;
}
hdd_ipa->stats.rx_ipa_sent_desc_cnt += cur_send_cnt;
+
+#ifdef HDD_IPA_EXTRA_DP_COUNTERS
+ hdd_ipa->stats.rx_ipa_dh_sent++; /* for desc head */
+#endif
spin_unlock_bh(&hdd_ipa->q_lock);
+ if (ipa_tx_dp_mul(hdd_pipe_id_2_ipa_client_id[HDD_IPA_RX_PIPE],
+ send_desc_head) != 0) {
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "ipa_tx_dp_mul failed!!! (cur_send_cnt=%d)", cur_send_cnt);
+ hdd_ipa->stats.tx_dp_err_cnt++;
+ spin_lock_bh(&hdd_ipa->q_lock);
+
+ list_for_each_entry_safe(desc, tmp,
+ &send_desc_head->link, link) {
+ list_del(&desc->link);
+ buf = desc->priv;
+ adf_nbuf_free(buf);
+ desc->priv = NULL;
+ desc->pyld_buffer = NULL;
+ desc->pyld_len = 0;
+ list_add_tail(&desc->link, &hdd_ipa->free_desc_head);
+ hdd_ipa->stats.freeq_cnt++;
+#ifdef HDD_IPA_EXTRA_DP_COUNTERS
+ hdd_ipa->stats.freeq_reclaim++;
+#endif
+ hdd_ipa->pending_desc_cnt--;
+ }
+
+ /* return anchor node */
+ list_add_tail(&send_desc_head->link, &hdd_ipa->free_desc_head);
+ hdd_ipa->stats.freeq_cnt++;
#ifdef HDD_IPA_EXTRA_DP_COUNTERS
- hdd_ipa->stats.rx_ipa_dh_sent++; //for desc head
+ hdd_ipa->stats.rx_ipa_dh_reclaim++;
+ hdd_ipa->stats.freeq_reclaim++;
#endif
- ipa_tx_dp_mul(hdd_ipa_pipe_client[HDD_IPA_RX_PIPE],
- send_desc_head);
+ spin_unlock_bh(&hdd_ipa->q_lock);
+ }
} else {
#ifdef HDD_IPA_EXTRA_DP_COUNTERS
hdd_ipa->stats.rx_ipa_hw_max_qued += send_desc_cnt;
@@ -508,12 +533,6 @@ static void hdd_ipa_send_pkt_to_ipa(struct ipa_tx_data_desc *send_desc_head,
static int hdd_ipa_is_ip_pkt(void *data, uint8_t ip_ver)
{
struct ethhdr *eth = (struct ethhdr *)data;
- struct llc_snap_hdr {
- uint8_t dsap;
- uint8_t ssap;
- uint8_t resv[4];
- __be16 eth_type;
- } __packed;
struct llc_snap_hdr *ls_hdr;
uint16_t eth_type;
int ret = 0;
@@ -523,16 +542,14 @@ static int hdd_ipa_is_ip_pkt(void *data, uint8_t ip_ver)
/* Non Ethernet II framing format */
ls_hdr = (struct llc_snap_hdr *)((uint8_t *)data +
sizeof(struct ethhdr));
- /* TODO Is this needed
- if ((ls_hdr->dsap == 0xAA && ls_hdr->ssap == 0xAA) ||
- (ls_hdr->dsap == 0xAB && ls_hdr->ssap == 0xAB))
- */
- eth_type = be16_to_cpu(ls_hdr->eth_type);
+
+ if (((ls_hdr->dsap == 0xAA) && (ls_hdr->ssap == 0xAA)) ||
+ ((ls_hdr->dsap == 0xAB) && (ls_hdr->ssap == 0xAB)))
+ eth_type = be16_to_cpu(ls_hdr->eth_type);
}
- if ((eth_type == ETH_P_IP) && (ip_ver == HDD_IPA_IPV4))
- ret = 1;
- else if ((eth_type == ETH_P_IPV6) && (ip_ver == HDD_IPA_IPV6))
+ if (((eth_type == ETH_P_IP) && (ip_ver == HDD_IPA_IPV4)) ||
+ ((eth_type == ETH_P_IPV6) && (ip_ver == HDD_IPA_IPV6)))
ret = 1;
if (ret != 1)
@@ -550,7 +567,7 @@ static void hdd_ipa_process_evt(int evt, void *priv)
*done_desc_head, *done_desc, *tmp;
hdd_adapter_t *adap_dev = NULL;
adf_nbuf_t buf, next_buf;
- uint8_t dev_id, cur_cnt = 0, iftype;
+ uint8_t cur_cnt = 0;
switch (evt) {
case HDD_IPA_RXT_EVT:
@@ -571,8 +588,6 @@ static void hdd_ipa_process_evt(int evt, void *priv)
}
return;
}
- dev_id = adap_dev->dev->ifindex;
- iftype = adap_dev->wdev.iftype;
/* send_desc_head is a anchor node */
send_desc_head = hdd_ipa_get_desc_from_freeq();
if (!send_desc_head) {
@@ -625,19 +640,8 @@ static void hdd_ipa_process_evt(int evt, void *priv)
}
skb_push(buf, HDD_IPA_WLAN_HDR_ONLY_LEN);
- memset(buf->data, 0, HDD_IPA_WLAN_HDR_ONLY_LEN);
- buf->data[HDD_IPA_WLAN_HDR_STA_ID_OFFSET] = rxt->sta_id;
- buf->data[HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET] |=
- dev_id & HDD_IPA_WLAN_HDR_DEV_ID_MASK;
- if (iftype == NL80211_IFTYPE_AP ||
- iftype == NL80211_IFTYPE_P2P_GO) {
- buf->data[HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET] |=
- HDD_IPA_WLAN_HDR_DEV_TYPE_AP;
- } else {
- buf->data[HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET] |=
- HDD_IPA_WLAN_HDR_DEV_TYPE_STA;
- }
-
+ /* vos_mem_zero(((struct ipa_rx_hdr *)(buf->data))->hdr, HDD_IPA_WLAN_HDR_ONLY_LEN); */
+ ((struct ipa_rx_hdr *)(buf->data))->hdr[HDD_IPA_WLAN_HDR_STA_ID_OFFSET] = rxt->sta_id;
send_desc = hdd_ipa_get_desc_from_freeq();
if (send_desc) {
send_desc->priv = buf;
@@ -697,7 +701,7 @@ static void hdd_ipa_process_evt(int evt, void *priv)
HDD_IPA_RM_GRANT_PENDING);
hdd_ipa_rm_request(hdd_ipa);
}
- //hdd_ipa_rm_request can immediately grant so check again.
+ /* hdd_ipa_rm_request can immediately grant so check again. */
if (atomic_read(&hdd_ipa->rm_state)
== HDD_IPA_RM_GRANT_PENDING) {
spin_lock_bh(&hdd_ipa->q_lock);
@@ -706,6 +710,11 @@ static void hdd_ipa_process_evt(int evt, void *priv)
/* return anchor node */
list_add_tail(&send_desc_head->link,
&hdd_ipa->free_desc_head);
+ hdd_ipa->stats.freeq_cnt++;
+#ifdef HDD_IPA_EXTRA_DP_COUNTERS
+ hdd_ipa->stats.rx_ipa_dh_reclaim++;
+ hdd_ipa->stats.freeq_reclaim++;
+#endif
spin_unlock_bh(&hdd_ipa->q_lock);
#ifdef HDD_IPA_EXTRA_DP_COUNTERS
hdd_ipa->stats.rx_ipa_rm_qued += cur_cnt;
@@ -791,6 +800,7 @@ VOS_STATUS hdd_ipa_process_rxt(v_VOID_t *vosContext, adf_nbuf_t rx_buf_list,
rxt.sta_id = sta_id;
rxt.rx_buf_list = rx_buf_list;
+
hdd_ipa_process_evt(HDD_IPA_RXT_EVT, &rxt);
return VOS_STATUS_SUCCESS;
@@ -804,88 +814,174 @@ void hdd_ipa_w2i_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data)
uint8_t client;
struct ipa_tx_data_desc *done_desc_head;
adf_nbuf_t skb;
- uint8_t sta_id, dev_id;
+ uint8_t sta_id;
hdd_adapter_t *adap_dev=NULL;
client = *((uint8_t *)priv);
- if (client != hdd_ipa_pipe_client[HDD_IPA_RX_PIPE]) {
+ if (client != hdd_pipe_id_2_ipa_client_id[HDD_IPA_RX_PIPE]) {
HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR,
"w2i cb wrong pipe: %d %x %x",
client, priv,
- &hdd_ipa_pipe_client[HDD_IPA_RX_PIPE]);
+ &hdd_pipe_id_2_ipa_client_id[HDD_IPA_RX_PIPE]);
return;
}
switch (evt) {
case IPA_RECEIVE:
skb = (adf_nbuf_t) data;
- sta_id = skb->data[HDD_IPA_WLAN_HDR_STA_ID_OFFSET];
- dev_id = skb->data[HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET];
+ sta_id = ((struct ipa_rx_hdr *)(skb->data))->hdr[HDD_IPA_WLAN_HDR_STA_ID_OFFSET];
+
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, "w2i -- skb:0x%p: %02x %02x %02x %02x %02x %02x %02x %02x", skb,
+ skb->data[0], skb->data[1], skb->data[2], skb->data[3],
+ skb->data[4], skb->data[5], skb->data[6], skb->data[7]);
+
+ skb_pull(skb, HDD_IPA_WLAN_HDR_ONLY_LEN);
+
if (sta_id < ARRAY_SIZE(hdd_ipa->hdd_ctx->sta_to_adapter)) {
adap_dev = hdd_ipa->hdd_ctx->sta_to_adapter[sta_id];
} else {
HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR,
- "w2i cb: wrong sta_id: %d", sta_id);
+ "w2i cb: wrong sta_id: %d", sta_id);
}
- skb_pull(skb, HDD_IPA_WLAN_HDR_ONLY_LEN);
+
hdd_ipa->stats.rx_ipa_excep++;
hdd_ipa_send_skb_to_network(skb, adap_dev);
break;
case IPA_WRITE_DONE:
done_desc_head = (struct ipa_tx_data_desc *)data;
hdd_ipa_w2i_write_done_handler(done_desc_head);
- break;
+ break;
+ default:
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR,
+ "w2i cb wrong event: 0x%x", evt);
+ return;
}
}
void hdd_ipa_nbuf_cb(adf_nbuf_t skb)
{
- ipa_free_skb(skb);
+ struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
+
+ /* TX COMP counter at frame free location. */
+ hdd_ipa->stats.tx_comp_cnt++;
+
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, "0x%p", NBUF_OWNER_PRIV_DATA(skb));
+ ipa_free_skb((struct ipa_rx_data *) NBUF_OWNER_PRIV_DATA(skb));
}
-void hdd_ipa_tx_process(adf_nbuf_t skb, uint8_t ac)
+#ifdef WLAN_TX_MUL
+void hdd_ipa_i2w_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data)
{
struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
- uint8_t sta_id;
- hdd_adapter_t *adap_dev;
+ struct ipa_rx_data_mul *ipa_tx_desc;
+ adf_nbuf_t skb;
+ uint8_t client, pipe_id;
- skb->queue_mapping = ac;
- sta_id = skb->data[HDD_IPA_WLAN_HDR_STA_ID_OFFSET];
- adap_dev = hdd_ipa->hdd_ctx->sta_to_adapter[sta_id];
- if (!adap_dev
- || (adap_dev && adap_dev->magic != WLAN_HDD_ADAPTER_MAGIC)) {
- HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Invalid sta_id %d", sta_id);
- ipa_free_skb(skb);
- return;
+ if (evt == IPA_RECEIVE) {
+ client = *((uint8_t *)priv);
+ struct list_head *head = (struct list_head *)data;
+
+ pipe_id = ipa_client_id_2_hdd_pipe_id[client];
+
+ if (hdd_ipa->pipe_to_vdev[pipe_id] == NULL) {
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, "TLSHIM tx fail (vdev=NULL)");
+ /* TODO: need to free ipa_desc and skb here */
+ return;
+ }
+
+ list_for_each_entry(ipa_tx_desc, head, link) {
+ if (ipa_tx_desc->dd == NULL)
+ break;
+
+ /* TX frame Counter at HDD CB function called by IPA loopback, to push lower layer.*/
+ hdd_ipa->stats.tx_ipa_recv++;
+
+ skb = ipa_tx_desc->dd->skb;
+
+ /* skb->dev = ipa_client_id_2_hdd_pipe_id[client]; */
+ adf_os_mem_set(skb->cb, 0, sizeof(skb->cb));
+ NBUF_OWNER_ID(skb) = IPA_NBUF_OWNER_ID;
+ NBUF_CALLBACK_FN(skb) = hdd_ipa_nbuf_cb;
+ NBUF_MAPPED_PADDR_LO(skb) = ipa_tx_desc->dd->dma_addr;
+
+ NBUF_OWNER_PRIV_DATA(skb) = (unsigned long)ipa_tx_desc->dd;
+
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, "skb:0x%p: %02x %02x %02x %02x %02x %02x %02x %02x", skb,
+ skb->data[0], skb->data[1], skb->data[2], skb->data[3],
+ skb->data[4], skb->data[5], skb->data[6], skb->data[7]);
+
+ skb = WLANTL_SendIPA_DataFrame(hdd_ipa->hdd_ctx->pvosContext, hdd_ipa->pipe_to_vdev[pipe_id],
+ ipa_tx_desc->dd->skb);
+ if (skb) {
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, "TLSHIM tx fail");
+ ipa_free_skb(ipa_tx_desc->dd);
+ continue;
+ }
+ }
+ ipa_free_desc(data);
+
+ } else {
+ /* HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "i2w cb wrong evt: %d", evt);
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Testing hack code data path"); */
+ skb = (adf_nbuf_t) data;
+ dev_kfree_skb_any(skb);
}
- skb->dev = adap_dev->dev;
- NBUF_OWNER_ID(skb) = IPA_NBUF_OWNER_ID;
- NBUF_CALLBACK_FN(skb) = hdd_ipa_nbuf_cb;
- skb_pull(skb, HDD_IPA_WLAN_HDR_ONLY_LEN);
- (adap_dev->dev->netdev_ops->ndo_start_xmit)(skb, adap_dev->dev);
}
+#else
+
void hdd_ipa_i2w_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data)
{
struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
+ struct ipa_rx_data *ipa_tx_desc;
adf_nbuf_t skb;
- uint8_t client;
- uint8_t i, ac = HDD_LINUX_AC_BE;
+ uint8_t client, pipe_id;
if (evt == IPA_RECEIVE) {
+ /* TX frame Counter at HDD CB function called by IPA loopback, to push lower layer */
+ hdd_ipa->stats.tx_ipa_recv++;
+
client = *((uint8_t *)priv);
- skb = (adf_nbuf_t) data;
- for (i = 0; i < HDD_IPA_MAX_TX_PIPE_MAP; i++) {
- if (client == hdd_ipa_tx_pipe_map_info[i].client) {
- ac = hdd_ipa_tx_pipe_map_info[i].ac;
- break;
- }
+ ipa_tx_desc = (struct ipa_rx_data *)data;
+ skb = ipa_tx_desc->skb;
+
+ adf_os_mem_set(skb->cb, 0, sizeof(skb->cb));
+ NBUF_OWNER_ID(skb) = IPA_NBUF_OWNER_ID;
+ NBUF_CALLBACK_FN(skb) = hdd_ipa_nbuf_cb;
+ NBUF_MAPPED_PADDR_LO(skb) = ipa_tx_desc->dma_addr;
+
+ NBUF_OWNER_PRIV_DATA(skb) = data;
+
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, "0x%p", NBUF_OWNER_PRIV_DATA(skb));
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, "skb:0x%p: %02x %02x %02x %02x %02x %02x %02x %02x", skb,
+ skb->data[0], skb->data[1], skb->data[2], skb->data[3],
+ skb->data[4], skb->data[5], skb->data[6], skb->data[7]);
+
+ pipe_id = ipa_client_id_2_hdd_pipe_id[client];
+
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, "client=%d, pipe_to_vdev[%d]=0x%x", client, pipe_id, hdd_ipa->pipe_to_vdev[pipe_id]);
+
+ if (hdd_ipa->pipe_to_vdev[pipe_id] == NULL) {
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, "TLSHIM tx fail (pipe_to_vdev[%d]=NULL)", pipe_id);
+ ipa_free_skb(ipa_tx_desc);
+ return;
}
- hdd_ipa->stats.tx_ipa_recv++;
- hdd_ipa_tx_process(skb, ac);
- } else
- HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "i2w cb wrong evt: %d", evt);
+
+ skb = WLANTL_SendIPA_DataFrame(hdd_ipa->hdd_ctx->pvosContext, hdd_ipa->pipe_to_vdev[pipe_id],
+ ipa_tx_desc->skb);
+ if (skb) {
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, "TLSHIM tx fail");
+ ipa_free_skb(ipa_tx_desc);
+ return;
+ }
+ } else {
+ /* HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "i2w cb wrong evt: %d", evt);
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Testing hack code data path"); */
+ skb = (adf_nbuf_t) data;
+ dev_kfree_skb_any(skb);
+ }
}
+#endif
static int hdd_ipa_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa)
{
@@ -896,9 +992,9 @@ static int hdd_ipa_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa)
for (i = 0; i < HDD_IPA_RX_PIPE; i++) {
ipa = &hdd_ipa->sys_pipe[i].ipa_sys_params;
- ipa->client = hdd_ipa_pipe_client[i];
+ ipa->client = hdd_pipe_id_2_ipa_client_id[i];
ipa->desc_fifo_sz = hdd_ipa->hdd_ctx->cfg_ini->IpaDescSize;
- ipa->priv = &hdd_ipa_pipe_client[i];
+ ipa->priv = &hdd_pipe_id_2_ipa_client_id[i];
ipa->notify = hdd_ipa_i2w_cb;
ipa->ipa_ep_cfg.hdr.hdr_len = HDD_IPA_WLAN_TX_HDR_LEN;
@@ -914,9 +1010,9 @@ static int hdd_ipa_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa)
ipa = &hdd_ipa->sys_pipe[HDD_IPA_RX_PIPE].ipa_sys_params;
- ipa->client = hdd_ipa_pipe_client[HDD_IPA_RX_PIPE];
- ipa->desc_fifo_sz = hdd_ipa->hdd_ctx->cfg_ini->IpaDescSize;
- ipa->priv = &hdd_ipa_pipe_client[HDD_IPA_RX_PIPE];
+ ipa->client = hdd_pipe_id_2_ipa_client_id[HDD_IPA_RX_PIPE];
+ ipa->desc_fifo_sz = hdd_ipa->hdd_ctx->cfg_ini->IpaDescSize + sizeof(struct sps_iovec); /* To make sure total # of desc is 1 less than the desc FIFO size */
+ ipa->priv = &hdd_pipe_id_2_ipa_client_id[HDD_IPA_RX_PIPE];
ipa->notify = hdd_ipa_w2i_cb;
ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
@@ -952,10 +1048,8 @@ void hdd_ipa_teardown_sys_pipe(struct hdd_ipa_priv *hdd_ipa)
}
}
-int hdd_ipa_register_interface(struct hdd_ipa_priv *hdd_ipa, uint8_t iftype,
- uint8_t sta_id, const char *ifname)
+int hdd_ipa_register_interface(struct hdd_ipa_priv *hdd_ipa, uint8_t sta_id, const char *ifname)
{
-#define HDD_IPA_TOS_MASK 0xE0
struct ipa_tx_intf tx_intf;
struct ipa_rx_intf rx_intf;
struct ipa_ioc_tx_intf_prop *tx_prop = NULL;
@@ -964,23 +1058,21 @@ int hdd_ipa_register_interface(struct hdd_ipa_priv *hdd_ipa, uint8_t iftype,
char ipv4_hdr_name[IPA_RESOURCE_NAME_MAX];
char ipv6_hdr_name[IPA_RESOURCE_NAME_MAX];
- int i, j, ip_max = HDD_IPA_IPV4;
+ int ip_max = HDD_IPA_IPV4;
int ret = 0;
if (hdd_ipa_is_ipv6_enabled(hdd_ipa))
ip_max = HDD_IPA_IPV6;
/* Allocate TX properties for TOS categories, 1 each for IPv4 & IPv6 */
- tx_prop = hdd_ipa_kzalloc(sizeof(struct ipa_ioc_tx_intf_prop) *
- HDD_IPA_MAX_TX_PIPE_MAP * ip_max);
+ tx_prop = hdd_ipa_kzalloc(sizeof(struct ipa_ioc_tx_intf_prop) * ip_max);
if (!tx_prop) {
HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "ENOMEM");
goto register_interface_fail;
}
/* Allocate RX properties, 1 each for IPv4 & IPv6 */
- rx_prop = hdd_ipa_kzalloc(sizeof(struct ipa_ioc_rx_intf_prop)
- * ip_max);
+ rx_prop = hdd_ipa_kzalloc(sizeof(struct ipa_ioc_rx_intf_prop) * ip_max);
if (!rx_prop) {
HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "ENOMEM");
goto register_interface_fail;
@@ -990,72 +1082,28 @@ int hdd_ipa_register_interface(struct hdd_ipa_priv *hdd_ipa, uint8_t iftype,
snprintf(ipv4_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s",
ifname, HDD_IPA_IPV4_NAME_EXT);
+ snprintf(ipv6_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s",
+ ifname, HDD_IPA_IPV6_NAME_EXT);
+
rx_prop[IPA_IP_v4].ip = IPA_IP_v4;
+ rx_prop[IPA_IP_v4].src_pipe = IPA_CLIENT_WLAN1_PROD;
+ rx_intf.num_props++;
if (hdd_ipa_is_ipv6_enabled(hdd_ipa)) {
- snprintf(ipv6_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s",
- ifname, HDD_IPA_IPV6_NAME_EXT);
rx_prop[IPA_IP_v6].ip = IPA_IP_v6;
+ rx_prop[IPA_IP_v6].src_pipe = IPA_CLIENT_WLAN1_PROD;
+ rx_intf.num_props++;
}
- /*
- TOS value: 1, 2 - > Maps to BK pipe [WLAN1_CONS]
- TOS value: 0, 3 - > Maps to BE pipe [WLAN2_CONS]
- TOS value: 4, 5 - > Maps to VI pipe [WLAN3_CONS]
- TOS Value: 6, 7 - > Maps to VO pipe [WLAN4_CONS]
- */
-
- /*
- IP-TOS - 8bits
- : DSCP(6-bits) ECN(2-bits)
- : DSCP - P2 P1 P0 X X X
- where (P2 P1 P0) form 802.1D
- So shifting tos_value by 5 bits before passing to IPA. Also IPA
- required mask to be set for 3 MSB bits.
- */
-
- for (i = 0; i < HDD_IPA_MAX_TX_PIPE_MAP; i++) {
- tx_prop[i].ip = IPA_IP_v4;
- tx_prop[i].attrib.attrib_mask = IPA_FLT_TOS_MASKED;
- tx_prop[i].attrib.tos_value =
- hdd_ipa_tx_pipe_map_info[i].tos_value << 5;
- tx_prop[i].attrib.tos_mask = HDD_IPA_TOS_MASK;
- tx_prop[i].dst_pipe = hdd_ipa_tx_pipe_map_info[i].client;
- strlcpy(tx_prop[i].hdr_name, ipv4_hdr_name,
- IPA_RESOURCE_NAME_MAX);
- tx_intf.num_props++;
- if (hdd_ipa_is_ipv6_enabled(hdd_ipa)) {
- j = i + HDD_IPA_MAX_TX_PIPE_MAP;
-
- tx_prop[j].ip = IPA_IP_v6;
- tx_prop[j].attrib.attrib_mask = IPA_FLT_TOS_MASKED;
- tx_prop[j].attrib.tos_value =
- hdd_ipa_tx_pipe_map_info[i].tos_value << 5;
- tx_prop[j].attrib.tos_mask = HDD_IPA_TOS_MASK;
- tx_prop[j].dst_pipe =
- hdd_ipa_tx_pipe_map_info[i].client;
- strlcpy(tx_prop[j].hdr_name, ipv6_hdr_name,
- IPA_RESOURCE_NAME_MAX);
- tx_intf.num_props++;
- }
- }
-
- for (i = 0; i < ip_max; i++) {
- rx_prop[i].attrib.attrib_mask = IPA_FLT_META_DATA;
- if (iftype == NL80211_IFTYPE_AP ||
- iftype == NL80211_IFTYPE_P2P_GO) {
- rx_prop[i].attrib.meta_data =
- HDD_IPA_WLAN_HDR_DEV_TYPE_AP
- << ((HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET-1) * 8);
- } else {
- rx_prop[i].attrib.meta_data =
- HDD_IPA_WLAN_HDR_DEV_TYPE_STA
- << ((HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET-1) * 8);
- }
- rx_prop[i].attrib.meta_data_mask =
- HDD_IPA_WLAN_HDR_DEV_TYPE_MASK
- << ((HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET-1) * 8);
- rx_prop[i].src_pipe = IPA_CLIENT_WLAN1_PROD;
- rx_intf.num_props++;
+ tx_prop[IPA_IP_v4].ip = IPA_IP_v4;
+ tx_prop[IPA_IP_v4].dst_pipe = hdd_pipe_id_2_ipa_client_id[wlan_sta_id_2_hdd_pipe_id[sta_id]];
+ strlcpy(tx_prop[IPA_IP_v4].hdr_name, ipv4_hdr_name, IPA_RESOURCE_NAME_MAX);
+ tx_intf.num_props++;
+ if (hdd_ipa_is_ipv6_enabled(hdd_ipa)) {
+ tx_prop[IPA_IP_v6].ip = IPA_IP_v6;
+ tx_prop[IPA_IP_v6].dst_pipe = hdd_pipe_id_2_ipa_client_id[wlan_sta_id_2_hdd_pipe_id[sta_id]];
+ strlcpy(tx_prop[IPA_IP_v6].hdr_name, ipv6_hdr_name,
+ IPA_RESOURCE_NAME_MAX);
+ tx_intf.num_props++;
}
tx_intf.prop = tx_prop;
@@ -1070,14 +1118,15 @@ register_interface_fail:
return ret;
}
-static int hdd_ipa_add_header_info(uint8_t sta_id, uint8_t *mac_addr)
+static int hdd_ipa_add_header_info(enum ipa_wlan_event type, uint8_t sta_id, uint8_t *mac_addr)
{
struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
- uint8_t dev_id, wlan_iftype;
char *ifname;
struct ipa_ioc_add_hdr *ipahdr = NULL;
- int ret = -EINVAL;
+ int i, ret = -EINVAL;
hdd_adapter_t *adap_dev;
+ struct ol_txrx_pdev_t *pdev;
+ struct ol_txrx_vdev_t *vdev;
adap_dev = hdd_ipa->hdd_ctx->sta_to_adapter[sta_id];
if (!adap_dev) {
@@ -1085,12 +1134,40 @@ static int hdd_ipa_add_header_info(uint8_t sta_id, uint8_t *mac_addr)
goto add_header_info_ctx_fail;
}
- dev_id = adap_dev->dev->ifindex;
- wlan_iftype = adap_dev->wdev.iftype;
ifname = adap_dev->dev->name;
- HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "Mode: %d Add Partial hdr: %s, %p\n",
- wlan_iftype, ifname, mac_addr);
+ for (i = 0; i < HDD_IPA_MAX_PIPE; i++)
+ hdd_ipa->pipe_to_vdev[i] = NULL;
+
+ if (wlan_sta_id_2_hdd_pipe_id[sta_id] == 0xFF) {
+ switch (type) {
+ case WLAN_AP_CONNECT:
+ wlan_sta_id_2_hdd_pipe_id[sta_id] = HDD_IPA_TX_WLAN0_PIPE; /* TODO: need to expand to AP+AP */
+ break;
+ case WLAN_STA_CONNECT:
+ /* Register pipe_to_vdev for STA mode */
+ pdev = ((pVosContextType)(WLAN_HDD_GET_CTX(adap_dev)->pvosContext))->pdev_txrx_ctx;
+ /* find the "vdev" this STA interface belongs to */
+ TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
+ if (adf_os_mem_cmp(mac_addr, vdev->mac_addr.raw, IEEE80211_ADDR_LEN) == 0) {
+ hdd_ipa->pipe_to_vdev[HDD_IPA_TX_WLAN2_PIPE] = vdev;
+ break;
+ }
+ }
+
+ wlan_sta_id_2_hdd_pipe_id[sta_id] = HDD_IPA_TX_WLAN2_PIPE; /* STA Mode */
+ break;
+ default:
+ break;
+ }
+ }
+
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, " wlan_sta_id_2_hdd_pipe_id[%d]: %d",
+ sta_id, wlan_sta_id_2_hdd_pipe_id[sta_id]);
+
+
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "ifindex: %d Add Partial hdr: %s, %p\n",
+ sta_id, ifname, mac_addr);
if (ifname == NULL) {
HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "ifname NULL");
goto add_header_info_ctx_fail;
@@ -1107,29 +1184,19 @@ static int hdd_ipa_add_header_info(uint8_t sta_id, uint8_t *mac_addr)
ipahdr->commit = 0;
ipahdr->num_hdrs = 1;
/* Set the Source MAC */
- memcpy(ipahdr->hdr[0].hdr, ipa_set_tx_hdr, HDD_IPA_WLAN_TX_HDR_LEN);
- memcpy(&ipahdr->hdr[0].hdr[HDD_IPA_WLAN_HDR_SRC_MAC_OFFSET], mac_addr,
+ memcpy(ipahdr->hdr[0].hdr, (uint8_t *)&ipa_set_tx_hdr, HDD_IPA_WLAN_TX_HDR_LEN);
+ memcpy((uint8_t *)(((struct ipa_tx_hdr *)(ipahdr->hdr[0].hdr))->eth.h_source), mac_addr,
ETH_ALEN);
- /* Check the interface is AP OR STA mode, and set the station ID */
- ipahdr->hdr[0].hdr[HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET] |=
- dev_id & HDD_IPA_WLAN_HDR_DEV_ID_MASK;
- ipahdr->hdr[0].hdr[HDD_IPA_WLAN_HDR_STA_ID_OFFSET] = sta_id;
- if (wlan_iftype == NL80211_IFTYPE_AP ||
- wlan_iftype == NL80211_IFTYPE_P2P_GO) {
- ipahdr->hdr[0].hdr[HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET] |=
- HDD_IPA_WLAN_HDR_DEV_TYPE_AP;
- } else {
- ipahdr->hdr[0].hdr[HDD_IPA_WLAN_HDR_DEV_INFO_OFFSET] |=
- HDD_IPA_WLAN_HDR_DEV_TYPE_STA;
- }
-
snprintf(ipahdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s",
ifname, HDD_IPA_IPV4_NAME_EXT);
ipahdr->hdr[0].hdr_len = HDD_IPA_WLAN_TX_HDR_LEN;
ipahdr->hdr[0].is_partial = HDD_IPA_WLAN_HDR_PARTIAL;
ipahdr->hdr[0].hdr_hdl = 0;
+ /* Set the type to IPV4 in the header*/
+ ((struct ipa_tx_hdr *)(ipahdr->hdr[0].hdr))->llc_snap.eth_type = cpu_to_be16(ETH_P_IP);
+
ret = ipa_add_hdr(ipahdr);
if (ret) {
@@ -1144,8 +1211,7 @@ static int hdd_ipa_add_header_info(uint8_t sta_id, uint8_t *mac_addr)
snprintf(ipahdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s",
ifname, HDD_IPA_IPV6_NAME_EXT);
/* Set the type to IPV6 in the header*/
- ipahdr->hdr[0].hdr[HDD_IPA_WLAN_TX_HDR_IP_VER_OFFSET] = 0x86;
- ipahdr->hdr[0].hdr[HDD_IPA_WLAN_TX_HDR_IP_VER_OFFSET + 1] = 0xdd;
+ ((struct ipa_tx_hdr *)(ipahdr->hdr[0].hdr))->llc_snap.eth_type = cpu_to_be16(ETH_P_IPV6);
ret = ipa_add_hdr(ipahdr);
if (ret) {
@@ -1158,7 +1224,7 @@ static int hdd_ipa_add_header_info(uint8_t sta_id, uint8_t *mac_addr)
ipahdr->hdr[0].name, ipahdr->hdr[0].hdr_hdl);
}
/* Configure the TX and RX pipes filter rules */
- ret = hdd_ipa_register_interface(hdd_ipa, wlan_iftype, sta_id, ifname);
+ ret = hdd_ipa_register_interface(hdd_ipa, sta_id, ifname);
add_header_info_fail:
adf_os_mem_free(ipahdr);
@@ -1206,6 +1272,8 @@ void hdd_ipa_clean_hdr(hdd_adapter_t *adap_dev, uint8_t sta_id)
int ret;
char name_ipa[IPA_RESOURCE_NAME_MAX];
+ wlan_sta_id_2_hdd_pipe_id[sta_id] = 0xFF;
+
/* Remove the headers */
snprintf(name_ipa, IPA_RESOURCE_NAME_MAX, "%s%s",
adap_dev->dev->name, HDD_IPA_IPV4_NAME_EXT);
@@ -1233,6 +1301,7 @@ static void hdd_ipa_msg_free_fn(void *buff, uint32_t len, uint32_t type)
int hdd_ipa_wlan_evt(void *Adapter, uint8_t sta_id,
enum ipa_wlan_event type, uint8_t *mac_addr)
{
+ struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
hdd_adapter_t *adap_dev = Adapter;
struct ipa_msg_meta meta;
struct ipa_wlan_msg *msg;
@@ -1251,7 +1320,7 @@ int hdd_ipa_wlan_evt(void *Adapter, uint8_t sta_id,
__stringify(WLAN_STA_DISCONNECT),
__stringify(WLAN_CLIENT_CONNECT_EX),
};
-
+ struct ol_txrx_peer_t *peer;
HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%s: %s evt, MAC: %pM sta_id: %d",
adap_dev->dev->name, hdd_ipa_event_name[type],
@@ -1265,33 +1334,42 @@ int hdd_ipa_wlan_evt(void *Adapter, uint8_t sta_id,
switch (type) {
case WLAN_STA_CONNECT:
case WLAN_AP_CONNECT:
- hdd_ipa_add_header_info(sta_id, mac_addr);
+ hdd_ipa_add_header_info(type, sta_id, mac_addr);
break;
case WLAN_STA_DISCONNECT:
+ hdd_ipa->pipe_to_vdev[HDD_IPA_TX_WLAN2_PIPE] = NULL;
case WLAN_AP_DISCONNECT:
hdd_ipa_clean_hdr(adap_dev, sta_id);
break;
case WLAN_CLIENT_CONNECT_EX:
+ /* Register pipe map to txrx_vdev into hdd_ipa */
+ peer = ol_txrx_peer_find_by_local_id(((pVosContextType)(WLAN_HDD_GET_CTX(adap_dev))->pvosContext)->pdev_txrx_ctx, sta_id);
+ if (!peer) {
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Invalid peer");
+ return -EINVAL;
+ }
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%d %d", adap_dev->dev->ifindex, sta_id);
+ if (hdd_ipa->pipe_to_vdev[HDD_IPA_TX_WLAN0_PIPE] == NULL) {
+ hdd_ipa->pipe_to_vdev[HDD_IPA_TX_WLAN0_PIPE] = peer->vdev; /* TODO: need to expand to AP+AP */
+ }
+
meta.msg_type = type;
meta.msg_len = (sizeof(struct ipa_wlan_msg_ex) +
- sizeof(struct ipa_wlan_hdr_attrib_val) * 2);
+ sizeof(struct ipa_wlan_hdr_attrib_val));
msg_ex = hdd_ipa_kzalloc (meta.msg_len);
if (msg_ex == NULL) {
HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "ENOMEM");
return -ENOMEM;
}
strlcpy(msg_ex->name, adap_dev->dev->name, IPA_RESOURCE_NAME_MAX);
- msg_ex->num_of_attribs = 2;
+ msg_ex->num_of_attribs = 1;
msg_ex->attribs[0].attrib_type = WLAN_HDR_ATTRIB_MAC_ADDR;
msg_ex->attribs[0].offset = HDD_IPA_WLAN_HDR_DES_MAC_OFFSET;
memcpy(msg_ex->attribs[0].u.mac_addr, mac_addr,
IPA_MAC_ADDR_SIZE);
- msg_ex->attribs[1].attrib_type = WLAN_HDR_ATTRIB_STA_ID;
- msg_ex->attribs[1].offset = HDD_IPA_WLAN_HDR_STA_ID_OFFSET;
- msg_ex->attribs[1].u.sta_id = sta_id;
ret = ipa_send_msg(&meta, msg_ex, hdd_ipa_msg_free_fn);
if (ret) {
@@ -1302,6 +1380,9 @@ int hdd_ipa_wlan_evt(void *Adapter, uint8_t sta_id,
}
return 0;
case WLAN_CLIENT_DISCONNECT:
+ /* TODO: need to expand to AP+AP */
+ /* This will remove the vdev for rest of the connected clients */
+ //hdd_ipa->pipe_to_vdev[HDD_IPA_TX_WLAN0_PIPE] = NULL;
break;
default:
@@ -1337,7 +1418,7 @@ static int hdd_ipa_rx_pipe_desc_alloc(void)
{
struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
uint32_t i, max_desc_cnt;
- int ret =0;
+ int ret = 0;
struct ipa_tx_data_desc *tmp_desc;
hdd_ipa->hw_desc_cnt = IPA_NUM_OF_FIFO_DESC(
@@ -1460,11 +1541,6 @@ static ssize_t hdd_ipa_debugfs_read_ipa_stats(struct file *file,
"RXT 5 skb:", hdd_ipa->stats.rxt_5);
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n",
"RXT > 5 skb:", hdd_ipa->stats.rxt_6);
-#endif
- len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n",
- "IPA TX Recieve:", hdd_ipa->stats.tx_ipa_recv);
-
-#ifdef HDD_IPA_EXTRA_DP_COUNTERS
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
"Free Queue use:", hdd_ipa->stats.freeq_use);
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
@@ -1474,7 +1550,14 @@ static ssize_t hdd_ipa_debugfs_read_ipa_stats(struct file *file,
"Free Queue Empty:", hdd_ipa->stats.freeq_empty);
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n",
"Free Queue cnt:", hdd_ipa->stats.freeq_cnt);
-
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n",
+ "IPA LB Count:", hdd_ipa->stats.ipa_lb_cnt);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n",
+ "IPA TX Recieve:", hdd_ipa->stats.tx_ipa_recv);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n",
+ "TX COMP Count:", hdd_ipa->stats.tx_comp_cnt);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n",
+ "TX DP Err Count:", hdd_ipa->stats.tx_dp_err_cnt);
if (len > buf_len)
len = buf_len;
@@ -1485,10 +1568,10 @@ static ssize_t hdd_ipa_debugfs_read_ipa_stats(struct file *file,
}
static const struct file_operations fops_ipa_stats = {
- .read = hdd_ipa_debugfs_read_ipa_stats,
- .open = simple_open,
- .owner = THIS_MODULE,
- .llseek = default_llseek,
+ .read = hdd_ipa_debugfs_read_ipa_stats,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
};
@@ -1497,7 +1580,7 @@ int hdd_ipa_debugfs_init(struct hdd_ipa_priv *hdd_ipa)
#ifdef WLAN_OPEN_SOURCE
hdd_ipa->debugfs_dir = debugfs_create_dir("cld",
hdd_ipa->hdd_ctx->wiphy->debugfsdir);
- if(!hdd_ipa->debugfs_dir)
+ if (!hdd_ipa->debugfs_dir)
return -ENOMEM;
debugfs_create_file("ipa-stats", S_IRUSR, hdd_ipa->debugfs_dir,
@@ -1517,10 +1600,13 @@ int hdd_ipa_debugfs_init(struct hdd_ipa_priv *hdd_ipa)
VOS_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx)
{
struct hdd_ipa_priv *hdd_ipa = NULL;
- int ret;
+ int ret, i;
if (!hdd_ipa_is_enabled(hdd_ctx))
return 0;
+ for (i = 0; i < HDD_IPA_WLAN_MAX_STA_ID; i++)
+ wlan_sta_id_2_hdd_pipe_id[i] = 0xFF;
+
hdd_ipa = hdd_ipa_kzalloc(sizeof(struct hdd_ipa_priv));
if (!hdd_ipa) {
HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, "ENOMEM");
@@ -1585,6 +1671,68 @@ VOS_STATUS hdd_ipa_cleanup(hdd_context_t *hdd_ctx)
return VOS_STATUS_SUCCESS;
}
-#endif
+#if 0
+/**
+* hdd_ipa_start_xmit() - This is a hack code for IPA loopback test
+*/
+int hdd_ipa_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
+ hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
+ uint8_t sta_id;
+ struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
+
+ v_MACADDR_t *pDestMacAddress = (v_MACADDR_t *)skb->data;
+
+ if (vos_is_macaddr_broadcast(pDestMacAddress) ||
+ vos_is_macaddr_group(pDestMacAddress)) {
+ /* The BC/MC station ID is assigned during BSS starting phase.
+ SAP will return the station ID used for BC/MC traffic. */
+ sta_id = pHddApCtx->uBCStaId;
+ hdd_softap_hard_start_xmit(skb, dev);
+ return NETDEV_TX_OK;
+ } else {
+ sta_id = *(uint8_t *)(((uint8_t *)(skb->data)) - 1);
+ if (sta_id == HDD_WLAN_INVALID_STA_ID) {
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_WARN,
+ "Failed to find right station");
+ goto drop_pkt;
+ } else if (FALSE == pAdapter->aStaInfo[sta_id].isUsed) {
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_WARN,
+ "STA %d is unregistered", sta_id);
+ goto drop_pkt;
+ }
+
+ if ((WLANTL_STA_CONNECTED !=
+ pAdapter->aStaInfo[sta_id].tlSTAState) &&
+ (WLANTL_STA_AUTHENTICATED !=
+ pAdapter->aStaInfo[sta_id].tlSTAState)) {
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_WARN,
+ "Station not connected yet");
+ goto drop_pkt;
+ } else if (WLANTL_STA_CONNECTED ==
+ pAdapter->aStaInfo[sta_id].tlSTAState) {
+ if (ntohs(skb->protocol) !=
+ HDD_ETHERTYPE_802_1_X) {
+ HDD_IPA_LOG(VOS_TRACE_LEVEL_WARN,
+ "NON-EAPOL packet in no-Auth state");
+ goto drop_pkt;
+ }
+ }
+ }
+ if (hdd_ipa_is_ip_pkt(skb->data, HDD_IPA_IPV4)) {
+ /* TX frame Counter at HDD entry from kernel network stack, before give frame to IPA Loopback */
+ hdd_ipa->stats.ipa_lb_cnt++;
+ ipa_tx_dp(IPA_CLIENT_WLAN1_CONS, skb, NULL);
+ } else {
+ hdd_softap_hard_start_xmit(skb, dev);
+ }
+ return NETDEV_TX_OK;
+drop_pkt:
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+}
+#endif
+#endif
diff --git a/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h b/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h
index d209ded62380..3998c534d839 100644
--- a/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h
+++ b/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h
@@ -104,9 +104,16 @@ struct cvg_nbuf_cb {
} extra_frags;
uint32_t owner_id;
__adf_nbuf_callback_fn adf_nbuf_callback_fn;
+#ifdef IPA_OFFLOAD
+ unsigned long priv_data;
+#endif
};
#define NBUF_OWNER_ID(skb) \
(((struct cvg_nbuf_cb *)((skb)->cb))->owner_id)
+#ifdef IPA_OFFLOAD
+#define NBUF_OWNER_PRIV_DATA(skb) \
+ (((struct cvg_nbuf_cb *)((skb)->cb))->priv_data)
+#endif
#define NBUF_CALLBACK_FN(skb) \
(((struct cvg_nbuf_cb *)((skb)->cb))->adf_nbuf_callback_fn)
#define NBUF_CALLBACK_FN_EXEC(skb) \
diff --git a/CORE/TL/inc/wlan_qct_tl.h b/CORE/TL/inc/wlan_qct_tl.h
index 898c6ce1df20..dc54fd115627 100644
--- a/CORE/TL/inc/wlan_qct_tl.h
+++ b/CORE/TL/inc/wlan_qct_tl.h
@@ -1298,6 +1298,39 @@ adf_nbuf_t WLANTL_SendSTA_DataFrame(v_PVOID_t pvosGCtx, v_U8_t ucSTAId,
adf_nbuf_t buf);
#endif
+#ifdef IPA_OFFLOAD
+/*===========================================================================
+
+ FUNCTION WLANTL_SendIPA_DataFrame
+
+ DESCRIPTION
+
+ HDD will call this API when there is a packet to be transmitted from IPA
+
+ DEPENDENCIES
+
+ A station must have been registered before sending packet to txrx layer
+
+
+ PARAMETERS
+
+ vos_ctx: pointer to the global vos context; a handle to TL's
+ control block can be extracted from its context
+ vdev: virtual device
+ buf: packet given by uppler layer for tx
+
+ RETURN VALUE
+
+ On success it will return NULL. On failure it will be the
+ passed buf pointer so that the caller will be able to free
+ up the buffer.
+
+============================================================================*/
+adf_nbuf_t WLANTL_SendIPA_DataFrame(void *vos_ctx, void *vdev,
+ adf_nbuf_t buf);
+#endif
+
+
/*==========================================================================
FUNCTION WLANTL_SetSTAPriority