diff options
| author | Prakash Dhavali <pdhavali@codeaurora.org> | 2014-02-08 11:11:53 -0800 |
|---|---|---|
| committer | Prakash Dhavali <pdhavali@codeaurora.org> | 2014-02-08 11:15:10 -0800 |
| commit | e71909cd0077c2a5d3118cb415aa8a351a7dbb6d (patch) | |
| tree | 53fa194004fad9ee6e26429e48a6b90eb364e651 | |
| parent | 5af3ed16d9d7ff1b7e7d3baea2492e6d44209f18 (diff) | |
| parent | f69dd0f17872aeb162c48241adf3b7321b09c8ee (diff) | |
Merge remote-tracking branch 'origin/caf/caf-wlan/master'
Release 1.0.0.31 QCA CLD WLAN Host Driver
* origin/caf/caf-wlan/master:
Cafstaging Release 1.0.0.31
qcacld: ipa: Add interface specific changes
qcacld: ipa: Remove IPA_RM_RESOURCE_A2_CONS usage
qcacld: Add function of updating macaddress from wlan_mac.bin
qcacld: Silent recovery on FW dump failure
qcacld: Integrating batch scan fixes from pronto
wlan:qcacld:rome_ibss: Added Rome IBSS WEP Security support
qcacld: Define open source flag based on license
qcacld: CL 835222 - update fw common interface files
wlan: make BAP module 64 bit clean
29 files changed, 1329 insertions, 917 deletions
diff --git a/Android.mk b/Android.mk index de83532a4213..f86c223bcb1e 100644 --- a/Android.mk +++ b/Android.mk @@ -22,8 +22,10 @@ ifneq ($(findstring vendor,$(LOCAL_PATH)),) # Determine if we are Proprietary or Open Source ifneq ($(findstring opensource,$(LOCAL_PATH)),) WLAN_PROPRIETARY := 0 + WLAN_OPEN_SOURCE := 1 else WLAN_PROPRIETARY := 1 + WLAN_OPEN_SOURCE := 0 endif ifeq ($(WLAN_PROPRIETARY),1) @@ -52,6 +54,7 @@ KBUILD_OPTIONS += MODNAME=wlan KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM) KBUILD_OPTIONS += $(WLAN_SELECT) KBUILD_OPTIONS += $(WLAN_ISOC_SELECT) +KBUILD_OPTIONS += WLAN_OPEN_SOURCE=$(WLAN_OPEN_SOURCE) include $(CLEAR_VARS) LOCAL_MODULE := $(WLAN_CHIPSET)_wlan.ko @@ -69,6 +72,7 @@ include $(DLKM_DIR)/AndroidKernelModule.mk $(shell mkdir -p $(TARGET_OUT)/lib/modules; \ ln -sf /system/lib/modules/$(WLAN_CHIPSET)/$(WLAN_CHIPSET)_wlan.ko \ $(TARGET_OUT)/lib/modules/wlan.ko) +$(shell ln -sf /persist/wlan_mac.bin $(TARGET_OUT_ETC)/firmware/wlan/qca_cld/wlan_mac.bin) endif # DLKM check diff --git a/CORE/BAP/src/bapApiData.c b/CORE/BAP/src/bapApiData.c index 44225547b46c..f9249a4a0f70 100644 --- a/CORE/BAP/src/bapApiData.c +++ b/CORE/BAP/src/bapApiData.c @@ -310,7 +310,7 @@ WLANBAP_XlateTxDataPkt v_PVOID_t pHddHdl; /* Handle to return BSL context in */ v_U16_t headerLength; /* The 802.3 frame length*/ v_U16_t protoType = WLANBAP_BT_AMP_TYPE_DATA; /* The protocol type bytes*/ - v_U32_t value = 0; + uintptr_t value = 0; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ @@ -443,7 +443,7 @@ WLANBAP_XlateTxDataPkt /*Set the logical link handle as user data so that we can retrieve it on Tx Complete */ - value = (v_U32_t)hciACLHeader.logLinkHandle; + value = (uintptr_t)hciACLHeader.logLinkHandle; vos_pkt_set_user_data_ptr( vosDataBuff, VOS_PKT_USER_DATA_ID_BAP, (v_VOID_t *)value); @@ -980,12 +980,12 @@ WLANBAP_TxCompCB VOS_STATUS wTxSTAtus ) { - VOS_STATUS vosStatus; - ptBtampHandle bapHdl; /* holds ptBtampHandle value returned */ + VOS_STATUS vosStatus; + ptBtampHandle bapHdl; /* holds ptBtampHandle value returned */ ptBtampContext bapContext; /* Holds the btampContext value returned */ - v_PVOID_t pHddHdl; /* Handle to return BSL context in */ + v_PVOID_t pHddHdl; /* Handle to return BSL context in */ v_PVOID_t pvlogLinkHandle = NULL; - v_U32_t value; + uintptr_t value; WLANBAP_HCIACLHeaderType hciACLHeader; @@ -1038,7 +1038,7 @@ WLANBAP_TxCompCB vos_pkt_get_user_data_ptr( vosDataBuff, VOS_PKT_USER_DATA_ID_BAP, &pvlogLinkHandle); - value = (v_U32_t)pvlogLinkHandle; + value = (uintptr_t)pvlogLinkHandle; hciACLHeader.logLinkHandle = value; #ifdef BAP_DEBUG 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_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h index a3ffb79c0d78..b030c4bc3eb8 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/CORE/HDD/inc/wlan_hdd_cfg.h @@ -2675,6 +2675,7 @@ typedef struct Function declarations and documenation -------------------------------------------------------------------------*/ VOS_STATUS hdd_parse_config_ini(hdd_context_t *pHddCtx); +VOS_STATUS hdd_update_mac_config(hdd_context_t *pHddCtx); VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ); VOS_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx); v_BOOL_t hdd_update_config_dat ( hdd_context_t *pHddCtx ); 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 5883fa0ad236..0f741496f550 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -641,6 +641,9 @@ struct hdd_station_ctx /*Increment whenever ibss New peer joins and departs the network */ int ibss_sta_generation; + /* Indication of wep/wpa-none keys installation */ + v_BOOL_t ibss_enc_key_installed; + /*Save the wep/wpa-none keys*/ tCsrRoamSetKey ibss_enc_key; v_BOOL_t hdd_ReassocScenario; @@ -1023,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) @@ -1376,4 +1382,45 @@ void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx); #endif int hdd_wmmps_helper(hdd_adapter_t *pAdapter, tANI_U8 *ptr); + +#ifdef FEATURE_WLAN_BATCH_SCAN +/**--------------------------------------------------------------------------- + + \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING + IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled: + WLS_BATCHING VERSION + WLS_BATCHING SET + WLS_BATCHING GET + WLS_BATCHING STOP + + \param - pAdapter Pointer to HDD adapter + \param - pPrivdata Pointer to priv_data + \param - command Pointer to command + + \return - 0 for success -EFAULT for failure + + --------------------------------------------------------------------------*/ + +int hdd_handle_batch_scan_ioctl +( + hdd_adapter_t *pAdapter, + hdd_priv_data_t *pPrivdata, + tANI_U8 *command +); + +/**--------------------------------------------------------------------------- + + \brief hdd_deinit_batch_scan () - This function cleans up batch scan data + structures + + \param - pAdapter Pointer to HDD adapter + + \return - None + + --------------------------------------------------------------------------*/ + +void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter); + +#endif /*End of FEATURE_WLAN_BATCH_SCAN*/ + #endif // end #if !defined( WLAN_HDD_MAIN_H ) 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_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c index 229efded8ef8..4d71b707cb41 100644 --- a/CORE/HDD/src/wlan_hdd_cfg.c +++ b/CORE/HDD/src/wlan_hdd_cfg.c @@ -3633,6 +3633,116 @@ static int parseHexDigit(char c) return 0; } +/* convert string to 6 bytes mac address + * 00AA00BB00CC -> 0x00 0xAA 0x00 0xBB 0x00 0xCC + */ +static void update_mac_from_string(hdd_context_t *pHddCtx, tCfgIniEntry *macTable, int num) +{ + int i = 0, j = 0, res = 0; + char *candidate = NULL; + v_MACADDR_t macaddr[VOS_MAX_CONCURRENCY_PERSONA]; + + memset(macaddr, 0, sizeof(macaddr)); + + for (i = 0; i < num; i++) + { + candidate = macTable[i].value; + for (j = 0; j < VOS_MAC_ADDR_SIZE; j++) { + res = hex2bin(&macaddr[i].bytes[j], &candidate[(j<<1)], 1); + if (res < 0) + break; + } + if (res == 0 && !vos_is_macaddr_zero(&macaddr[i])) { + vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], + (v_U8_t *)&macaddr[i].bytes[0], VOS_MAC_ADDR_SIZE); + } + } +} + +/* + * This function tries to update macaddress from cfg file. + * It overwrites the MAC address if config file exist. + */ +VOS_STATUS hdd_update_mac_config(hdd_context_t *pHddCtx) +{ + int status, i = 0; + const struct firmware *fw = NULL; + char *line, *buffer = NULL; + char *name, *value; + tCfgIniEntry macTable[VOS_MAX_CONCURRENCY_PERSONA]; + + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + + memset(macTable, 0, sizeof(macTable)); + status = request_firmware(&fw, WLAN_MAC_FILE, pHddCtx->parent_dev); + + if (status) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: request_firmware failed %d\n", + __func__, status); + vos_status = VOS_STATUS_E_FAILURE; + goto config_exit; + } + if (!fw || !fw->data || !fw->size) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: invalid firmware\n", __func__); + vos_status = VOS_STATUS_E_INVAL; + goto config_exit; + } + + buffer = (char *)fw->data; + + /* data format: + * Intf0MacAddress=00AA00BB00CC + * Intf1MacAddress=00AA00BB00CD + * END + */ + while (buffer != NULL) + { + line = get_next_line(buffer); + buffer = i_trim(buffer); + + if (strlen((char *)buffer) == 0 || *buffer == '#') { + buffer = line; + continue; + } + if (strncmp(buffer, "END", 3) == 0) + break; + + name = buffer; + buffer = strchr(buffer, '='); + if (buffer) { + *buffer++ = '\0'; + i_trim(name); + if (strlen(name) != 0) { + buffer = i_trim(buffer); + if (strlen(buffer) == 12) { + value = buffer; + macTable[i].name = name; + macTable[i++].value = value; + if (i >= VOS_MAX_CONCURRENCY_PERSONA) + break; + } + } + } + buffer = line; + } + if (i <= VOS_MAX_CONCURRENCY_PERSONA) { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: %d Mac addresses provided\n", __func__, i); + } + else { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: invalid number of Mac address provided, nMac = %d\n", + __func__, i); + vos_status = VOS_STATUS_E_INVAL; + goto config_exit; + } + + update_mac_from_string(pHddCtx, &macTable[0], i); + +config_exit: + release_firmware(fw); + return vos_status; +} static VOS_STATUS hdd_apply_cfg_ini( hdd_context_t *pHddCtx, tCfgIniEntry* iniTable, unsigned long entries) { diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 3e295220689d..216bec3d2d25 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -3781,6 +3781,13 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, } if ((WLAN_HDD_IBSS == pAdapter->device_mode) && !pairwise) { + /* if a key is already installed, block all subsequent ones */ + if (pAdapter->sessionCtx.station.ibss_enc_key_installed) { + hddLog(VOS_TRACE_LEVEL_INFO_MED, + "%s: IBSS key installed already", __func__); + return 0; + } + setKey.keyDirection = eSIR_TX_RX; /*Set the group key*/ status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), @@ -3796,6 +3803,10 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, the PTK after peer joins the IBSS network*/ vos_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key, &setKey, sizeof(tCsrRoamSetKey)); + +#if defined (QCA_WIFI_2_0) && !defined (QCA_WIFI_ISOC) + pAdapter->sessionCtx.station.ibss_enc_key_installed = 1; +#endif return status; } if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) || @@ -6704,6 +6715,7 @@ static int wlan_hdd_cfg80211_set_privacy_ibss( pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED; vos_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey)); + pHddStaCtx->ibss_enc_key_installed = 0; if (params->ie_len && ( NULL != params->ie) ) { diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c index 1037154ac026..3518e8f62882 100644 --- a/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/CORE/HDD/src/wlan_hdd_hostapd.c @@ -271,6 +271,12 @@ int hdd_hostapd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { hdd_setP2pOpps(dev, command); } +#ifdef FEATURE_WLAN_BATCH_SCAN + else if( strncmp(command, "WLS_BATCHING", 12) == 0 ) + { + ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command); + } +#endif /* command should be a string having format @@ -283,6 +289,7 @@ int hdd_hostapd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ret = sapSetPreferredChannel(command); } + } exit: if (command) @@ -504,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) @@ -589,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 77a7b818f86a..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; } @@ -386,17 +421,15 @@ static void hdd_ipa_destory_rm_resource(struct hdd_ipa_priv *hdd_ipa) if (!hdd_ipa_is_rm_enabled(hdd_ipa)) return; - ipa_rm_delete_dependency(IPA_RM_RESOURCE_WLAN_PROD, - IPA_RM_RESOURCE_A2_CONS); #ifdef HDD_IPA_USE_IPA_RM_TIMER ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_WLAN_PROD); #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, @@ -404,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, @@ -480,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++; @@ -503,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++; @@ -519,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++; @@ -530,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) { @@ -588,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); @@ -614,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; @@ -682,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++; @@ -701,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); @@ -742,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++; @@ -783,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) { @@ -806,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, @@ -858,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; @@ -952,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) { @@ -989,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; @@ -1002,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; @@ -1022,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)); @@ -1086,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++; } @@ -1113,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), @@ -1320,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: @@ -1390,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; @@ -1426,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, @@ -1575,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", @@ -1589,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. @@ -1601,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; @@ -1624,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; @@ -1634,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; } @@ -1655,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 @@ -1666,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/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index c744b22fc977..7beee7f9d478 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -677,6 +677,7 @@ void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code) } + #ifdef FEATURE_WLAN_BATCH_SCAN /**--------------------------------------------------------------------------- @@ -733,7 +734,6 @@ hdd_extract_assigned_int_from_str { return NULL; } - if (tempInt < 0) { tempInt = 0; @@ -1142,6 +1142,7 @@ static void hdd_batch_scan_result_ind_callback { v_BOOL_t isLastAp; tANI_U32 numApMetaInfo; + tANI_U32 numNetworkInScanList; tANI_U32 numberScanList; tANI_U32 nextScanListOffset; tANI_U32 nextApMetaInfoOffset; @@ -1166,6 +1167,7 @@ static void hdd_batch_scan_result_ind_callback pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp; isLastAp = FALSE; numApMetaInfo = 0; + numNetworkInScanList = 0; numberScanList = 0; nextScanListOffset = 0; nextApMetaInfoOffset = 0; @@ -1195,7 +1197,7 @@ static void hdd_batch_scan_result_ind_callback while (numberScanList) { - pScanList = (tpSirBatchScanList)(pBatchScanRsp->scanResults + + pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults + nextScanListOffset); if (NULL == pScanList) { @@ -1204,9 +1206,10 @@ static void hdd_batch_scan_result_ind_callback isLastAp = TRUE; goto done; } - numApMetaInfo = pScanList->numNetworksInScanList; + numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList; VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Batch scan rsp: numApMetaInfo %d", numApMetaInfo); + "Batch scan rsp: numApMetaInfo %d scanId %d", + numApMetaInfo, pScanList->scanId); if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork)) { @@ -1216,6 +1219,9 @@ static void hdd_batch_scan_result_ind_callback goto done; } + /*Initialize next AP meta info offset for next scan list*/ + nextApMetaInfoOffset = 0; + while (numApMetaInfo) { pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList + @@ -1232,13 +1238,11 @@ static void hdd_batch_scan_result_ind_callback pBatchScanRsp->timestamp - pApMetaInfo->timestamp; VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: bssId 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x " - "ch %d rssi %d timestamp %d", __func__, - pApMetaInfo->bssid[0],pApMetaInfo->bssid[1], - pApMetaInfo->bssid[2],pApMetaInfo->bssid[3], - pApMetaInfo->bssid[4],pApMetaInfo->bssid[5], - pApMetaInfo->ch, pApMetaInfo->rssi, - pApMetaInfo->timestamp); + "%s: bssId "MAC_ADDRESS_STR + " ch %d rssi %d timestamp %d", __func__, + MAC_ADDR_ARRAY(pApMetaInfo->bssid), + pApMetaInfo->ch, pApMetaInfo->rssi, + pApMetaInfo->timestamp); /*mark last AP in batch scan response*/ if ((TRUE == pBatchScanRsp->isLastResult) && @@ -1257,7 +1261,9 @@ static void hdd_batch_scan_result_ind_callback numApMetaInfo--; } - nextScanListOffset += (sizeof(tSirBatchScanList) - (sizeof(tANI_U8))); + nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8)) + + (sizeof(tSirBatchScanNetworkInfo) + * numNetworkInScanList)); numberScanList--; } @@ -1490,6 +1496,7 @@ tANI_U32 hdd_populate_user_batch_scan_rsp pAdapter->prev_batch_id = pPrev->ApInfo.batchId; } vos_mem_free(pPrev); + pPrev = NULL; } return cur_len; @@ -1572,11 +1579,11 @@ int hdd_return_batch_scan_rsp_to_user rc = wait_for_completion_timeout( &pAdapter->hdd_get_batch_scan_req_var, msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT)); - if (0 == rc) + if (0 >= rc) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Timeout waiting to fetch batch scan rsp from fw", - __func__); + "%s: wait on hdd_get_batch_scan_req_var failed %ld", + __func__, rc); return -EFAULT; } } @@ -1643,6 +1650,242 @@ int hdd_return_batch_scan_rsp_to_user return 0; } /*End of hdd_return_batch_scan_rsp_to_user*/ +/**--------------------------------------------------------------------------- + + \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING + IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled: + WLS_BATCHING VERSION + WLS_BATCHING SET + WLS_BATCHING GET + WLS_BATCHING STOP + + \param - pAdapter Pointer to HDD adapter + \param - pPrivdata Pointer to priv_data + \param - command Pointer to command + + \return - 0 for success -EFAULT for failure + + --------------------------------------------------------------------------*/ + +int hdd_handle_batch_scan_ioctl +( + hdd_adapter_t *pAdapter, + hdd_priv_data_t *pPrivdata, + tANI_U8 *command +) +{ + int ret = 0; + + if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0) + { + char extra[32]; + tANI_U8 len = 0; + tANI_U8 version = HDD_BATCH_SCAN_VERSION; + + if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Batch scan feature is not supported by FW", __func__); + ret = -EINVAL; + goto exit; + } + + len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d", + version); + if (copy_to_user(pPrivdata->buf, &extra, len + 1)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + ret = HDD_BATCH_SCAN_VERSION; + } + else if (strncmp(command, "WLS_BATCHING SET", 16) == 0) + { + int status; + tANI_U8 *value = (command + 16); + eHalStatus halStatus; + unsigned long rc; + tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq; + tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp; + + if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Batch scan feature is not supported by FW", __func__); + ret = -EINVAL; + goto exit; + } + + if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) && + (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) && + (WLAN_HDD_P2P_GO != pAdapter->device_mode) && + (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Received WLS_BATCHING SET command in invalid mode %d " + "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode", + pAdapter->device_mode); + ret = -EINVAL; + goto exit; + } + + status = hdd_parse_set_batchscan_command(value, pReq); + if (status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid WLS_BATCHING SET command"); + ret = -EINVAL; + goto exit; + } + + + pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE; + halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq, + pAdapter->sessionId, hdd_set_batch_scan_req_callback, + pAdapter); + + if ( eHAL_STATUS_SUCCESS == halStatus ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "sme_SetBatchScanReq returned success halStatus %d", + halStatus); + if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp) + { + INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var); + rc = wait_for_completion_timeout( + &pAdapter->hdd_set_batch_scan_req_var, + msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT)); + if (0 == rc) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Timeout waiting for set batch scan to complete", + __func__); + ret = -EINVAL; + goto exit; + } + } + if ( !pRsp->nScansToBatch ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Received set batch scan failure response from FW", + __func__); + ret = -EINVAL; + goto exit; + } + /*As per the Batch Scan Framework API we should return the MIN of + either MSCAN or the max # of scans firmware can cache*/ + ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch); + + pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: request MSCAN %d response MSCAN %d ret %d", + __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret); + } + else + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "sme_SetBatchScanReq returned failure halStatus %d", + halStatus); + ret = -EINVAL; + goto exit; + } + } + else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0) + { + eHalStatus halStatus; + tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd; + pInd->param = 0; + + if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Batch scan feature is not supported by FW", __func__); + ret = -EINVAL; + goto exit; + } + + if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Batch scan is not yet enabled batch scan state %d", + pAdapter->batchScanState); + ret = -EINVAL; + goto exit; + } + + mutex_lock(&pAdapter->hdd_batch_scan_lock); + hdd_deinit_batch_scan(pAdapter); + mutex_unlock(&pAdapter->hdd_batch_scan_lock); + + pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED; + + halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd, + pAdapter->sessionId); + if ( eHAL_STATUS_SUCCESS == halStatus ) + { + ret = 0; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "sme_StopBatchScanInd returned success halStatus %d", + halStatus); + } + else + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "sme_StopBatchScanInd returned failure halStatus %d", + halStatus); + ret = -EINVAL; + goto exit; + } + } + else if (strncmp(command, "WLS_BATCHING GET", 16) == 0) + { + tANI_U32 remain_len; + + if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Batch scan feature is not supported by FW", __func__); + ret = -EINVAL; + goto exit; + } + + if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Batch scan is not yet enabled could not return results" + "Batch Scan state %d", + pAdapter->batchScanState); + ret = -EINVAL; + goto exit; + } + + pPrivdata->used_len = 16; + remain_len = pPrivdata->total_len - pPrivdata->used_len; + if (remain_len < pPrivdata->total_len) + { + /*Clear previous batch scan response data if any*/ + vos_mem_zero((tANI_U8 *)(command + pPrivdata->used_len), remain_len); + } + else + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid total length from user space can't fetch batch" + " scan response total_len %d used_len %d remain len %d", + pPrivdata->total_len, pPrivdata->used_len, remain_len); + ret = -EINVAL; + goto exit; + } + ret = hdd_return_batch_scan_rsp_to_user(pAdapter, pPrivdata, command); + } + +exit: + + return ret; +} + #endif/*End of FEATURE_WLAN_BATCH_SCAN*/ /**--------------------------------------------------------------------------- @@ -3801,218 +4044,14 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) status = sme_SendRateUpdateInd((tHalHandle)(pHddCtx->hHal), rateUpdateParams); } -#ifdef FEATURE_WLAN_BATCH_SCAN - else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0) - { - char extra[32]; - tANI_U8 len = 0; - tANI_U8 version = HDD_BATCH_SCAN_VERSION; - - if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN)) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Batch scan feature is not supported by FW", __func__); - ret = -EINVAL; - goto exit; - } - if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) && - (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) && - (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode)) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Received WLS_BATCHING_VERSION command in invalid mode %d " - "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client" - " mode", - pAdapter->device_mode); - ret = -EINVAL; - goto exit; - } - - len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d", - version); - if (copy_to_user(priv_data.buf, &extra, len + 1)) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: failed to copy data to user buffer", __func__); - ret = -EFAULT; - goto exit; - } - ret = HDD_BATCH_SCAN_VERSION; - } - else if (strncmp(command, "WLS_BATCHING SET", 16) == 0) - { - int status; - tANI_U8 *value = (command + 16); - eHalStatus halStatus; - unsigned long rc; - tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq; - tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp; - - if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN)) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Batch scan feature is not supported by FW", __func__); - ret = -EINVAL; - goto exit; - } - - if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) && - (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) && - (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode)) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Received WLS_BATCHING SET command in invalid mode %d " - "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode", - pAdapter->device_mode); - ret = -EINVAL; - goto exit; - } - - status = hdd_parse_set_batchscan_command(value, pReq); - if (status) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Invalid WLS_BATCHING SET command"); - ret = -EINVAL; - goto exit; - } - pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE; - halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq, - pAdapter->sessionId, hdd_set_batch_scan_req_callback, - pAdapter); - - if ( eHAL_STATUS_SUCCESS == halStatus ) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "sme_SetBatchScanReq returned success halStatus %d", - halStatus); - if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp) - { - INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var); - rc = wait_for_completion_timeout( - &pAdapter->hdd_set_batch_scan_req_var, - msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT)); - if (0 == rc) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Timeout waiting for set batch scan to complete", - __func__); - ret = -EINVAL; - goto exit; - } - } - if ( !pRsp->nScansToBatch ) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Received set batch scan failure response from FW", - __func__); - ret = -EINVAL; - goto exit; - } - /*As per the Batch Scan Framework API we should return the MIN of - either MSCAN or the max # of scans firmware can cache*/ - ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch); - - pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED; - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: request MSCAN %d response MSCAN %d ret %d", - __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret); - } - else - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "sme_SetBatchScanReq returned failure halStatus %d", - halStatus); - ret = -EINVAL; - goto exit; - } - } - else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0) - { - eHalStatus halStatus; - tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd; - pInd->param = 0; - - if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN)) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Batch scan feature is not supported by FW", __func__); - ret = -EINVAL; - goto exit; - } - - if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Batch scan is not yet enabled batch scan state %d", - pAdapter->batchScanState); - ret = -EINVAL; - goto exit; - } - - pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED; - - halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd, - pAdapter->sessionId); - if ( eHAL_STATUS_SUCCESS == halStatus ) - { - ret = 0; - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "sme_StopBatchScanInd returned success halStatus %d", - halStatus); - } - else - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "sme_StopBatchScanInd returned failure halStatus %d", - halStatus); - ret = -EINVAL; - goto exit; - } - } - else if (strncmp(command, "WLS_BATCHING GET", 16) == 0) +#ifdef FEATURE_WLAN_BATCH_SCAN + else if (strncmp(command, "WLS_BATCHING", 12) == 0) { - tANI_U32 remain_len; - - if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN)) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Batch scan feature is not supported by FW", __func__); - ret = -EINVAL; - goto exit; - } - - if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Batch scan is not yet enabled could not return results" - "Batch Scan state %d", - pAdapter->batchScanState); - ret = -EINVAL; - goto exit; - } - - priv_data.used_len = 16; - remain_len = priv_data.total_len - priv_data.used_len; - if (remain_len < priv_data.total_len) - { - /*Clear previous batch scan response data if any*/ - vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len); - } - else - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Invalid total length from user space can't fetch batch" - " scan response total_len %d used_len %d remain len %d", - priv_data.total_len, priv_data.used_len, remain_len); - ret = -EINVAL; - goto exit; - } - ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command); + ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command); } #endif + #if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD) else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0) { @@ -6690,11 +6729,6 @@ void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_ { struct net_device *pWlanDev = NULL; -#ifdef FEATURE_WLAN_BATCH_SCAN - tHddBatchScanRsp *pNode; - tHddBatchScanRsp *pPrev; -#endif - if (pAdapter) pWlanDev = pAdapter->dev; else { @@ -6704,14 +6738,20 @@ void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_ } #ifdef FEATURE_WLAN_BATCH_SCAN - pNode = pAdapter->pBatchScanRsp; - while (pNode) + if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) + || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) + || (pAdapter->device_mode == WLAN_HDD_P2P_GO) + || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE) + ) + { + if (pAdapter) { - pPrev = pNode; - pNode = pNode->pNext; - vos_mem_free((v_VOID_t * )pPrev); + if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState) + { + hdd_deinit_batch_scan(pAdapter); + } } - pAdapter->pBatchScanRsp = NULL; + } #endif if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) { @@ -7473,6 +7513,44 @@ VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx ) return VOS_STATUS_SUCCESS; } +#ifdef FEATURE_WLAN_BATCH_SCAN +/**--------------------------------------------------------------------------- + + \brief hdd_deinit_batch_scan () - This function cleans up batch scan data + structures + + \param - pAdapter Pointer to HDD adapter + + \return - None + + --------------------------------------------------------------------------*/ +void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter) +{ + tHddBatchScanRsp *pNode; + tHddBatchScanRsp *pPrev; + + if (pAdapter) + { + pNode = pAdapter->pBatchScanRsp; + while (pNode) + { + pPrev = pNode; + pNode = pNode->pNext; + vos_mem_free((v_VOID_t * )pPrev); + } + pAdapter->pBatchScanRsp = NULL; + } + + pAdapter->pBatchScanRsp = NULL; + pAdapter->numScanList = 0; + pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED; + pAdapter->prev_batch_id = 0; + + return; +} +#endif + + VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx ) { hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; @@ -7498,6 +7576,13 @@ VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx ) clear_bit(WMM_INIT_DONE, &pAdapter->event_flags); } +#ifdef FEATURE_WLAN_BATCH_SCAN + if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState) + { + hdd_deinit_batch_scan(pAdapter); + } +#endif + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); pAdapterNode = pNext; } @@ -7701,6 +7786,8 @@ void hdd_dump_concurrency_info(hdd_context_t *pHddCtx) memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid)); } break; + case WLAN_HDD_IBSS: + return; /* skip printing station message below */ default: break; } @@ -9021,8 +9108,15 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc) goto err_config; } - pHddCtx->current_intf_count=0; - pHddCtx->max_intf_count = WLAN_MAX_INTERFACES; + if ( VOS_STATUS_SUCCESS != hdd_update_mac_config( pHddCtx ) ) + { + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: can't update mac config, using MAC from ini file", + __func__); + } + + pHddCtx->current_intf_count=0; + pHddCtx->max_intf_count = WLAN_MAX_INTERFACES; #ifndef QCA_WIFI_2_0 pHddCtx->cfg_ini->maxWoWFilters = WOWL_MAX_PTRNS_ALLOWED; diff --git a/CORE/MAC/inc/qwlan_version.h b/CORE/MAC/inc/qwlan_version.h index cdf522fde2e2..275ed7c67ac8 100644 --- a/CORE/MAC/inc/qwlan_version.h +++ b/CORE/MAC/inc/qwlan_version.h @@ -42,9 +42,9 @@ BRIEF DESCRIPTION: #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 30 +#define QWLAN_VERSION_BUILD 31 -#define QWLAN_VERSIONSTR "1.0.0.30" +#define QWLAN_VERSIONSTR "1.0.0.31" #ifdef QCA_WIFI_2_0 diff --git a/CORE/SERVICES/BMI/ol_fw.c b/CORE/SERVICES/BMI/ol_fw.c index 29e55d563dc5..515bdc81a3bf 100644 --- a/CORE/SERVICES/BMI/ol_fw.c +++ b/CORE/SERVICES/BMI/ol_fw.c @@ -492,7 +492,7 @@ u_int32_t host_interest_item_address(u_int32_t target_type, u_int32_t item_offse } #if defined(QCA_WIFI_2_0) && !defined(QCA_WIFI_ISOC) -void dump_CE_register(struct ol_softc *scn) +int dump_CE_register(struct ol_softc *scn) { A_UINT32 CE_reg_address = CE7_LOCATION; A_UINT32 CE_reg_values[CE_USEFUL_SIZE>>2]; @@ -504,13 +504,14 @@ void dump_CE_register(struct ol_softc *scn) CE_reg_word_size * sizeof(A_UINT32)) != A_OK) { printk(KERN_ERR "Dumping CE register failed!\n"); - return; + return -EACCES; } printk("CE7 Register Dump:\n"); for (i = 0; i < CE_reg_word_size; i++) { printk("[%02d] : 0x%08X\n", i, CE_reg_values[i]); } + return EOK; } #endif @@ -522,15 +523,21 @@ static void ramdump_work_handler(struct work_struct *ramdump) void __iomem *ramdump_base; unsigned long address; unsigned long size; + int ret; u_int32_t host_interest_address; if (!ramdump_scn) { printk("No RAM dump will be collected since ramdump_scn is NULL!\n"); - goto out; + goto out_fail; } - hif_pci_check_soc_status(ramdump_scn->hif_sc); - dump_CE_register(ramdump_scn); + ret = hif_pci_check_soc_status(ramdump_scn->hif_sc); + if (ret) + goto out_fail; + + ret = dump_CE_register(ramdump_scn); + if (ret) + goto out_fail; if (HIFDiagReadMem(ramdump_scn->hif_hdl, host_interest_item_address(ramdump_scn->target_type, @@ -539,7 +546,7 @@ static void ramdump_work_handler(struct work_struct *ramdump) printk(KERN_ERR "HifDiagReadiMem FW Dump Area Pointer failed!\n"); dump_CE_register(ramdump_scn); - goto out; + goto out_fail; } printk("Host interest item address: 0x%08X\n", host_interest_address); @@ -547,25 +554,30 @@ static void ramdump_work_handler(struct work_struct *ramdump) if (cnss_get_ramdump_mem(&address, &size)) { printk("No RAM dump will be collected since failed to get " "memory address or size!\n"); - goto out; + goto out_fail; } ramdump_base = ioremap(address, size); if (!ramdump_base) { printk("No RAM dump will be collected since ramdump_base is NULL!\n"); - goto out; + goto out_fail; } - ol_target_coredump(ramdump_scn, ramdump_base, TOTAL_DUMP_SIZE); + ret = ol_target_coredump(ramdump_scn, ramdump_base, TOTAL_DUMP_SIZE); iounmap(ramdump_base); + if (ret) + goto out_fail; printk("%s: RAM dump collecting completed!\n", __func__); msleep(250); - -out: /* Notify SSR framework the target has crashed. */ cnss_device_crashed(); return; + +out_fail: + /* silent SSR on dump failure */ + cnss_device_self_recovery(); + return; } static DECLARE_WORK(ramdump_work, ramdump_work_handler); @@ -1003,11 +1015,12 @@ int ol_diag_read(struct ol_softc *scn, u_int8_t *buffer, * * \return: None * --------------------------------------------------------------------------*/ -void ol_target_coredump(void *inst, void *memoryBlock, u_int32_t blockLength) +int ol_target_coredump(void *inst, void *memoryBlock, u_int32_t blockLength) { struct ol_softc *scn = (struct ol_softc *)inst; char *bufferLoc = memoryBlock; int result = 0; + int ret = 0; u_int32_t amountRead = 0; u_int32_t sectionCount = 0; u_int32_t pos = 0; @@ -1055,6 +1068,7 @@ void ol_target_coredump(void *inst, void *memoryBlock, u_int32_t blockLength) } else { printk(KERN_ERR "Could not read dump section!\n"); dump_CE_register(scn); + ret = -EACCES; break; /* Could not read the section */ } } else { @@ -1062,6 +1076,7 @@ void ol_target_coredump(void *inst, void *memoryBlock, u_int32_t blockLength) break; /* Insufficient room in buffer */ } } + return ret; } #endif diff --git a/CORE/SERVICES/BMI/ol_fw.h b/CORE/SERVICES/BMI/ol_fw.h index 1b5f9f296269..f15e2d3b501f 100644 --- a/CORE/SERVICES/BMI/ol_fw.h +++ b/CORE/SERVICES/BMI/ol_fw.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. * @@ -68,7 +68,7 @@ #define TOTAL_DUMP_SIZE 0x00200000 #define PCIE_READ_LIMIT 0x00005000 -void ol_target_coredump(void *instance, void* memoryBlock, +int ol_target_coredump(void *instance, void* memoryBlock, u_int32_t blockLength); int ol_diag_read(struct ol_softc *scn, u_int8_t* buffer, u_int32_t pos, size_t count); diff --git a/CORE/SERVICES/COMMON/wmi_services.h b/CORE/SERVICES/COMMON/wmi_services.h index e97d2e04a613..e8b41bd2ff6d 100644 --- a/CORE/SERVICES/COMMON/wmi_services.h +++ b/CORE/SERVICES/COMMON/wmi_services.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -97,6 +97,7 @@ typedef enum { WMI_SERVICE_MHF_OFFLOAD, /* multi-hop forwarding offload */ WMI_SERVICE_COEX_SAR, /* target support SAR tx limit from WMI_PDEV_PARAM_TXPOWER_LIMITxG */ WMI_SERVICE_BCN_TXRATE_OVERRIDE, /* Will support the bcn/prb rsp rate override */ + WMI_SERVICE_NAN, /* Neighbor Awareness Network */ WMI_MAX_SERVICE=64 /* max service */ } WMI_SERVICE; diff --git a/CORE/SERVICES/COMMON/wmi_tlv_defs.h b/CORE/SERVICES/COMMON/wmi_tlv_defs.h index 067c9ffd74e1..8ffd0582ac16 100644 --- a/CORE/SERVICES/COMMON/wmi_tlv_defs.h +++ b/CORE/SERVICES/COMMON/wmi_tlv_defs.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. * @@ -418,6 +418,8 @@ typedef enum { WMITLV_TAG_STRUC_wmi_mhf_offload_plumb_routing_table_cmd_fixed_param, WMITLV_TAG_STRUC_WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param, WMITLV_TAG_STRUC_WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param, + WMITLV_TAG_STRUC_wmi_nan_cmd_param, + WMITLV_TAG_STRUC_wmi_nan_event_hdr, WMITLV_TAG_STRUC_wmi_diag_data_container_event_fixed_param, } WMITLV_TAG_ID; @@ -568,7 +570,8 @@ typedef enum { OP(WMI_BATCH_SCAN_TRIGGER_RESULT_CMDID) \ OP(WMI_THERMAL_MGMT_CMDID) \ OP(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID) \ - OP(WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID) + OP(WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID) \ + OP(WMI_NAN_CMDID) /* * IMPORTANT: Please add _ALL_ WMI Events Here. @@ -630,6 +633,7 @@ typedef enum { OP(WMI_BATCH_SCAN_ENABLED_EVENTID) \ OP(WMI_BATCH_SCAN_RESULT_EVENTID) \ OP(WMI_THERMAL_MGMT_EVENTID) \ + OP(WMI_NAN_EVENTID) \ OP(WMI_DIAG_DATA_CONTAINER_EVENTID) /* TLV definitions of WMI commands */ @@ -1511,6 +1515,11 @@ WMITLV_CREATE_PARAM_STRUC(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID); WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param, WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) WMITLV_CREATE_PARAM_STRUC(WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID); +/* NaN Request */ +#define WMITLV_TABLE_WMI_NAN_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_nan_cmd_param, wmi_nan_cmd_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_NAN_CMDID); /************************** TLV definitions of WMI events *******************************/ @@ -1812,6 +1821,11 @@ WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_dfs_radar_event_fixed_param, wmi WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_thermal_mgmt_event_fixed_param, wmi_thermal_mgmt_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) WMITLV_CREATE_PARAM_STRUC(WMI_THERMAL_MGMT_EVENTID); +/* NAN Response/Indication Event */ +#define WMITLV_TABLE_WMI_NAN_EVENTID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_nan_event_hdr, wmi_nan_event_hdr, fixed_param, WMITLV_SIZE_FIX) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) + WMITLV_CREATE_PARAM_STRUC(WMI_NAN_EVENTID); #define WMITLV_TABLE_WMI_DIAG_DATA_CONTAINER_EVENTID(id,op,buf,len) \ WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_diag_data_container_event_fixed_param, wmi_diag_data_container_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ diff --git a/CORE/SERVICES/COMMON/wmi_unified.h b/CORE/SERVICES/COMMON/wmi_unified.h index b4e1f179539a..3d487815450f 100644 --- a/CORE/SERVICES/COMMON/wmi_unified.h +++ b/CORE/SERVICES/COMMON/wmi_unified.h @@ -170,6 +170,7 @@ typedef enum { WMI_GRP_MHF_OFL, WMI_GRP_LOCATION_SCAN, WMI_GRP_OEM, + WMI_GRP_NAN, } WMI_GRP_ID; #define WMI_CMD_GRP_START_ID(grp_id) (((grp_id) << 12) | 0x1) @@ -585,6 +586,9 @@ typedef enum { WMI_BATCH_SCAN_TRIGGER_RESULT_CMDID, /* OEM related cmd */ WMI_OEM_REQ_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_OEM), + + /** Nan Request */ + WMI_NAN_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_NAN), } WMI_CMD_ID; typedef enum { @@ -772,6 +776,9 @@ typedef enum { WMI_OEM_CAPABILITY_EVENTID=WMI_EVT_GRP_START_ID(WMI_GRP_OEM), WMI_OEM_MEASUREMENT_REPORT_EVENTID, WMI_OEM_ERROR_REPORT_EVENTID, + + /* NAN Event */ + WMI_NAN_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_NAN), } WMI_EVT_ID; /* defines for OEM message sub-types */ @@ -6306,6 +6313,26 @@ typedef struct { } wmi_thermal_mgmt_event_fixed_param; typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_nan_cmd_param */ + A_UINT32 data_len; /** length in byte of data[]. */ + /* This structure is used to send REQ binary blobs + * from application/service to firmware where Host drv is pass through . + * Following this structure is the TLV: + * A_UINT8 data[]; // length in byte given by field data_len. + */ +} wmi_nan_cmd_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_nan_event_hdr */ + A_UINT32 data_len; /** length in byte of data[]. */ + /* This structure is used to send REQ binary blobs + * from firmware to application/service where Host drv is pass through . + * Following this structure is the TLV: + * A_UINT8 data[]; // length in byte given by field data_len. + */ +} wmi_nan_event_hdr; + +typedef struct { A_UINT32 tlv_header; A_UINT32 num_data; /* followed by WMITLV_TAG_ARRAY_BYTE */ diff --git a/CORE/SERVICES/COMMON/wmi_version.h b/CORE/SERVICES/COMMON/wmi_version.h index fbc3636b9e73..55446bd96c06 100644 --- a/CORE/SERVICES/COMMON/wmi_version.h +++ b/CORE/SERVICES/COMMON/wmi_version.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 33 +#define __WMI_REVISION_ 34 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.c b/CORE/SERVICES/HIF/PCIe/if_pci.c index 4b5e32bd863d..90b4ccab0b28 100644 --- a/CORE/SERVICES/HIF/PCIe/if_pci.c +++ b/CORE/SERVICES/HIF/PCIe/if_pci.c @@ -331,8 +331,8 @@ hif_pci_device_warm_reset(struct hif_pci_softc *sc) } -void -hif_pci_check_soc_status(struct hif_pci_softc *sc) + +int hif_pci_check_soc_status(struct hif_pci_softc *sc) { u_int16_t device_id; u_int32_t val; @@ -342,7 +342,7 @@ hif_pci_check_soc_status(struct hif_pci_softc *sc) pci_read_config_word(sc->pdev, PCI_DEVICE_ID, &device_id); if(device_id != sc->devid) { printk(KERN_ERR "PCIe link is down!\n"); - return; + return -EACCES; } /* Check PCIe local register for bar/memory access */ @@ -365,7 +365,7 @@ hif_pci_check_soc_status(struct hif_pci_softc *sc) A_PCI_READ32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + RTC_STATE_ADDRESS), A_PCI_READ32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS)); - return; + return -EACCES; } A_PCI_WRITE32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + @@ -378,6 +378,7 @@ hif_pci_check_soc_status(struct hif_pci_softc *sc) /* Check BAR + 0x10c register for SoC internal bus issues */ val = A_PCI_READ32(sc->mem + 0x10c); printk("BAR + 0x10c is %08x\n", val); + return EOK; } /* diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.h b/CORE/SERVICES/HIF/PCIe/if_pci.h index ee3fb120c040..d3955f7f0e5a 100644 --- a/CORE/SERVICES/HIF/PCIe/if_pci.h +++ b/CORE/SERVICES/HIF/PCIe/if_pci.h @@ -121,7 +121,7 @@ extern int pktlogmod_init(void *context); extern void pktlogmod_exit(void *context); #endif -void hif_pci_check_soc_status(struct hif_pci_softc *sc); +int hif_pci_check_soc_status(struct hif_pci_softc *sc); /* * A firmware interrupt to the Host is indicated by the diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c index a661cdf8ef44..765254829b51 100644 --- a/CORE/SERVICES/WMA/wma.c +++ b/CORE/SERVICES/WMA/wma.c @@ -8700,11 +8700,11 @@ static void wma_set_bsskey(tp_wma_handle wma_handle, tpSetBssKeyParams key_info) ** So cache the BSS key in the wma_handle and re-use it when the STA key is been setup for a peer */ if (wlan_op_mode_ibss == txrx_vdev->opmode) { - WMA_LOGD("Caching IBSS Key"); - vos_mem_copy(&wma_handle->ibsskey_info, key_info, sizeof(tSetBssKeyParams)); key_info->status = eHAL_STATUS_SUCCESS; if (wma_handle->ibss_started > 0) goto out; + WMA_LOGD("Caching IBSS Key"); + vos_mem_copy(&wma_handle->ibsskey_info, key_info, sizeof(tSetBssKeyParams)); } adf_os_mem_set(&key_params, 0, sizeof(key_params)); @@ -15114,13 +15114,13 @@ wma_batch_scan_result_event_handler tSirBatchScanResultIndParam *pHddResult; tSirBatchScanNetworkInfo *pHddApMetaInfo; tp_wma_handle wma = (tp_wma_handle) handle; - u_int32_t nextScanListOffset, nextApMetaInfoOffset; - u_int8_t bssid[IEEE80211_ADDR_LEN], ssid[33], *ssid_temp; - u_int32_t temp, count1, count2, scan_num, netinfo_num, total_size; - WMI_BATCH_SCAN_RESULT_EVENTID_param_tlvs *param_tlvs; - wmi_batch_scan_result_event_fixed_param *fix_param; wmi_batch_scan_result_scan_list *scan_list; wmi_batch_scan_result_network_info *network_info; + wmi_batch_scan_result_event_fixed_param *fix_param; + WMI_BATCH_SCAN_RESULT_EVENTID_param_tlvs *param_tlvs; + u_int8_t bssid[IEEE80211_ADDR_LEN], ssid[33], *ssid_temp; + u_int32_t temp, count1, count2, scan_num, netinfo_num, total_size; + u_int32_t nextScanListOffset, nextApMetaInfoOffset, numNetworkInScanList; tpAniSirGlobal pMac = (tpAniSirGlobal )vos_get_context(VOS_MODULE_ID_PE, wma->vos_context); @@ -15192,12 +15192,18 @@ wma_batch_scan_result_event_handler network_info = param_tlvs->network_list; nextScanListOffset = 0; nextApMetaInfoOffset = 0; + numNetworkInScanList = 0; + for(count1 = 0; count1 < scan_num; count1++) { - pHddScanList = (tSirBatchScanList *)(pHddResult->scanResults + + pHddScanList = (tSirBatchScanList *)((tANI_U8 *)pHddResult->scanResults + nextScanListOffset); pHddScanList->scanId = scan_list->scanId; pHddScanList->numNetworksInScanList = scan_list->numNetworksInScanList; + numNetworkInScanList = pHddScanList->numNetworksInScanList; + + /*Initialize next AP meta info offset for next scan list*/ + nextApMetaInfoOffset = 0; for (count2 = 0; count2 < scan_list->numNetworksInScanList; count2++) { @@ -15242,7 +15248,9 @@ wma_batch_scan_result_event_handler network_info++; } - nextScanListOffset += (sizeof(tSirBatchScanList) - (sizeof(tANI_U8))); + nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8)) + + (sizeof(tSirBatchScanNetworkInfo) + * numNetworkInScanList)); scan_list++; } diff --git a/CORE/SERVICES/WMI/wmi_unified.c b/CORE/SERVICES/WMI/wmi_unified.c index 8d681fa4ff5e..28830972dee1 100644 --- a/CORE/SERVICES/WMI/wmi_unified.c +++ b/CORE/SERVICES/WMI/wmi_unified.c @@ -478,6 +478,8 @@ static u_int8_t* get_wmi_cmd_string(WMI_CMD_ID wmi_command) CASE_RETURN_STRING(WMI_BATCH_SCAN_TRIGGER_RESULT_CMDID); /* OEM related cmd */ CASE_RETURN_STRING(WMI_OEM_REQ_CMDID); + /* NAN request cmd */ + CASE_RETURN_STRING(WMI_NAN_CMDID); } return "Invalid WMI cmd"; } diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c index e14333b2c197..97d7a6312f27 100644 --- a/CORE/SME/src/csr/csrApiRoam.c +++ b/CORE/SME/src/csr/csrApiRoam.c @@ -5620,10 +5620,18 @@ static tANI_BOOLEAN csrRoamProcessResults( tpAniSirGlobal pMac, tSmeCmd *pComman if( CSR_IS_ENC_TYPE_STATIC( pProfile->negotiatedUCEncryptionType ) && !CSR_IS_INFRA_AP( pSession->pCurRoamProfile )) { // Issue the set Context request to LIM to establish the Broadcast STA context for the Ibss. - csrRoamIssueSetContextReq( pMac, sessionId, +#if defined (QCA_WIFI_2_0) && !defined (QCA_WIFI_ISOC) + // In Rome IBSS case, dummy key installation will break + // proper BSS key installation, so skip it. + if (!CSR_IS_IBSS( pSession->pCurRoamProfile )) +#endif + { + csrRoamIssueSetContextReq( pMac, sessionId, pProfile->negotiatedMCEncryptionType, pSirBssDesc, &BroadcastMac, FALSE, FALSE, eSIR_TX_RX, 0, 0, NULL, 0 ); // NO keys... these key parameters don't matter. + } + } } else diff --git a/CORE/VOSS/inc/wlan_hdd_misc.h b/CORE/VOSS/inc/wlan_hdd_misc.h index ec623a153be9..232161f64c5b 100644 --- a/CORE/VOSS/inc/wlan_hdd_misc.h +++ b/CORE/VOSS/inc/wlan_hdd_misc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -38,6 +38,7 @@ #define WLAN_DICT_FILE "wlan/qca_cld/WCNSS_qcom_wlan_dictionary.dat" #define WLAN_COUNTRY_INFO_FILE "wlan/qca_cld/WCNSS_wlan_country_info.dat" #define WLAN_HO_CFG_FILE "wlan/qca_cld/WCNSS_wlan_ho_config" +#define WLAN_MAC_FILE "wlan/qca_cld/wlan_mac.bin" #else #define WLAN_INI_FILE "wlan/prima/WCNSS_qcom_cfg.ini" #define WLAN_CFG_FILE "wlan/prima/WCNSS_cfg.dat" 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], @@ -1,5 +1,5 @@ -# We can build either as part of a standalone Kernel build or part -# of an Android build. Determine which mechanism is being used +# We can build either as part of a standalone Kernel build or as +# an external module. Determine which mechanism is being used ifeq ($(MODNAME),) KERNEL_BUILD := 1 else @@ -7,10 +7,11 @@ else endif ifeq ($(KERNEL_BUILD),1) - # These are provided in Android-based builds + # These are provided in external module based builds # Need to explicitly define for Kernel-based builds MODNAME := wlan - WLAN_ROOT := drivers/staging/prima + WLAN_ROOT := drivers/staging/qcacld-2.0 + WLAN_OPEN_SOURCE := 1 endif ifeq ($(KERNEL_BUILD), 0) @@ -972,11 +973,7 @@ ifeq ($(RE_ENABLE_WIFI_ON_WDI_TIMEOUT),1) CDEFINES += -DWDI_RE_ENABLE_WIFI_ON_WDI_TIMEOUT endif -ifeq ($(KERNEL_BUILD),1) -CDEFINES += -DWLAN_OPEN_SOURCE -endif - -ifeq ($(findstring opensource, $(WLAN_ROOT)), opensource) +ifeq ($(WLAN_OPEN_SOURCE), 1) CDEFINES += -DWLAN_OPEN_SOURCE endif @@ -1,13 +1,21 @@ KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build -KBUILD_OPTIONS := WLAN_ROOT=$(shell pwd) +KBUILD_OPTIONS := WLAN_ROOT=$(PWD) KBUILD_OPTIONS += MODNAME=wlan +# Determine if the driver license is Open source or proprietary +# This is determined under the assumption that LICENSE doesn't change. +# Please change here if driver license text changes. +LICENSE_FILE ?= $(PWD)/$(WLAN_ROOT)/CORE/HDD/src/wlan_hdd_main.c +WLAN_OPEN_SOURCE = $(shell if grep -q "MODULE_LICENSE(\"Dual BSD/GPL\")" \ + $(LICENSE_FILE); then echo 1; else echo 0; fi) + #By default build for CLD WLAN_SELECT := CONFIG_QCA_CLD_WLAN=m KBUILD_OPTIONS += CONFIG_QCA_WIFI_ISOC=0 KBUILD_OPTIONS += CONFIG_QCA_WIFI_2_0=1 KBUILD_OPTIONS += $(WLAN_SELECT) +KBUILD_OPTIONS += WLAN_OPEN_SOURCE=$(WLAN_OPEN_SOURCE) KBUILD_OPTIONS += $(KBUILD_EXTRA) # Extra config if any all: |
