diff options
| -rw-r--r-- | CORE/CLD_TXRX/TLSHIM/tl_shim.c | 50 | ||||
| -rw-r--r-- | CORE/CLD_TXRX/TLSHIM/tl_shim.h | 5 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_ipa.h | 12 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_main.h | 3 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_assoc.c | 10 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_hostapd.c | 8 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_ipa.c | 1215 | ||||
| -rw-r--r-- | CORE/VOSS/src/vos_trace.c | 7 |
8 files changed, 685 insertions, 625 deletions
diff --git a/CORE/CLD_TXRX/TLSHIM/tl_shim.c b/CORE/CLD_TXRX/TLSHIM/tl_shim.c index ef00f2d6fe26..b3df3a7f9f5c 100644 --- a/CORE/CLD_TXRX/TLSHIM/tl_shim.c +++ b/CORE/CLD_TXRX/TLSHIM/tl_shim.c @@ -1575,3 +1575,53 @@ VOS_STATUS tl_shim_get_vdevid(struct ol_txrx_peer_t *peer, u_int8_t *vdev_id) *vdev_id = peer->vdev->vdev_id; return VOS_STATUS_SUCCESS; } + +/* + * Function to get vdev(tl_context) given the MAC address. + */ +void *tl_shim_get_vdev_by_addr(void *vos_context, uint8_t *mac_addr) +{ + struct ol_txrx_peer_t *peer = NULL; + ol_txrx_pdev_handle pdev = NULL; + uint8_t peer_id; + + if (vos_context == NULL || mac_addr == NULL) { + TLSHIM_LOGE("Invalid argument %p, %p", vos_context, mac_addr); + return NULL; + } + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, vos_context); + peer = ol_txrx_find_peer_by_addr(pdev, mac_addr, &peer_id); + + if (!peer) { + TLSHIM_LOGE("PEER [%pM] not found", mac_addr); + return NULL; + } + + return peer->vdev; +} + +/* + * Function to get vdev(tl_context) given the TL station ID. + */ +void *tl_shim_get_vdev_by_sta_id(void *vos_context, uint8_t sta_id) +{ + struct ol_txrx_peer_t *peer = NULL; + ol_txrx_pdev_handle pdev = NULL; + + if (sta_id >= WLAN_MAX_STA_COUNT) { + TLSHIM_LOGE("Invalid sta id passed"); + return NULL; + } + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, vos_context); + + peer = ol_txrx_peer_find_by_local_id(pdev, sta_id); + + if (!peer) { + TLSHIM_LOGE("PEER [%d] not found", sta_id); + return NULL; + } + + return peer->vdev; +} diff --git a/CORE/CLD_TXRX/TLSHIM/tl_shim.h b/CORE/CLD_TXRX/TLSHIM/tl_shim.h index a5d8fa836a3c..31084662b82b 100644 --- a/CORE/CLD_TXRX/TLSHIM/tl_shim.h +++ b/CORE/CLD_TXRX/TLSHIM/tl_shim.h @@ -28,6 +28,9 @@ #ifndef TXRX_TL_SHIM_H #define TXRX_TL_SHIM_H +#include <ol_txrx_osif_api.h> +#include <adf_os_lock.h> + #ifdef FEATURE_WLAN_CCX typedef struct deferred_iapp_work { pVosContextType pVosGCtx; @@ -86,5 +89,7 @@ VOS_STATUS tl_shim_get_vdevid(struct ol_txrx_peer_t *peer, u_int8_t *vdev_id); * BETTER_AP_FOUND event is received from roam engine. */ int tlshim_mgmt_roam_event_ind(void *context, u_int32_t vdev_id); +void *tl_shim_get_vdev_by_addr(void *vos_context, uint8_t *mac_addr); +void *tl_shim_get_vdev_by_sta_id(void *vos_context, uint8_t sta_id); #endif diff --git a/CORE/HDD/inc/wlan_hdd_ipa.h b/CORE/HDD/inc/wlan_hdd_ipa.h index d0c532f945e0..aaac547e70ce 100644 --- a/CORE/HDD/inc/wlan_hdd_ipa.h +++ b/CORE/HDD/inc/wlan_hdd_ipa.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -44,12 +44,12 @@ #ifdef IPA_OFFLOAD #include <mach/ipa.h> -VOS_STATUS hdd_ipa_init(hdd_context_t *pHddCtx); -VOS_STATUS hdd_ipa_cleanup(hdd_context_t *pHddCtx); -int hdd_ipa_wlan_evt(void *pAdapter, uint8_t sta_id, - enum ipa_wlan_event type, uint8_t *mac_addr); +VOS_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx); +VOS_STATUS hdd_ipa_cleanup(hdd_context_t *hdd_ctx); +int hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id, + enum ipa_wlan_event type, uint8_t *mac_addr); VOS_STATUS hdd_ipa_process_rxt(v_VOID_t *vosContext, adf_nbuf_t rxBuf, - v_U8_t staId); + v_U8_t sta_id); bool hdd_ipa_is_enabled(hdd_context_t *pHddCtx); #endif diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index 7213c73da511..0f741496f550 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -1026,6 +1026,9 @@ struct hdd_adapter_s #ifdef QCA_WIFI_2_0 v_BOOL_t internalCancelRemainOnChReq; #endif +#ifdef IPA_OFFLOAD + void *ipa_context; +#endif }; #define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station) diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c index f07a5df4674c..30dc08dd1d77 100644 --- a/CORE/HDD/src/wlan_hdd_assoc.c +++ b/CORE/HDD/src/wlan_hdd_assoc.c @@ -813,8 +813,8 @@ static eHalStatus hdd_DisConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo * #ifdef IPA_OFFLOAD if (hdd_ipa_is_enabled(pHddCtx)) - hdd_ipa_wlan_evt(pAdapter, pHddStaCtx->conn_info.staId[0], - WLAN_STA_DISCONNECT, pAdapter->dev->dev_addr); + hdd_ipa_wlan_evt(pAdapter, pHddStaCtx->conn_info.staId[0], + WLAN_STA_DISCONNECT, pHddStaCtx->conn_info.bssId); #endif if(pHddStaCtx->conn_info.connState != eConnectionState_Disconnecting) @@ -1299,9 +1299,9 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs pHddCtx->sta_to_adapter[pRoamInfo->staId] = pAdapter; #ifdef IPA_OFFLOAD - if (hdd_ipa_is_enabled(pHddCtx)) - hdd_ipa_wlan_evt(pAdapter, pRoamInfo->staId, WLAN_STA_CONNECT, - pAdapter->dev->dev_addr); + if (hdd_ipa_is_enabled(pHddCtx)) + hdd_ipa_wlan_evt(pAdapter, pRoamInfo->staId, WLAN_STA_CONNECT, + pRoamInfo->bssid); #endif #ifdef FEATURE_WLAN_TDLS diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c index 5dafbabe316f..3518e8f62882 100644 --- a/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/CORE/HDD/src/wlan_hdd_hostapd.c @@ -511,8 +511,8 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa } #ifdef IPA_OFFLOAD if (hdd_ipa_is_enabled(pHddCtx)) - hdd_ipa_wlan_evt(pHostapdAdapter, WLAN_RX_SAP_SELF_STA_ID, - WLAN_AP_CONNECT, pHostapdAdapter->dev->dev_addr); + hdd_ipa_wlan_evt(pHostapdAdapter, pHddApCtx->uBCStaId, + WLAN_AP_CONNECT, pHostapdAdapter->dev->dev_addr); #endif if (0 != (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff) @@ -596,8 +596,8 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa pHddApCtx->operatingChannel = 0; //Invalidate the channel info. #ifdef IPA_OFFLOAD if (hdd_ipa_is_enabled(pHddCtx)) - hdd_ipa_wlan_evt(pHostapdAdapter, WLAN_RX_SAP_SELF_STA_ID, - WLAN_AP_DISCONNECT, pHostapdAdapter->dev->dev_addr); + hdd_ipa_wlan_evt(pHostapdAdapter, pHddApCtx->uBCStaId, + WLAN_AP_DISCONNECT, pHostapdAdapter->dev->dev_addr); #endif goto stopbss; case eSAP_STA_SET_KEY_EVENT: diff --git a/CORE/HDD/src/wlan_hdd_ipa.c b/CORE/HDD/src/wlan_hdd_ipa.c index 5965f7892afc..88da1e7337b0 100644 --- a/CORE/HDD/src/wlan_hdd_ipa.c +++ b/CORE/HDD/src/wlan_hdd_ipa.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -24,7 +24,6 @@ * under proprietary terms before Copyright ownership was assigned * to the Linux Foundation. */ - /*======================================================================== \file wlan_hdd_ipa.c @@ -50,18 +49,14 @@ Include Files #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" +#include "wlan_qct_tl.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 -#define HDD_IPA_WLAN_HDR_ONLY_LEN 4 -#define HDD_IPA_WLAN_HDR_STA_ID_OFFSET 3 -#define HDD_IPA_WLAN_HDR_DES_MAC_OFFSET 0 struct llc_snap_hdr { uint8_t dsap; @@ -70,49 +65,60 @@ struct llc_snap_hdr { __be16 eth_type; } __packed; -struct ipa_tx_hdr { +struct hdd_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 = { +static struct hdd_ipa_tx_hdr ipa_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 */ + {0xDE, 0xAD, 0xBE, 0xEF, 0xFF, 0xFF}, + {0xDE, 0xAD, 0xBE, 0xEF, 0xFF, 0xFF}, + 0x00 /* length can be zero */ }, { - /* LLC SNAP header 8 bytes */ - 0xaa, 0xaa, - {0x03, 0x00, 0x00, 0x00}, - 0x0008 /* type value(2 bytes) ,filled by wlan */ - /* 0x0800 - IPV4, 0x86dd - IPV6 */ + /* LLC SNAP header 8 bytes */ + 0xaa, 0xaa, + {0x03, 0x00, 0x00, 0x00}, + 0x0008 /* type value(2 bytes) ,filled by wlan */ + /* 0x0800 - IPV4, 0x86dd - IPV6 */ } }; -struct ipa_rx_hdr { - uint8_t hdr[HDD_IPA_WLAN_HDR_ONLY_LEN]; +/* + +----------+----------+--------------+--------+ + | Reserved | QCMAP ID | interface id | STA ID | + +----------+----------+--------------+--------+ + */ +struct hdd_ipa_cld_hdr { + uint8_t reserved[2]; + uint8_t iface_id; + uint8_t sta_id; +} __packed; + +struct hdd_ipa_rx_hdr { + struct hdd_ipa_cld_hdr cld_hdr; 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_CLD_HDR_LEN sizeof(struct hdd_ipa_cld_hdr) +#define HDD_IPA_WLAN_TX_HDR_LEN sizeof(ipa_tx_hdr) +#define HDD_IPA_WLAN_RX_HDR_LEN sizeof(struct hdd_ipa_rx_hdr) +#define HDD_IPA_WLAN_HDR_DES_MAC_OFFSET 0 + +#define HDD_IPA_GET_IFACE_ID(_data) \ + (((struct hdd_ipa_cld_hdr *) (_data))->iface_id) -#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_PARTIAL 1 #define HDD_IPA_LOG(LVL, fmt, args...) VOS_TRACE(VOS_MODULE_ID_HDD, LVL, \ - "%s:%d "fmt"\n", __func__, __LINE__, ## args) + "%s:%d: "fmt, __func__, __LINE__, ## args) + +#define HDD_IPA_DBG_DUMP(_lvl, _prefix, _buf, _len) \ + do {\ + VOS_TRACE(VOS_MODULE_ID_HDD, _lvl, "%s:", _prefix); \ + VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_HDD, _lvl, _buf, _len); \ + } while(0) enum hdd_ipa_rm_state { HDD_IPA_RM_RELEASED, @@ -121,101 +127,106 @@ enum hdd_ipa_rm_state { HDD_IPA_RM_RELEASE_PENDING, }; -enum hdd_ipa_pipe_index { - HDD_IPA_TX_WLAN0_PIPE, - HDD_IPA_TX_WLAN1_PIPE, - HDD_IPA_TX_WLAN2_PIPE, - HDD_IPA_RX_PIPE, - HDD_IPA_MAX_PIPE +#define HDD_IPA_MAX_IFACE 3 +#define HDD_IPA_MAX_SYSBAM_PIPE 4 +#define HDD_IPA_RX_PIPE HDD_IPA_MAX_IFACE + +static struct hdd_ipa_adapter_2_client { + enum ipa_client_type cons_client; + enum ipa_client_type prod_client; +} hdd_ipa_adapter_2_client[HDD_IPA_MAX_IFACE] = { + {IPA_CLIENT_WLAN1_CONS, IPA_CLIENT_WLAN1_PROD}, + {IPA_CLIENT_WLAN2_CONS, IPA_CLIENT_WLAN1_PROD}, + {IPA_CLIENT_WLAN3_CONS, IPA_CLIENT_WLAN1_PROD}, }; -enum hdd_ipa_ip_ver { - HDD_IPA_IPV4 = 1, - HDD_IPA_IPV6 = 2 +struct hdd_ipa_sys_pipe { + uint32_t conn_hdl; + uint8_t conn_hdl_valid; + struct ipa_sys_connect_params ipa_sys_params; }; -#define HDD_IPA_WLAN_MAX_STA_ID 255 +struct hdd_ipa_priv; -uint8_t wlan_sta_id_2_hdd_pipe_id[HDD_IPA_WLAN_MAX_STA_ID] = {0xFF}; +struct hdd_ipa_iface_context { + struct hdd_ipa_priv *hdd_ipa; + hdd_adapter_t *adapter; + void *tl_context; -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_WLAN1_PROD -}; + enum ipa_client_type cons_client; + enum ipa_client_type prod_client; -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 + uint8_t iface_id; /* This iface ID */ + uint8_t sta_id; /* This iface station ID */ }; -struct hdd_ipa_sys_pipe { - uint32_t conn_hdl; - uint8_t conn_hdl_valid; - struct ipa_sys_connect_params ipa_sys_params; + +struct hdd_ipa_stats { + uint32_t event[IPA_WLAN_EVENT_MAX]; + uint32_t send_msg; + uint32_t free_msg; + + uint64_t prefilter; + uint64_t rm_grant; + uint64_t rm_release; +#ifdef HDD_IPA_EXTRA_DP_COUNTERS + uint64_t rx_ipa_rm_qued; +#endif + uint64_t rx_ipa_sent_desc_cnt; + uint64_t rx_ipa_write_done; + uint64_t rx_ipa_excep; + + uint64_t rx_ipa_hw_maxed_out; + + uint64_t freeq_empty; + uint64_t freeq_cnt; + +#ifdef HDD_IPA_EXTRA_DP_COUNTERS + uint64_t rxt_drop; + uint64_t rxt_recv; + uint64_t rx_ipa_hw_max_qued; + uint64_t rxt_d_drop; + uint64_t rxt_dh_drop; + uint64_t rxt_0; + uint64_t rxt_1; + uint64_t rxt_2; + uint64_t rxt_3; + uint64_t rxt_4; + uint64_t rxt_5; + uint64_t rxt_6; + uint64_t freeq_use; + uint64_t freeq_reclaim; + uint64_t rx_ipa_dh_sent; + uint64_t rx_ipa_dh_reclaim; + uint64_t rx_ipa_dh_not_used; +#endif + uint64_t ipa_lb_cnt; + uint64_t tx_ipa_recv; + uint64_t tx_comp_cnt; + uint64_t tx_dp_err_cnt; }; struct hdd_ipa_priv { - struct hdd_ipa_sys_pipe sys_pipe[HDD_IPA_MAX_PIPE]; + struct hdd_ipa_sys_pipe sys_pipe[HDD_IPA_MAX_SYSBAM_PIPE]; + struct hdd_ipa_iface_context iface_context[HDD_IPA_MAX_IFACE]; atomic_t rm_state; #ifndef HDD_IPA_USE_IPA_RM_TIMER struct timer_list rm_timer; uint8_t rm_timer_on; #endif + enum ipa_client_type prod_client; + uint32_t pending_desc_cnt; uint32_t hw_desc_cnt; spinlock_t q_lock; 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; - struct { - uint64_t prefilter; - uint64_t rm_grant; - uint64_t rm_release; -#ifdef HDD_IPA_EXTRA_DP_COUNTERS - uint64_t rx_ipa_rm_qued; -#endif - uint64_t rx_ipa_sent_desc_cnt; - uint64_t rx_ipa_write_done; - uint64_t rx_ipa_excep; - - uint64_t rx_ipa_hw_maxed_out; - - uint64_t freeq_empty; - uint64_t freeq_cnt; + struct hdd_ipa_stats stats; -#ifdef HDD_IPA_EXTRA_DP_COUNTERS - uint64_t rxt_drop; - uint64_t rxt_recv; - uint64_t rx_ipa_hw_max_qued; - uint64_t rxt_d_drop; - uint64_t rxt_dh_drop; - uint64_t rxt_0; - uint64_t rxt_1; - uint64_t rxt_2; - uint64_t rxt_3; - uint64_t rxt_4; - uint64_t rxt_5; - uint64_t rxt_6; - uint64_t freeq_use; - uint64_t freeq_reclaim; - uint64_t rx_ipa_dh_sent; - uint64_t rx_ipa_dh_reclaim; - uint64_t rx_ipa_dh_not_used; -#endif - 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 { @@ -239,12 +250,22 @@ bool hdd_ipa_is_enabled(hdd_context_t *hdd_ctx) return hdd_ctx->cfg_ini->IpaEnable; } -static inline void *hdd_ipa_kzalloc(uint32_t size) +static inline bool hdd_ipa_is_pre_filter_enabled(struct hdd_ipa_priv *hdd_ipa) +{ + hdd_context_t *hdd_ctx = hdd_ipa->hdd_ctx; + return hdd_ctx->cfg_ini->IpaPreFilterEnable; +} + +static inline bool hdd_ipa_is_ipv6_enabled(struct hdd_ipa_priv *hdd_ipa) { - void *data = NULL; + hdd_context_t *hdd_ctx = hdd_ipa->hdd_ctx; + return hdd_ctx->cfg_ini->IpaIPv6Enable; +} - data = adf_os_mem_alloc(NULL, size); - return data; +static inline bool hdd_ipa_is_rm_enabled(struct hdd_ipa_priv *hdd_ipa) +{ + hdd_context_t *hdd_ctx = hdd_ipa->hdd_ctx; + return hdd_ctx->cfg_ini->IpaRMEnable; } static inline struct ipa_tx_data_desc *hdd_ipa_get_desc_from_freeq(void) @@ -254,7 +275,8 @@ static inline struct ipa_tx_data_desc *hdd_ipa_get_desc_from_freeq(void) spin_lock_bh(&ghdd_ipa->q_lock); if (!list_empty(&ghdd_ipa->free_desc_head)) { - desc = list_first_entry(&ghdd_ipa->free_desc_head, struct ipa_tx_data_desc, link); + desc = list_first_entry(&ghdd_ipa->free_desc_head, + struct ipa_tx_data_desc, link); list_del(&desc->link); hdd_ipa->stats.freeq_cnt--; #ifdef HDD_IPA_EXTRA_DP_COUNTERS @@ -267,22 +289,33 @@ static inline struct ipa_tx_data_desc *hdd_ipa_get_desc_from_freeq(void) return desc; } -static inline bool hdd_ipa_can_pre_filter(struct hdd_ipa_priv *hdd_ipa) +static bool hdd_ipa_can_send_to_ipa(struct hdd_ipa_priv *hdd_ipa, void *data) { - hdd_context_t *hdd_ctx = hdd_ipa->hdd_ctx; - return hdd_ctx->cfg_ini->IpaPreFilterEnable; -} + struct ethhdr *eth = (struct ethhdr *)data; + struct llc_snap_hdr *ls_hdr; + uint16_t eth_type; -static inline bool hdd_ipa_is_ipv6_enabled(struct hdd_ipa_priv *hdd_ipa) -{ - hdd_context_t *hdd_ctx = hdd_ipa->hdd_ctx; - return hdd_ctx->cfg_ini->IpaIPv6Enable; -} + if (!hdd_ipa_is_pre_filter_enabled(hdd_ipa)) + return true; -static inline bool hdd_ipa_is_rm_enabled(struct hdd_ipa_priv *hdd_ipa) -{ - hdd_context_t *hdd_ctx = hdd_ipa->hdd_ctx; - return hdd_ctx->cfg_ini->IpaRMEnable; + eth_type = be16_to_cpu(eth->h_proto); + if (eth_type < 0x600) { + /* Non Ethernet II framing format */ + ls_hdr = (struct llc_snap_hdr *)((uint8_t *)data + + sizeof(struct ethhdr)); + + 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) + return true; + + if (hdd_ipa_is_ipv6_enabled(hdd_ipa) && eth_type == ETH_P_IPV6) + return true; + + return false; } static int hdd_ipa_rm_request(struct hdd_ipa_priv *hdd_ipa) @@ -362,7 +395,7 @@ static int hdd_ipa_setup_rm(struct hdd_ipa_priv *hdd_ipa) ret = ipa_rm_create_resource(&create_params); if (ret) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "create resource fail"); + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Create RM resource failed"); goto setup_rm_fail; } @@ -370,11 +403,13 @@ static int hdd_ipa_setup_rm(struct hdd_ipa_priv *hdd_ipa) ret = ipa_rm_inactivity_timer_init(IPA_RM_RESOURCE_WLAN_PROD, HDD_IPA_RX_INACTIVITY_MSEC_DELAY); if (ret) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "timer fail"); + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Timer init failed"); goto setup_rm_fail; } #endif + atomic_set(&hdd_ipa->rm_state, HDD_IPA_RM_RELEASED); + setup_rm_fail: return ret; } @@ -391,10 +426,10 @@ static void hdd_ipa_destory_rm_resource(struct hdd_ipa_priv *hdd_ipa) #endif ret = ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD); if (ret) - HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "fail"); + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "RM resource delete failed"); } -void hdd_ipa_rm_timer_handler(unsigned long ptr) +static void hdd_ipa_rm_timer_handler(unsigned long ptr) { struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; atomic_set(&hdd_ipa->rm_state, @@ -402,27 +437,26 @@ void hdd_ipa_rm_timer_handler(unsigned long ptr) hdd_ipa_rm_release(hdd_ipa); } -void hdd_ipa_send_skb_to_network(adf_nbuf_t skb, hdd_adapter_t *adap_dev) +static void hdd_ipa_send_skb_to_network(adf_nbuf_t skb, hdd_adapter_t *adapter) { - if (!adap_dev || (adap_dev && - adap_dev->magic != WLAN_HDD_ADAPTER_MAGIC)) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Invalid adapter: adap=0x%x", - adap_dev); + if (!adapter || adapter->magic != WLAN_HDD_ADAPTER_MAGIC) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Invalid adapter: 0x%p", + adapter); - adf_nbuf_free(skb); - return; - } - skb->dev = adap_dev->dev; - skb->protocol = eth_type_trans(skb, skb->dev); - skb->ip_summed = CHECKSUM_NONE; - ++adap_dev->hdd_stats.hddTxRxStats.rxPackets; - ++adap_dev->stats.rx_packets; - adap_dev->stats.rx_bytes += skb->len; - if (netif_rx_ni(skb) == NET_RX_SUCCESS) - ++adap_dev->hdd_stats.hddTxRxStats.rxDelivered; - else - ++adap_dev->hdd_stats.hddTxRxStats.rxRefused; - adap_dev->dev->last_rx = jiffies; + adf_nbuf_free(skb); + return; + } + skb->dev = adapter->dev; + skb->protocol = eth_type_trans(skb, skb->dev); + skb->ip_summed = CHECKSUM_NONE; + ++adapter->hdd_stats.hddTxRxStats.rxPackets; + ++adapter->stats.rx_packets; + adapter->stats.rx_bytes += skb->len; + if (netif_rx_ni(skb) == NET_RX_SUCCESS) + ++adapter->hdd_stats.hddTxRxStats.rxDelivered; + else + ++adapter->hdd_stats.hddTxRxStats.rxRefused; + adapter->dev->last_rx = jiffies; } static void hdd_ipa_send_pkt_to_ipa(struct ipa_tx_data_desc *send_desc_head, @@ -478,21 +512,25 @@ static void hdd_ipa_send_pkt_to_ipa(struct ipa_tx_data_desc *send_desc_head, 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], + if (ipa_tx_dp_mul(hdd_ipa->prod_client, 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_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) { + &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); + 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++; @@ -501,7 +539,8 @@ static void hdd_ipa_send_pkt_to_ipa(struct ipa_tx_data_desc *send_desc_head, } /* return anchor node */ - list_add_tail(&send_desc_head->link, &hdd_ipa->free_desc_head); + 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++; @@ -517,7 +556,8 @@ static void hdd_ipa_send_pkt_to_ipa(struct ipa_tx_data_desc *send_desc_head, hdd_ipa->stats.rx_ipa_hw_maxed_out++; list_splice_tail_init(&send_desc_head->link, &hdd_ipa->pend_desc_head); - list_add_tail(&send_desc_head->link, &hdd_ipa->free_desc_head); + 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_not_used++; @@ -528,52 +568,25 @@ 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 *ls_hdr; - uint16_t eth_type; - int ret = 0; - - eth_type = be16_to_cpu(eth->h_proto); - if (eth_type < 0x600) { - /* Non Ethernet II framing format */ - ls_hdr = (struct llc_snap_hdr *)((uint8_t *)data + - sizeof(struct ethhdr)); - - 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)) || - ((eth_type == ETH_P_IPV6) && (ip_ver == HDD_IPA_IPV6))) - ret = 1; - - if (ret != 1) - HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, "NOT IP Packet!!! (eth_type=0x%x, ip_ver=%d)", eth_type, ip_ver); - - return ret; -} - - static void hdd_ipa_process_evt(int evt, void *priv) { struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; struct hdd_ipa_rxt *rxt; struct ipa_tx_data_desc *send_desc_head = NULL, *send_desc, *done_desc_head, *done_desc, *tmp; - hdd_adapter_t *adap_dev = NULL; + hdd_adapter_t *adapter = NULL; + struct hdd_ipa_iface_context *iface_context = NULL; adf_nbuf_t buf, next_buf; uint8_t cur_cnt = 0; + struct hdd_ipa_cld_hdr *cld_hdr; switch (evt) { case HDD_IPA_RXT_EVT: rxt = priv; - adap_dev = hdd_ipa->hdd_ctx->sta_to_adapter[rxt->sta_id]; - if (!adap_dev || - (adap_dev && adap_dev->magic != WLAN_HDD_ADAPTER_MAGIC)) { + adapter = hdd_ipa->hdd_ctx->sta_to_adapter[rxt->sta_id]; + if (!adapter || + (adapter && adapter->magic != WLAN_HDD_ADAPTER_MAGIC)) { HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Invalid sta_id"); buf = rxt->rx_buf_list; while (buf) { @@ -586,10 +599,14 @@ static void hdd_ipa_process_evt(int evt, void *priv) } return; } + + iface_context = + (struct hdd_ipa_iface_context *) adapter->ipa_context; /* send_desc_head is a anchor node */ send_desc_head = hdd_ipa_get_desc_from_freeq(); if (!send_desc_head) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "send_desc_head=Null. FreeQ Empty"); + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "send_desc_head=Null. FreeQ Empty"); buf = rxt->rx_buf_list; while (buf) { next_buf = adf_nbuf_queue_next(buf); @@ -612,34 +629,28 @@ static void hdd_ipa_process_evt(int evt, void *priv) INIT_LIST_HEAD(&send_desc_head->link); buf = rxt->rx_buf_list; while (buf) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, "RX data:\n \ - %02x %02x %02x %02x %02x %02x %02x %02x\n \ - %02x %02x %02x %02x %02x %02x %02x %02x\n \ - %02x %02x %02x %02x %02x %02x %02x %02x\n", - buf->data[0], buf->data[1], buf->data[2], buf->data[3], - buf->data[4], buf->data[5], buf->data[6], buf->data[7], - buf->data[8], buf->data[9], buf->data[10], buf->data[11], - buf->data[12], buf->data[13], buf->data[14], buf->data[15], - buf->data[16], buf->data[17], buf->data[18], buf->data[19], - buf->data[20], buf->data[21], buf->data[22], buf->data[23]); + HDD_IPA_DBG_DUMP(VOS_TRACE_LEVEL_DEBUG, "RX data", + buf->data, 24); next_buf = adf_nbuf_queue_next(buf); - /* we want to send Rx packets to IPA only when it is IPV4 or IPV6i(if IPV6 - is enabled). All other packets will be sent to network stack directly. */ - if (hdd_ipa_can_pre_filter(hdd_ipa) && - (!hdd_ipa_is_ip_pkt(buf->data, HDD_IPA_IPV4) && - (!hdd_ipa_is_ipv6_enabled(hdd_ipa) || - !hdd_ipa_is_ip_pkt(buf->data, HDD_IPA_IPV6)))) { + /* + * we want to send Rx packets to IPA only when it is + * IPV4 or IPV6i(if IPV6 is enabled). All other packets + * will be sent to network stack directly. + */ + if (!hdd_ipa_can_send_to_ipa(hdd_ipa, buf->data)) { hdd_ipa->stats.prefilter++; - hdd_ipa_send_skb_to_network(buf, adap_dev); + hdd_ipa_send_skb_to_network(buf, adapter); buf = next_buf; continue; } - skb_push(buf, HDD_IPA_WLAN_HDR_ONLY_LEN); - /* 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; + cld_hdr = (struct hdd_ipa_cld_hdr *) skb_push(buf, + HDD_IPA_WLAN_CLD_HDR_LEN); + cld_hdr->sta_id = rxt->sta_id; + cld_hdr->iface_id = iface_context->iface_id; + send_desc = hdd_ipa_get_desc_from_freeq(); if (send_desc) { send_desc->priv = buf; @@ -680,7 +691,8 @@ static void hdd_ipa_process_evt(int evt, void *priv) if(cur_cnt == 0){ spin_lock_bh(&hdd_ipa->q_lock); - list_add_tail(&send_desc_head->link, &hdd_ipa->free_desc_head); + 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_not_used++; @@ -699,7 +711,8 @@ 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); @@ -740,7 +753,8 @@ rxt_end: done_desc->priv = NULL; done_desc->pyld_buffer = NULL; done_desc->pyld_len = 0; - list_add_tail(&done_desc->link, &hdd_ipa->free_desc_head); + list_add_tail(&done_desc->link, + &hdd_ipa->free_desc_head); hdd_ipa->stats.freeq_cnt++; #ifdef HDD_IPA_EXTRA_DP_COUNTERS hdd_ipa->stats.freeq_reclaim++; @@ -781,12 +795,6 @@ rxt_end: } } -static void hdd_ipa_w2i_write_done_handler( - struct ipa_tx_data_desc *done_desc_head) -{ - hdd_ipa_process_evt(HDD_IPA_WRITE_DONE_EVT, done_desc_head); -} - VOS_STATUS hdd_ipa_process_rxt(v_VOID_t *vosContext, adf_nbuf_t rx_buf_list, v_U8_t sta_id) { @@ -804,50 +812,43 @@ VOS_STATUS hdd_ipa_process_rxt(v_VOID_t *vosContext, adf_nbuf_t rx_buf_list, return VOS_STATUS_SUCCESS; } - - -void hdd_ipa_w2i_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data) +static void hdd_ipa_w2i_cb(void *priv, enum ipa_dp_evt_type evt, + unsigned long data) { - struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; - uint8_t client; + struct hdd_ipa_priv *hdd_ipa = NULL; + hdd_adapter_t *adapter = NULL; struct ipa_tx_data_desc *done_desc_head; adf_nbuf_t skb; - uint8_t sta_id; - hdd_adapter_t *adap_dev=NULL; + uint8_t iface_id; - client = *((uint8_t *)priv); - 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_pipe_id_2_ipa_client_id[HDD_IPA_RX_PIPE]); - return; - } + hdd_ipa = (struct hdd_ipa_priv *)priv; switch (evt) { case IPA_RECEIVE: skb = (adf_nbuf_t) data; - 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 { + iface_id = HDD_IPA_GET_IFACE_ID(skb->data); + if (iface_id >= HDD_IPA_MAX_IFACE) { HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, - "w2i cb: wrong sta_id: %d", sta_id); + "IPA_RECEIVE: Invalid iface_id: %u\n", + iface_id); + adf_nbuf_free(skb); + return; } + adapter = hdd_ipa->iface_context[iface_id].adapter; + + HDD_IPA_DBG_DUMP(VOS_TRACE_LEVEL_DEBUG, "w2i -- skb", skb->data, + 8); + + skb_pull(skb, HDD_IPA_WLAN_CLD_HDR_LEN); + hdd_ipa->stats.rx_ipa_excep++; - hdd_ipa_send_skb_to_network(skb, adap_dev); + hdd_ipa_send_skb_to_network(skb, adapter); break; case IPA_WRITE_DONE: done_desc_head = (struct ipa_tx_data_desc *)data; - hdd_ipa_w2i_write_done_handler(done_desc_head); + hdd_ipa_process_evt(HDD_IPA_WRITE_DONE_EVT, done_desc_head); break; default: HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, @@ -856,93 +857,33 @@ void hdd_ipa_w2i_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data) } } -void hdd_ipa_nbuf_cb(adf_nbuf_t skb) +static void hdd_ipa_nbuf_cb(adf_nbuf_t 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)); + HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, "%lx", NBUF_OWNER_PRIV_DATA(skb)); ipa_free_skb((struct ipa_rx_data *) NBUF_OWNER_PRIV_DATA(skb)); } -#ifdef WLAN_TX_MUL -void hdd_ipa_i2w_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data) +static 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_mul *ipa_tx_desc; - adf_nbuf_t skb; - uint8_t client, pipe_id; - - 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); - } -} - -#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 hdd_ipa_priv *hdd_ipa = NULL; struct ipa_rx_data *ipa_tx_desc; + struct hdd_ipa_iface_context *iface_context; adf_nbuf_t skb; - 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); + iface_context = (struct hdd_ipa_iface_context *) priv; ipa_tx_desc = (struct ipa_rx_data *)data; skb = ipa_tx_desc->skb; + hdd_ipa = iface_context->hdd_ipa; + 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; @@ -950,36 +891,22 @@ void hdd_ipa_i2w_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data) 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_DBG_DUMP(VOS_TRACE_LEVEL_DEBUG, "i2w", skb->data, 8); - 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++; - skb = WLANTL_SendIPA_DataFrame(hdd_ipa->hdd_ctx->pvosContext, hdd_ipa->pipe_to_vdev[pipe_id], - ipa_tx_desc->skb); + skb = WLANTL_SendIPA_DataFrame(hdd_ipa->hdd_ctx->pvosContext, + iface_context->tl_context, 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) { @@ -987,12 +914,12 @@ static int hdd_ipa_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa) struct ipa_sys_connect_params *ipa; /*setup TX pipes */ - for (i = 0; i < HDD_IPA_RX_PIPE; i++) { + for (i = 0; i < HDD_IPA_MAX_IFACE; i++) { ipa = &hdd_ipa->sys_pipe[i].ipa_sys_params; - ipa->client = hdd_pipe_id_2_ipa_client_id[i]; + ipa->client = hdd_ipa_adapter_2_client[i].cons_client; ipa->desc_fifo_sz = hdd_ipa->hdd_ctx->cfg_ini->IpaDescSize; - ipa->priv = &hdd_pipe_id_2_ipa_client_id[i]; + ipa->priv = &hdd_ipa->iface_context[i]; ipa->notify = hdd_ipa_i2w_cb; ipa->ipa_ep_cfg.hdr.hdr_len = HDD_IPA_WLAN_TX_HDR_LEN; @@ -1000,17 +927,35 @@ static int hdd_ipa_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa) ret = ipa_setup_sys_pipe(ipa, &(hdd_ipa->sys_pipe[i].conn_hdl)); if (ret) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Fail: %d", ret); + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Failed for pipe %d" + " ret: %d", i, ret); goto setup_sys_pipe_fail; } hdd_ipa->sys_pipe[i].conn_hdl_valid = 1; } + /* + * Hard code it here, this can be extended if in case PROD pipe is also + * per interface. Right now there is no advantage of doing this. + */ + hdd_ipa->prod_client = IPA_CLIENT_WLAN1_PROD; + ipa = &hdd_ipa->sys_pipe[HDD_IPA_RX_PIPE].ipa_sys_params; - 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->client = hdd_ipa->prod_client; + + /* The maximum number of descriptors that can be provided to a BAM at + * once is one less than the total number of descriptors that the buffer + * can contain. + * If max_num_of_descriptors = (BAM_PIPE_DESCRIPTOR_FIFO_SIZE / sizeof + * (SPS_DESCRIPTOR)), then (max_num_of_descriptors - 1) descriptors can + * be provided at once. + * Because of above requirement, one extra descriptor will be added to + * make sure hardware always has one descriptor. + */ + ipa->desc_fifo_sz = hdd_ipa->hdd_ctx->cfg_ini->IpaDescSize + + sizeof(struct sps_iovec); + ipa->priv = hdd_ipa; ipa->notify = hdd_ipa_w2i_cb; ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT; @@ -1020,59 +965,73 @@ static int hdd_ipa_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa) ret = ipa_setup_sys_pipe(ipa, &(hdd_ipa->sys_pipe[i].conn_hdl)); if (ret) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Fail: %d", ret); + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Failed for RX pipe: %d", + ret); goto setup_sys_pipe_fail; } hdd_ipa->sys_pipe[HDD_IPA_RX_PIPE].conn_hdl_valid = 1; + return ret; + setup_sys_pipe_fail: + + while (--i >= 0) { + ipa_teardown_sys_pipe(hdd_ipa->sys_pipe[i].conn_hdl); + vos_mem_zero(&hdd_ipa->sys_pipe[i], + sizeof(struct hdd_ipa_sys_pipe )); + } + return ret; } /* Disconnect all the Sys pipes */ -void hdd_ipa_teardown_sys_pipe(struct hdd_ipa_priv *hdd_ipa) +static void hdd_ipa_teardown_sys_pipe(struct hdd_ipa_priv *hdd_ipa) { int ret = 0, i; - for (i = 0; i < HDD_IPA_MAX_PIPE; i++) { + for (i = 0; i < HDD_IPA_MAX_SYSBAM_PIPE; i++) { if (hdd_ipa->sys_pipe[i].conn_hdl_valid) { ret = ipa_teardown_sys_pipe( hdd_ipa->sys_pipe[i].conn_hdl); if (ret) - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "fail: %d", - ret); + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Failed: %d", + ret); hdd_ipa->sys_pipe[i].conn_hdl_valid = 0; } } } -int hdd_ipa_register_interface(struct hdd_ipa_priv *hdd_ipa, uint8_t sta_id, const char *ifname) +static int hdd_ipa_register_interface(struct hdd_ipa_priv *hdd_ipa, + struct hdd_ipa_iface_context *iface_context) { struct ipa_tx_intf tx_intf; struct ipa_rx_intf rx_intf; struct ipa_ioc_tx_intf_prop *tx_prop = NULL; struct ipa_ioc_rx_intf_prop *rx_prop = NULL; + char *ifname = iface_context->adapter->dev->name; char ipv4_hdr_name[IPA_RESOURCE_NAME_MAX]; char ipv6_hdr_name[IPA_RESOURCE_NAME_MAX]; - int ip_max = HDD_IPA_IPV4; + int num_prop = 1; int ret = 0; if (hdd_ipa_is_ipv6_enabled(hdd_ipa)) - ip_max = HDD_IPA_IPV6; + num_prop++; /* Allocate TX properties for TOS categories, 1 each for IPv4 & IPv6 */ - tx_prop = hdd_ipa_kzalloc(sizeof(struct ipa_ioc_tx_intf_prop) * ip_max); + tx_prop = vos_mem_malloc(sizeof(struct ipa_ioc_tx_intf_prop) * + num_prop); if (!tx_prop) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "ENOMEM"); + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "tx_prop allocation failed"); 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 = vos_mem_malloc(sizeof(struct ipa_ioc_rx_intf_prop) * + num_prop); if (!rx_prop) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "ENOMEM"); + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "rx_prop allocation failed"); goto register_interface_fail; } vos_mem_zero(&tx_intf, sizeof(tx_intf)); @@ -1084,23 +1043,42 @@ int hdd_ipa_register_interface(struct hdd_ipa_priv *hdd_ipa, uint8_t sta_id, con 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_prop[IPA_IP_v4].src_pipe = iface_context->prod_client; + + rx_prop[IPA_IP_v4].attrib.attrib_mask = IPA_FLT_META_DATA; + + /* + * Interface ID is 3rd byte in the CLD header. Add the meta data and + * mask to identify the interface in IPA hardware + */ + rx_prop[IPA_IP_v4].attrib.meta_data = + htonl(iface_context->iface_id << 16); + rx_prop[IPA_IP_v4].attrib.meta_data_mask = htonl(0x00FF0000); + rx_intf.num_props++; if (hdd_ipa_is_ipv6_enabled(hdd_ipa)) { rx_prop[IPA_IP_v6].ip = IPA_IP_v6; - rx_prop[IPA_IP_v6].src_pipe = IPA_CLIENT_WLAN1_PROD; + rx_prop[IPA_IP_v6].src_pipe = iface_context->prod_client; + + rx_prop[IPA_IP_v4].attrib.attrib_mask = IPA_FLT_META_DATA; + rx_prop[IPA_IP_v4].attrib.meta_data = + htonl(iface_context->iface_id << 16); + rx_prop[IPA_IP_v4].attrib.meta_data_mask = htonl(0x00FF0000); + 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_prop[IPA_IP_v4].dst_pipe = iface_context->cons_client; + 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]]; + tx_prop[IPA_IP_v6].dst_pipe = iface_context->cons_client; strlcpy(tx_prop[IPA_IP_v6].hdr_name, ipv6_hdr_name, - IPA_RESOURCE_NAME_MAX); + IPA_RESOURCE_NAME_MAX); tx_intf.num_props++; } @@ -1111,201 +1089,248 @@ int hdd_ipa_register_interface(struct hdd_ipa_priv *hdd_ipa, uint8_t sta_id, con ret = ipa_register_intf(ifname, &tx_intf, &rx_intf); register_interface_fail: - adf_os_mem_free(tx_prop); - adf_os_mem_free(rx_prop); + vos_mem_free(tx_prop); + vos_mem_free(rx_prop); return ret; } -static int hdd_ipa_add_header_info(enum ipa_wlan_event type, uint8_t sta_id, uint8_t *mac_addr) +static void hdd_remove_ipa_header(char *name) { - struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; - char *ifname; - struct ipa_ioc_add_hdr *ipahdr = NULL; - 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) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "adap_dev NULL"); - goto add_header_info_ctx_fail; + struct ipa_ioc_get_hdr hdrlookup; + int ret = 0, len; + struct ipa_ioc_del_hdr *ipa_hdr; + + vos_mem_zero(&hdrlookup, sizeof(hdrlookup)); + strlcpy(hdrlookup.name, name, sizeof(hdrlookup.name)); + ret = ipa_get_hdr(&hdrlookup); + if (ret) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "Hdr deleted already %s, %d", + name, ret); + return; } - ifname = adap_dev->dev->name; - for (i = 0; i < HDD_IPA_MAX_PIPE; i++) - hdd_ipa->pipe_to_vdev[i] = NULL; + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "hdl: 0x%x", hdrlookup.hdl); + len = sizeof(struct ipa_ioc_del_hdr) + sizeof(struct ipa_hdr_del)*1; + ipa_hdr = (struct ipa_ioc_del_hdr *) vos_mem_malloc(len); + if (ipa_hdr == NULL) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "ipa_hdr allocation failed"); + return; + } + ipa_hdr->num_hdls = 1; + ipa_hdr->commit = 0; + ipa_hdr->hdl[0].hdl = hdrlookup.hdl; + ipa_hdr->hdl[0].status = -1; + ret = ipa_del_hdr(ipa_hdr); + if (ret != 0) + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Delete header failed: %d", + ret); - 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; - } - } + vos_mem_free(ipa_hdr); +} - 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]); +static int hdd_ipa_add_header_info(struct hdd_ipa_priv *hdd_ipa, + struct hdd_ipa_iface_context *iface_context, uint8_t *mac_addr) +{ + hdd_adapter_t *adapter = iface_context->adapter; + char *ifname; + struct ipa_ioc_add_hdr *ipa_hdr = NULL; + int ret = -EINVAL; + struct hdd_ipa_tx_hdr *tx_hdr = NULL; + ifname = adapter->dev->name; - 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; - } + + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "Add Partial hdr: %s, %pM", + ifname, mac_addr); /* dynamically allocate the memory to add the hdrs */ - ipahdr = hdd_ipa_kzalloc(sizeof(struct ipa_ioc_add_hdr) + - sizeof(struct ipa_hdr_add)); - if (!ipahdr) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "%s: ENOMEM", ifname); - return -ENOMEM; + ipa_hdr = vos_mem_malloc(sizeof(struct ipa_ioc_add_hdr) + + sizeof(struct ipa_hdr_add)); + if (!ipa_hdr) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: ipa_hdr allocation failed", ifname); + ret = -ENOMEM; + goto end; } - ipahdr->commit = 0; - ipahdr->num_hdrs = 1; + ipa_hdr->commit = 0; + ipa_hdr->num_hdrs = 1; + + tx_hdr = (struct hdd_ipa_tx_hdr *)ipa_hdr->hdr[0].hdr; + /* Set the Source MAC */ - 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); + memcpy(tx_hdr, &ipa_tx_hdr, HDD_IPA_WLAN_TX_HDR_LEN); + memcpy(tx_hdr->eth.h_source, mac_addr, ETH_ALEN); - 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; + snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s", + ifname, HDD_IPA_IPV4_NAME_EXT); + ipa_hdr->hdr[0].hdr_len = HDD_IPA_WLAN_TX_HDR_LEN; + ipa_hdr->hdr[0].is_partial = 1; + ipa_hdr->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); + tx_hdr->llc_snap.eth_type = cpu_to_be16(ETH_P_IP); - ret = ipa_add_hdr(ipahdr); + ret = ipa_add_hdr(ipa_hdr); if (ret) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "%s IPv4 fail: %d", ifname - , ret); - goto add_header_info_fail; + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "%s IPv4 add hdr failed: %d", + ifname, ret); + goto end; } - HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%s: IPv4 hdr_hdl: %x", - ipahdr->hdr[0].name, ipahdr->hdr[0].hdr_hdl); + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%s: IPv4 hdr_hdl: 0x%x", + ipa_hdr->hdr[0].name, ipa_hdr->hdr[0].hdr_hdl); + if (hdd_ipa_is_ipv6_enabled(hdd_ipa)) { - snprintf(ipahdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s", - ifname, HDD_IPA_IPV6_NAME_EXT); + snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s", + ifname, HDD_IPA_IPV6_NAME_EXT); + /* Set the type to IPV6 in the header*/ - ((struct ipa_tx_hdr *)(ipahdr->hdr[0].hdr))->llc_snap.eth_type = cpu_to_be16(ETH_P_IPV6); + tx_hdr->llc_snap.eth_type = cpu_to_be16(ETH_P_IPV6); + + ret = ipa_add_hdr(ipa_hdr); - ret = ipa_add_hdr(ipahdr); if (ret) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, - "%s: IPv6 hdr fail: %d", ifname, ret); - goto add_header_info_fail; + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: IPv6 add hdr failed: %d", + ifname, ret); + goto clean_ipv4_hdr; } - HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%s: IPv6 hdr_hdl: %x", - ipahdr->hdr[0].name, ipahdr->hdr[0].hdr_hdl); + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%s: IPv6 hdr_hdl: 0x%x", + ipa_hdr->hdr[0].name, ipa_hdr->hdr[0].hdr_hdl); } - /* Configure the TX and RX pipes filter rules */ - ret = hdd_ipa_register_interface(hdd_ipa, sta_id, ifname); -add_header_info_fail: - adf_os_mem_free(ipahdr); -add_header_info_ctx_fail: - return ret; -} - -void hdd_remove_ipa_header(char *name) -{ - struct ipa_ioc_get_hdr hdrlookup; - int ret = 0, len; - struct ipa_ioc_del_hdr *ipahdr; - - vos_mem_zero(&hdrlookup, sizeof(hdrlookup)); - strlcpy(hdrlookup.name, name, sizeof(hdrlookup.name)); - ret = ipa_get_hdr(&hdrlookup); - if (ret) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "Hdr deleted already %s, %d", - name, ret); - return; - } + vos_mem_free(ipa_hdr); + return ret; - HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "hdl: %x", hdrlookup.hdl); - len = sizeof(struct ipa_ioc_del_hdr) + sizeof(struct ipa_hdr_del)*1; - ipahdr = (struct ipa_ioc_del_hdr *) hdd_ipa_kzalloc(len); - if (ipahdr == NULL) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "ENOMEM"); - return; - } - ipahdr->num_hdls = 1; - ipahdr->commit = 0; - ipahdr->hdl[0].hdl = hdrlookup.hdl; - ipahdr->hdl[0].status = -1; - ret = ipa_del_hdr(ipahdr); - if (ret != 0) - HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "Fail: %d", ret); +clean_ipv4_hdr: + snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s", + ifname, HDD_IPA_IPV4_NAME_EXT); + hdd_remove_ipa_header(ipa_hdr->hdr[0].name); +end: + if(ipa_hdr) + vos_mem_free(ipa_hdr); - adf_os_mem_free(ipahdr); + return ret; } -void hdd_ipa_clean_hdr(hdd_adapter_t *adap_dev, uint8_t sta_id) +static void hdd_ipa_clean_hdr(hdd_adapter_t *adapter) { struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; 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); + adapter->dev->name, HDD_IPA_IPV4_NAME_EXT); hdd_remove_ipa_header(name_ipa); if (hdd_ipa_is_ipv6_enabled(hdd_ipa)) { snprintf(name_ipa, IPA_RESOURCE_NAME_MAX, "%s%s", - adap_dev->dev->name, HDD_IPA_IPV6_NAME_EXT); + adapter->dev->name, HDD_IPA_IPV6_NAME_EXT); hdd_remove_ipa_header(name_ipa); } /* unregister the interface with IPA */ - ret = ipa_deregister_intf(adap_dev->dev->name); + ret = ipa_deregister_intf(adapter->dev->name); if (ret) HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, - "%s: ipa_deregister_intf fail: %d", adap_dev->dev->name, ret); + "%s: ipa_deregister_intf fail: %d", + adapter->dev->name, ret); +} + +static void hdd_ipa_cleanup_iface(struct hdd_ipa_priv *hdd_ipa, + struct hdd_ipa_iface_context *iface_context) +{ + hdd_ipa_clean_hdr(iface_context->adapter); + + iface_context->adapter->ipa_context = NULL; + iface_context->adapter = NULL; + iface_context->tl_context = NULL; +} + + +static int hdd_ipa_setup_iface(struct hdd_ipa_priv *hdd_ipa, + hdd_adapter_t *adapter, uint8_t sta_id) +{ + struct hdd_ipa_iface_context *iface_context = NULL; + void *tl_context = NULL; + int i, ret = 0; + + for (i = 0; i < HDD_IPA_MAX_IFACE; i++) { + if (hdd_ipa->iface_context[i].adapter == NULL) { + iface_context = &hdd_ipa->iface_context[i]; + break; + } + } + + if (iface_context == NULL) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "All the IPA interfaces are in use"); + ret = -ENOMEM; + goto end; + } + + + adapter->ipa_context = iface_context; + iface_context->adapter = adapter; + iface_context->sta_id = sta_id; + tl_context = tl_shim_get_vdev_by_sta_id(hdd_ipa->hdd_ctx->pvosContext, + sta_id); + + if (tl_context == NULL) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "Not able to get TL context sta_id: %d", + sta_id); + ret = -EINVAL; + goto end; + } + + iface_context->tl_context = tl_context; + + ret = hdd_ipa_add_header_info(hdd_ipa, iface_context, + adapter->dev->dev_addr); + + if (ret) + goto end; + + /* Configure the TX and RX pipes filter rules */ + ret = hdd_ipa_register_interface(hdd_ipa, iface_context); + if (ret) + goto cleanup_header; + + return ret; + +cleanup_header: + + hdd_ipa_clean_hdr(adapter); +end: + if (iface_context) + hdd_ipa_cleanup_iface(hdd_ipa, iface_context); + return ret; } static void hdd_ipa_msg_free_fn(void *buff, uint32_t len, uint32_t type) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "msg type:%d, len:%d\n", type, len); - adf_os_mem_free(buff); + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "msg type:%d, len:%d", type, len); + ghdd_ipa->stats.free_msg++; + vos_mem_free(buff); } -int hdd_ipa_wlan_evt(void *Adapter, uint8_t sta_id, +int hdd_ipa_wlan_evt(hdd_adapter_t *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; struct ipa_wlan_msg_ex *msg_ex = NULL; int ret; - const char *hdd_ipa_event_name[IPA_EVENT_MAX] = { + const char *hdd_ipa_event_name[IPA_WLAN_EVENT_MAX] = { __stringify(WLAN_CLIENT_CONNECT), __stringify(WLAN_CLIENT_DISCONNECT), __stringify(WLAN_CLIENT_POWER_SAVE_MODE), @@ -1318,69 +1343,67 @@ 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], - mac_addr, sta_id); - if (type >= IPA_EVENT_MAX) + adapter->dev->name, hdd_ipa_event_name[type], mac_addr, + sta_id); + + if (type >= IPA_WLAN_EVENT_MAX) return -EINVAL; if (WARN_ON(is_zero_ether_addr(mac_addr))) return -EINVAL; + hdd_ipa->stats.event[type]++; + switch (type) { case WLAN_STA_CONNECT: case WLAN_AP_CONNECT: - hdd_ipa_add_header_info(type, sta_id, mac_addr); + ret = hdd_ipa_setup_iface(hdd_ipa, adapter, sta_id); + if (ret) + goto end; 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); + hdd_ipa_cleanup_iface(hdd_ipa, + adapter->ipa_context); 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 */ - } + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%d %d", + adapter->dev->ifindex, sta_id); meta.msg_type = type; meta.msg_len = (sizeof(struct ipa_wlan_msg_ex) + sizeof(struct ipa_wlan_hdr_attrib_val)); - msg_ex = hdd_ipa_kzalloc (meta.msg_len); + msg_ex = vos_mem_malloc (meta.msg_len); + if (msg_ex == NULL) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "ENOMEM"); + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "msg_ex allocation failed"); return -ENOMEM; } - strlcpy(msg_ex->name, adap_dev->dev->name, IPA_RESOURCE_NAME_MAX); + strlcpy(msg_ex->name, adapter->dev->name, + IPA_RESOURCE_NAME_MAX); 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); + IPA_MAC_ADDR_SIZE); ret = ipa_send_msg(&meta, msg_ex, hdd_ipa_msg_free_fn); if (ret) { HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%s: Evt: %d : %d", msg_ex->name, meta.msg_type, ret); - adf_os_mem_free(msg_ex); + vos_mem_free(msg_ex); return ret; } + hdd_ipa->stats.send_msg++; + 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: @@ -1388,30 +1411,59 @@ int hdd_ipa_wlan_evt(void *Adapter, uint8_t sta_id, } meta.msg_len = sizeof(struct ipa_wlan_msg); - msg = hdd_ipa_kzalloc(meta.msg_len); + msg = vos_mem_malloc(meta.msg_len); if (msg == NULL) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "ENOMEM"); + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "msg allocation failed"); return -ENOMEM; } meta.msg_type = type; - strlcpy(msg->name, adap_dev->dev->name, IPA_RESOURCE_NAME_MAX); + strlcpy(msg->name, adapter->dev->name, IPA_RESOURCE_NAME_MAX); memcpy(msg->mac_addr, mac_addr, ETH_ALEN); + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%s: Evt: %d", msg->name, meta.msg_type); + ret = ipa_send_msg(&meta, msg, hdd_ipa_msg_free_fn); if (ret) { HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%s: Evt: %d fail:%d", msg->name, meta.msg_type, ret); - adf_os_mem_free(msg); + vos_mem_free(msg); return ret; } + hdd_ipa->stats.send_msg++; + +end: return ret; } +static void hdd_ipa_rx_pipe_desc_free(void) +{ + struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; + uint32_t i = 0, max_desc_cnt; + struct ipa_tx_data_desc *desc, *tmp; + + max_desc_cnt = hdd_ipa->hw_desc_cnt * HDD_IPA_DESC_BUFFER_RATIO; + + spin_lock_bh(&hdd_ipa->q_lock); + list_for_each_entry_safe(desc, tmp, &hdd_ipa->free_desc_head, link) { + list_del(&desc->link); + spin_unlock_bh(&hdd_ipa->q_lock); + vos_mem_free(desc); + spin_lock_bh(&hdd_ipa->q_lock); + i++; + } + spin_unlock_bh(&hdd_ipa->q_lock); + + if (i != max_desc_cnt) + HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, "free desc leak"); + +} + + static int hdd_ipa_rx_pipe_desc_alloc(void) { struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; @@ -1424,46 +1476,34 @@ static int hdd_ipa_rx_pipe_desc_alloc(void) max_desc_cnt = hdd_ipa->hw_desc_cnt * HDD_IPA_DESC_BUFFER_RATIO; spin_lock_init(&hdd_ipa->q_lock); - spin_lock_bh(&hdd_ipa->q_lock); + INIT_LIST_HEAD(&hdd_ipa->free_desc_head); INIT_LIST_HEAD(&hdd_ipa->pend_desc_head); hdd_ipa->stats.freeq_cnt = max_desc_cnt; for (i = 0; i < max_desc_cnt; i++) { - tmp_desc = hdd_ipa_kzalloc(sizeof(struct + tmp_desc = vos_mem_malloc(sizeof(struct ipa_tx_data_desc)); if (!tmp_desc) { - ret = -1; - break; + ret = -ENOMEM; + + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "Descriptor allocation failed\n"); + goto fail; } + spin_lock_bh(&hdd_ipa->q_lock); list_add_tail(&tmp_desc->link, &hdd_ipa->free_desc_head); + spin_unlock_bh(&hdd_ipa->q_lock); } - spin_unlock_bh(&hdd_ipa->q_lock); + + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "Desc sz:%d h_desc_cnt:%d freeq_cnt:%llu", hdd_ipa->hdd_ctx->cfg_ini->IpaDescSize, hdd_ipa->hw_desc_cnt, hdd_ipa->stats.freeq_cnt); return ret; -} - -static void hdd_ipa_rx_pipe_desc_free(void) -{ - struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; - uint32_t i = 0, max_desc_cnt; - struct ipa_tx_data_desc *desc, *tmp; - - max_desc_cnt = hdd_ipa->hw_desc_cnt * HDD_IPA_DESC_BUFFER_RATIO; - - spin_lock_bh(&hdd_ipa->q_lock); - list_for_each_entry_safe(desc, tmp, &hdd_ipa->free_desc_head, link) { - list_del(&desc->link); - adf_os_mem_free(desc); - i++; - } - spin_unlock_bh(&hdd_ipa->q_lock); - - if (i != max_desc_cnt) - HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, "free mem leak"); - +fail: + hdd_ipa_rx_pipe_desc_free(); + return ret; } static ssize_t hdd_ipa_debugfs_read_ipa_stats(struct file *file, @@ -1573,7 +1613,7 @@ static const struct file_operations fops_ipa_stats = { }; -int hdd_ipa_debugfs_init(struct hdd_ipa_priv *hdd_ipa) +static int hdd_ipa_debugfs_init(struct hdd_ipa_priv *hdd_ipa) { #ifdef WLAN_OPEN_SOURCE hdd_ipa->debugfs_dir = debugfs_create_dir("cld", @@ -1587,6 +1627,13 @@ int hdd_ipa_debugfs_init(struct hdd_ipa_priv *hdd_ipa) return 0; } +static void hdd_ipa_debugfs_remove(struct hdd_ipa_priv *hdd_ipa) +{ +#ifdef WLAN_OPEN_SOURCE + debugfs_remove_recursive(hdd_ipa->debugfs_dir); +#endif +} + /** * hdd_ipa_init() - Allocate hdd_ipa resources, ipa pipe resource and register * wlan interface with IPA module. @@ -1599,21 +1646,31 @@ VOS_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx) { struct hdd_ipa_priv *hdd_ipa = NULL; int ret, i; - if (!hdd_ipa_is_enabled(hdd_ctx)) - return 0; + struct hdd_ipa_iface_context *iface_context = NULL; - for (i = 0; i < HDD_IPA_WLAN_MAX_STA_ID; i++) - wlan_sta_id_2_hdd_pipe_id[i] = 0xFF; + if (!hdd_ipa_is_enabled(hdd_ctx)) + return VOS_STATUS_SUCCESS; - hdd_ipa = hdd_ipa_kzalloc(sizeof(struct hdd_ipa_priv)); + hdd_ipa = vos_mem_malloc(sizeof(struct hdd_ipa_priv)); if (!hdd_ipa) { - HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, "ENOMEM"); + HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, "hdd_ipa allocation failed"); goto fail_setup_rm; } hdd_ctx->hdd_ipa = hdd_ipa; ghdd_ipa = hdd_ipa; hdd_ipa->hdd_ctx = hdd_ctx; + /* Create the interface context */ + for (i = 0; i < HDD_IPA_MAX_IFACE; i++) { + iface_context = &hdd_ipa->iface_context[i]; + iface_context->hdd_ipa = hdd_ipa; + iface_context->cons_client = + hdd_ipa_adapter_2_client[i].cons_client; + iface_context->prod_client = + hdd_ipa_adapter_2_client[i].prod_client; + iface_context->iface_id = i; + } + ret = hdd_ipa_setup_rm(hdd_ipa); if (ret) goto fail_setup_rm; @@ -1622,8 +1679,6 @@ VOS_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx) if (ret) goto fail_create_sys_pipe; - atomic_set(&hdd_ipa->rm_state, HDD_IPA_RM_RELEASED); - ret = hdd_ipa_rx_pipe_desc_alloc(); if (ret) goto fail_alloc_rx_pipe_desc; @@ -1632,17 +1687,21 @@ VOS_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx) if (ret) goto fail_alloc_rx_pipe_desc; - HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, "IPA Init Done"); #ifndef HDD_IPA_USE_IPA_RM_TIMER setup_timer(&hdd_ipa->rm_timer, hdd_ipa_rm_timer_handler, (unsigned long) &hdd_ipa); #endif + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "IPA Init Done"); + return VOS_STATUS_SUCCESS; fail_alloc_rx_pipe_desc: hdd_ipa_rx_pipe_desc_free(); fail_create_sys_pipe: hdd_ipa_destory_rm_resource(hdd_ipa); fail_setup_rm: + if (hdd_ipa) + vos_mem_free(hdd_ipa); + return VOS_STATUS_E_FAILURE; } @@ -1653,6 +1712,8 @@ VOS_STATUS hdd_ipa_cleanup(hdd_context_t *hdd_ctx) if (!hdd_ipa_is_enabled(hdd_ctx)) return VOS_STATUS_SUCCESS; + hdd_ipa_debugfs_remove(hdd_ipa); + #ifndef HDD_IPA_USE_IPA_RM_TIMER del_timer(&hdd_ipa->rm_timer); #endif @@ -1664,73 +1725,9 @@ VOS_STATUS hdd_ipa_cleanup(hdd_context_t *hdd_ctx) hdd_ipa_teardown_sys_pipe(hdd_ipa); hdd_ipa_destory_rm_resource(hdd_ipa); - adf_os_mem_free(hdd_ctx->hdd_ipa); + vos_mem_free(hdd_ipa); + hdd_ctx->hdd_ipa = NULL; return VOS_STATUS_SUCCESS; } - -#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/VOSS/src/vos_trace.c b/CORE/VOSS/src/vos_trace.c index 5b5f33562506..ea81ece70c25 100644 --- a/CORE/VOSS/src/vos_trace.c +++ b/CORE/VOSS/src/vos_trace.c @@ -388,10 +388,15 @@ void vos_trace_hex_dump( VOS_MODULE_ID module, VOS_TRACE_LEVEL level, { char *buf = (char *)data; int i; + + if (!(gVosTraceInfo[module].moduleTraceLevel & + VOS_TRACE_LEVEL_TO_MODULE_BITMASK(level))) + return; + for (i=0; (i+7)<buf_len; i+=8) { vos_trace_msg( module, level, - "%02x %02x %02x %02x %02x %02x %02x %02x \n", + "%02x %02x %02x %02x %02x %02x %02x %02x", buf[i], buf[i+1], buf[i+2], |
