diff options
| author | Prakash Dhavali <pdhavali@qca.qualcomm.com> | 2014-01-31 11:57:25 -0800 |
|---|---|---|
| committer | Prakash Dhavali <pdhavali@qca.qualcomm.com> | 2014-01-31 17:28:12 -0800 |
| commit | 2356510be4eb29bb83d803483cf9669a23e8217a (patch) | |
| tree | 3bac207b2258c48b9a3b533519a360d9e5b7bff6 | |
| parent | e3ecf322a421590b47f208bbeea2be278e16d448 (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.c | 38 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_ipa.c | 692 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h | 7 | ||||
| -rw-r--r-- | CORE/TL/inc/wlan_qct_tl.h | 33 |
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 |
