From 68677464296ebea53b6e6b0d5c08e667b7868a37 Mon Sep 17 00:00:00 2001 From: Abhishek Ambure Date: Fri, 13 Sep 2019 12:44:26 +0530 Subject: [PATCH] qcacld-3.0: Keep IBSS code under feature flag in HDD IBSS code is placed under QCA_IBSS_SUPPORT feature flag. Change-Id: Ib3c2d24c703e19d3c25c7b89932751faac5e2874 CRs-Fixed: 2527264 --- core/hdd/inc/wlan_hdd_main.h | 22 +- core/hdd/src/wlan_hdd_assoc.c | 348 +++++---- core/hdd/src/wlan_hdd_cfg80211.c | 947 ++++++++++++----------- core/hdd/src/wlan_hdd_ioctl.c | 1224 ++++++++++++++++-------------- core/hdd/src/wlan_hdd_ioctl.h | 20 + core/hdd/src/wlan_hdd_main.c | 13 +- core/hdd/src/wlan_hdd_wext.c | 32 + 7 files changed, 1435 insertions(+), 1171 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 61d10b25a467..fcdcdfb22973 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -2221,7 +2221,26 @@ struct hdd_adapter *hdd_get_first_valid_adapter(struct hdd_context *hdd_ctx); void hdd_allow_suspend(uint32_t reason); void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason); +#ifdef QCA_IBSS_SUPPORT +/** + * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA. + * @struct hdd_adapter Hdd adapter. + * + * This function sets the IBSS power save config parameters to WMA + * which will send it to firmware if FW supports IBSS power save + * before vdev start. + * + * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE + * on failure. + */ QDF_STATUS hdd_set_ibss_power_save_params(struct hdd_adapter *adapter); +#else +static inline QDF_STATUS +hdd_set_ibss_power_save_params(struct hdd_adapter *adapter) +{ + return QDF_STATUS_SUCCESS; +} +#endif /** * wlan_hdd_validate_context() - check the HDD context @@ -2908,9 +2927,6 @@ static inline void hdd_set_tso_flags(struct hdd_context *hdd_ctx, } #endif /* FEATURE_TSO */ -void hdd_get_ibss_peer_info_cb(void *context, - tSirPeerInfoRspParams *peer_info); - #ifdef CONFIG_CNSS_LOGGER /** * wlan_hdd_nl_init() - wrapper function to CNSS_LOGGER case diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index ee1b5140efd4..322e68ebe5b0 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -2432,6 +2432,7 @@ bool hdd_is_roam_sync_in_progress(struct csr_roam_info *roaminfo) } #endif +#ifdef QCA_IBSS_SUPPORT /** * hdd_get_ibss_peer_sta_id() - get sta id for IBSS peer * @hddstactx: pointer to HDD sta context @@ -2464,6 +2465,206 @@ static uint8_t hdd_get_ibss_peer_sta_id(struct hdd_station_ctx *hddstactx, return sta_id; } +/** + * hdd_roam_ibss_indication_handler() - update the status of the IBSS + * @adapter: pointer to adapter + * @roam_info: pointer to roam info + * @roam_id: roam id + * @roam_status: roam status + * @roam_result: roam result + * + * Here we update the status of the Ibss when we receive information that we + * have started/joined an ibss session. + * + * Return: none + */ +static void hdd_roam_ibss_indication_handler(struct hdd_adapter *adapter, + struct csr_roam_info *roam_info, + uint32_t roam_id, + eRoamCmdStatus roam_status, + eCsrRoamResult roam_result) +{ + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + hdd_debug("%s: id %d, status %d, result %d", + adapter->dev->name, roam_id, + roam_status, roam_result); + + switch (roam_result) { + /* both IBSS Started and IBSS Join should come in here. */ + case eCSR_ROAM_RESULT_IBSS_STARTED: + case eCSR_ROAM_RESULT_IBSS_JOIN_SUCCESS: + case eCSR_ROAM_RESULT_IBSS_COALESCED: + { + struct hdd_station_ctx *hdd_sta_ctx = + WLAN_HDD_GET_STATION_CTX_PTR(adapter); + + if (!roam_info) { + QDF_ASSERT(0); + return; + } + + /* When IBSS Started comes from CSR, we need to move + * connection state to IBSS Disconnected (meaning no peers + * are in the IBSS). + */ + hdd_conn_set_connection_state(adapter, + eConnectionState_IbssDisconnected); + /* notify wmm */ + hdd_wmm_connect(adapter, roam_info, + eCSR_BSS_TYPE_IBSS); + + hdd_sta_ctx->broadcast_sta_id = roam_info->staId; + + hdd_roam_register_sta(adapter, roam_info, + roam_info->staId, + roam_info->bss_desc); + + if (roam_info->bss_desc) { + struct cfg80211_bss *bss; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) + struct ieee80211_channel *chan; +#endif + /* we created the IBSS, notify supplicant */ + hdd_debug("%s: created ibss " QDF_MAC_ADDR_STR, + adapter->dev->name, + QDF_MAC_ADDR_ARRAY( + roam_info->bss_desc->bssId)); + + /* we must first give cfg80211 the BSS information */ + bss = wlan_hdd_cfg80211_update_bss_db(adapter, + roam_info); + if (!bss) { + hdd_err("%s: unable to create IBSS entry", + adapter->dev->name); + return; + } + hdd_debug("Enabling queues"); + wlan_hdd_netif_queue_control(adapter, + WLAN_START_ALL_NETIF_QUEUE_N_CARRIER, + WLAN_CONTROL_PATH); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) + chan = ieee80211_get_channel( + adapter->wdev.wiphy, + roam_info->bss_desc->chan_freq); + + if (chan) + cfg80211_ibss_joined(adapter->dev, + bss->bssid, chan, + GFP_KERNEL); + else + hdd_warn("%s: freq: %d, can't find channel", + adapter->dev->name, + roam_info->bss_desc->chan_freq); +#else + cfg80211_ibss_joined(adapter->dev, bss->bssid, + GFP_KERNEL); +#endif + cfg80211_put_bss( + hdd_ctx->wiphy, + bss); + } + if (eCSR_ROAM_RESULT_IBSS_STARTED == roam_result) { + policy_mgr_incr_active_session(hdd_ctx->psoc, + adapter->device_mode, adapter->vdev_id); + hdd_green_ap_start_state_mc(hdd_ctx, + adapter->device_mode, true); + } else if (eCSR_ROAM_RESULT_IBSS_JOIN_SUCCESS == roam_result || + eCSR_ROAM_RESULT_IBSS_COALESCED == roam_result) { + policy_mgr_update_connection_info(hdd_ctx->psoc, + adapter->vdev_id); + } + break; + } + + case eCSR_ROAM_RESULT_IBSS_START_FAILED: + { + hdd_err("%s: unable to create IBSS", adapter->dev->name); + break; + } + + default: + hdd_err("%s: unexpected result %d", + adapter->dev->name, (int)roam_result); + break; + } +} + +/** + * hdd_is_key_install_required_for_ibss() - check encryption type to identify + * if key installation is required + * @encr_type: encryption type + * + * Return: true if key installation is required and false otherwise. + */ +static inline bool hdd_is_key_install_required_for_ibss( + eCsrEncryptionType encr_type) +{ + if (eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == encr_type || + eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == encr_type || + eCSR_ENCRYPT_TYPE_TKIP == encr_type || + eCSR_ENCRYPT_TYPE_AES_GCMP == encr_type || + eCSR_ENCRYPT_TYPE_AES_GCMP_256 == encr_type || + eCSR_ENCRYPT_TYPE_AES == encr_type) + return true; + else + return false; +} +#else +/** + * hdd_roam_ibss_indication_handler() - update the status of the IBSS + * @adapter: pointer to adapter + * @roam_info: pointer to roam info + * @roam_id: roam id + * @roam_status: roam status + * @roam_result: roam result + * + * This function is dummy + * + * Return: none + */ +static inline void +hdd_roam_ibss_indication_handler(struct hdd_adapter *adapter, + struct csr_roam_info *roam_info, + uint32_t roam_id, + eRoamCmdStatus roam_status, + eCsrRoamResult roam_result) +{ +} + +/** + * hdd_get_ibss_peer_sta_id() - get sta id for IBSS peer + * @hddstactx: pointer to HDD sta context + * @roaminfo: pointer to roaminfo structure + * + * This function is dummy + * + * Return: WLAN_MAX_STA_COUNT if peer not found. + */ +static inline uint8_t +hdd_get_ibss_peer_sta_id(struct hdd_station_ctx *hddstactx, + struct csr_roam_info *roaminfo) +{ + return WLAN_MAX_STA_COUNT; +} + +/** + * hdd_is_key_install_required_for_ibss() - check encryption type to identify + * if key installation is required + * @encr_type: encryption type + * + * This function is dummy + * + * Return: true. + */ +static inline bool +hdd_is_key_install_required_for_ibss(eCsrEncryptionType encr_type) +{ + return true; +} +#endif + /** * hdd_change_sta_state_authenticated()- * This function changes STA state to authenticated @@ -2517,27 +2718,6 @@ static int hdd_change_sta_state_authenticated(struct hdd_adapter *adapter, return qdf_status_to_os_return(status); } -/** - * hdd_is_key_install_required_for_ibss() - check encryption type to identify - * if key installation is required - * @encr_type: encryption type - * - * Return: true if key installation is required and false otherwise. - */ -static inline bool hdd_is_key_install_required_for_ibss( - eCsrEncryptionType encr_type) -{ - if (eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == encr_type || - eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == encr_type || - eCSR_ENCRYPT_TYPE_TKIP == encr_type || - eCSR_ENCRYPT_TYPE_AES_GCMP == encr_type || - eCSR_ENCRYPT_TYPE_AES_GCMP_256 == encr_type || - eCSR_ENCRYPT_TYPE_AES == encr_type) - return true; - else - return false; -} - /** * hdd_change_peer_state_after_set_key() - change the peer state on set key * complete @@ -3509,132 +3689,6 @@ hdd_association_completion_handler(struct hdd_adapter *adapter, return QDF_STATUS_SUCCESS; } -/** - * hdd_roam_ibss_indication_handler() - update the status of the IBSS - * @adapter: pointer to adapter - * @roam_info: pointer to roam info - * @roam_id: roam id - * @roam_status: roam status - * @roam_result: roam result - * - * Here we update the status of the Ibss when we receive information that we - * have started/joined an ibss session. - * - * Return: none - */ -static void hdd_roam_ibss_indication_handler(struct hdd_adapter *adapter, - struct csr_roam_info *roam_info, - uint32_t roam_id, - eRoamCmdStatus roam_status, - eCsrRoamResult roam_result) -{ - struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); - - hdd_debug("%s: id %d, status %d, result %d", - adapter->dev->name, roam_id, - roam_status, roam_result); - - switch (roam_result) { - /* both IBSS Started and IBSS Join should come in here. */ - case eCSR_ROAM_RESULT_IBSS_STARTED: - case eCSR_ROAM_RESULT_IBSS_JOIN_SUCCESS: - case eCSR_ROAM_RESULT_IBSS_COALESCED: - { - struct hdd_station_ctx *hdd_sta_ctx = - WLAN_HDD_GET_STATION_CTX_PTR(adapter); - - if (!roam_info) { - QDF_ASSERT(0); - return; - } - - /* When IBSS Started comes from CSR, we need to move - * connection state to IBSS Disconnected (meaning no peers - * are in the IBSS). - */ - hdd_conn_set_connection_state(adapter, - eConnectionState_IbssDisconnected); - /* notify wmm */ - hdd_wmm_connect(adapter, roam_info, - eCSR_BSS_TYPE_IBSS); - - hdd_sta_ctx->broadcast_sta_id = roam_info->staId; - - hdd_roam_register_sta(adapter, roam_info, - roam_info->staId, - roam_info->bss_desc); - - if (roam_info->bss_desc) { - struct cfg80211_bss *bss; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) - struct ieee80211_channel *chan; -#endif - /* we created the IBSS, notify supplicant */ - hdd_debug("%s: created ibss " QDF_MAC_ADDR_STR, - adapter->dev->name, - QDF_MAC_ADDR_ARRAY( - roam_info->bss_desc->bssId)); - - /* we must first give cfg80211 the BSS information */ - bss = wlan_hdd_cfg80211_update_bss_db(adapter, - roam_info); - if (!bss) { - hdd_err("%s: unable to create IBSS entry", - adapter->dev->name); - return; - } - hdd_debug("Enabling queues"); - wlan_hdd_netif_queue_control(adapter, - WLAN_START_ALL_NETIF_QUEUE_N_CARRIER, - WLAN_CONTROL_PATH); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) - chan = ieee80211_get_channel( - adapter->wdev.wiphy, - roam_info->bss_desc->chan_freq); - - if (chan) - cfg80211_ibss_joined(adapter->dev, - bss->bssid, chan, - GFP_KERNEL); - else - hdd_warn("%s: freq: %d, can't find channel", - adapter->dev->name, - roam_info->bss_desc->chan_freq); -#else - cfg80211_ibss_joined(adapter->dev, bss->bssid, - GFP_KERNEL); -#endif - cfg80211_put_bss( - hdd_ctx->wiphy, - bss); - } - if (eCSR_ROAM_RESULT_IBSS_STARTED == roam_result) { - policy_mgr_incr_active_session(hdd_ctx->psoc, - adapter->device_mode, adapter->vdev_id); - hdd_green_ap_start_state_mc(hdd_ctx, - adapter->device_mode, true); - } else if (eCSR_ROAM_RESULT_IBSS_JOIN_SUCCESS == roam_result || - eCSR_ROAM_RESULT_IBSS_COALESCED == roam_result) { - policy_mgr_update_connection_info(hdd_ctx->psoc, - adapter->vdev_id); - } - break; - } - - case eCSR_ROAM_RESULT_IBSS_START_FAILED: - { - hdd_err("%s: unable to create IBSS", adapter->dev->name); - break; - } - - default: - hdd_err("%s: unexpected result %d", - adapter->dev->name, (int)roam_result); - break; - } -} - /** * hdd_save_peer() - Save peer MAC address in adapter peer table. * @sta_ctx: pointer to hdd station context diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index ae2f2f3e8b44..443db48f81dd 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -15347,6 +15347,20 @@ static bool hdd_is_btk_enc_type(uint32_t cipher_type) #endif #ifdef CRYPTO_SET_KEY_CONVERGED +#ifdef QCA_IBSS_SUPPORT +/** + * wlan_hdd_add_key_ibss() - API to add IBSS key + * @adapter: Pointer to adapter + * @pairwise: need to add key pairwise + * @key_index: key index + * @mac_addr: Pointer to mac_addr + * @params: Pointer to key params + * @key_already_installed: pointer to key already installed state + * + * This API will add IBSS key for given mac address. + * + * Return: 0 for success, error number on failure. + */ static int wlan_hdd_add_key_ibss(struct hdd_adapter *adapter, bool pairwise, u8 key_index, const u8 *mac_addr, struct key_params *params, @@ -15384,6 +15398,29 @@ static int wlan_hdd_add_key_ibss(struct hdd_adapter *adapter, return 0; } +#else +/** + * wlan_hdd_add_key_ibss() - API to add IBSS key + * @adapter: Pointer to adapter + * @pairwise: need to add key pairwise + * @key_index: key index + * @mac_addr: Pointer to mac_addr + * @params: Pointer to key params + * @key_already_installed: pointer to key already installed state + * + * This function is dummy + * + * Return: 0 + */ +static inline int +wlan_hdd_add_key_ibss(struct hdd_adapter *adapter, + bool pairwise, u8 key_index, + const u8 *mac_addr, struct key_params *params, + bool *key_already_installed) +{ + return 0; +} +#endif static int wlan_hdd_add_key_sap(struct hdd_adapter *adapter, bool pairwise, u8 key_index, @@ -18526,6 +18563,7 @@ static int wlan_hdd_cfg80211_set_ie(struct hdd_adapter *adapter, return 0; } +#ifdef QCA_IBSS_SUPPORT /** * hdd_is_wpaie_present() - check for WPA ie * @ie: Pointer to ie @@ -18563,6 +18601,478 @@ static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len) return false; } +/** + * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy + * @adapter: Pointer to adapter + * @param: Pointer to IBSS parameters + * + * This function is used to initialize the security settings in IBSS mode + * + * Return: 0 for success, non-zero for failure + */ +static int wlan_hdd_cfg80211_set_privacy_ibss(struct hdd_adapter *adapter, + struct cfg80211_ibss_params + *params) +{ + uint32_t ret; + int status = 0; + eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE; + struct hdd_station_ctx *sta_ctx = + WLAN_HDD_GET_STATION_CTX_PTR(adapter); + struct csr_roam_profile *roam_profile; + + hdd_enter(); + + sta_ctx->wpa_versions = 0; + qdf_mem_zero(&sta_ctx->ibss_enc_key, sizeof(tCsrRoamSetKey)); + sta_ctx->ibss_enc_key_installed = 0; + + if (params->ie_len && (params->ie)) { + if (wlan_get_ie_ptr_from_eid(WLAN_EID_RSN, params->ie, + params->ie_len)) { + sta_ctx->wpa_versions = NL80211_WPA_VERSION_2; + encryptionType = eCSR_ENCRYPT_TYPE_AES; + } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) { + tDot11fIEWPA dot11_wpa_ie; + mac_handle_t mac_handle = + hdd_adapter_get_mac_handle(adapter); + const u8 *ie; + + memset(&dot11_wpa_ie, 0, sizeof(dot11_wpa_ie)); + ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_WPA, + params->ie, params->ie_len); + if (ie) { + sta_ctx->wpa_versions = NL80211_WPA_VERSION_1; + /* Unpack the WPA IE + * Skip past the EID byte and length byte + * and four byte WiFi OUI + */ + if (ie[1] < DOT11F_IE_WPA_MIN_LEN || + ie[1] > DOT11F_IE_WPA_MAX_LEN) { + hdd_err("invalid ie len:%d", ie[1]); + return -EINVAL; + } + ret = dot11f_unpack_ie_wpa( + MAC_CONTEXT(mac_handle), + (uint8_t *)&ie[2 + 4], + ie[1] - 4, &dot11_wpa_ie, false); + if (DOT11F_FAILED(ret)) { + hdd_err("unpack failed ret: 0x%x", ret); + return -EINVAL; + } + /* + * Extract the multicast cipher, the + * encType for unicast cipher for + * wpa-none is none + */ + encryptionType = + hdd_translate_wpa_to_csr_encryption_type + (dot11_wpa_ie.multicast_cipher); + } + } + + status = + wlan_hdd_cfg80211_set_ie(adapter, params->ie, + params->ie_len); + + if (0 > status) { + hdd_err("Failed to parse WPA/RSN IE"); + return status; + } + } + + roam_profile = hdd_roam_profile(adapter); + roam_profile->AuthType.authType[0] = + sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_OPEN_SYSTEM; + + if (params->privacy) { + /* Security enabled IBSS, At this time there is no information + * available about the security parameters, so initialise the + * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY. + * The correct security parameters will be updated later in + * wlan_hdd_cfg80211_add_key Hal expects encryption type to be + * set inorder enable privacy bit in beacons + */ + + encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; + } + hdd_debug("encryptionType=%d", encryptionType); + sta_ctx->conn_info.uc_encrypt_type = encryptionType; + roam_profile->EncryptionType.numEntries = 1; + roam_profile->EncryptionType.encryptionType[0] = + encryptionType; + return status; +} + +/** + * __wlan_hdd_cfg80211_join_ibss() - join ibss + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @param: Pointer to IBSS join parameters + * + * This function is used to create/join an IBSS network + * + * Return: 0 for success, non-zero for failure + */ +static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ibss_params *params) +{ + struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + struct csr_roam_profile *roam_profile; + int status; + struct hdd_station_ctx *sta_ctx = + WLAN_HDD_GET_STATION_CTX_PTR(adapter); + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + struct qdf_mac_addr bssid; + uint8_t channelNum = 0; + mac_handle_t mac_handle; + struct wlan_mlme_ibss_cfg ibss_cfg = {0}; + uint8_t conn_info_channel; + + hdd_enter(); + + if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EINVAL; + } + + if (wlan_hdd_validate_vdev_id(adapter->vdev_id)) + return -EINVAL; + + qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_JOIN_IBSS, + adapter->vdev_id, adapter->device_mode); + + hdd_debug("Device_mode %s(%d)", + qdf_opmode_str(adapter->device_mode), adapter->device_mode); + + status = wlan_hdd_validate_context(hdd_ctx); + + if (0 != status) + return status; + + if (QDF_IS_STATUS_ERROR(ucfg_mlme_get_ibss_cfg(hdd_ctx->psoc, + &ibss_cfg))) { + return -EINVAL; + } + + mac_handle = hdd_ctx->mac_handle; + if (NULL != + params->chandef.chan) { + uint32_t numChans = CFG_VALID_CHANNEL_LIST_LEN; + uint32_t validChan[CFG_VALID_CHANNEL_LIST_LEN]; + int indx; + + /* Get channel number */ + channelNum = ieee80211_frequency_to_channel( + params-> + chandef. + chan-> + center_freq); + ucfg_mlme_get_valid_channel_freq_list(hdd_ctx->psoc, validChan, + &numChans); + + for (indx = 0; indx < numChans; indx++) { + if (channelNum == + wlan_reg_freq_to_chan(hdd_ctx->pdev, validChan[indx])) + break; + } + if (indx >= numChans) { + hdd_err("Not valid Channel: %d", channelNum); + return -EINVAL; + } + } + + /* Disable NAN Discovery if enabled */ + ucfg_nan_disable_concurrency(hdd_ctx->psoc); + + if (!policy_mgr_allow_concurrency(hdd_ctx->psoc, + PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) { + hdd_err("This concurrency combination is not allowed"); + return -ECONNREFUSED; + } + + status = policy_mgr_reset_connection_update(hdd_ctx->psoc); + if (!QDF_IS_STATUS_SUCCESS(status)) + hdd_err("qdf_reset_connection_update failed status: %d", status); + + status = policy_mgr_current_connections_update(hdd_ctx->psoc, + adapter->vdev_id, channelNum, + POLICY_MGR_UPDATE_REASON_JOIN_IBSS); + if (QDF_STATUS_E_FAILURE == status) { + hdd_err("connections update failed!!"); + return -EINVAL; + } + + if (QDF_STATUS_SUCCESS == status) { + status = policy_mgr_wait_for_connection_update( + hdd_ctx->psoc); + if (!QDF_IS_STATUS_SUCCESS(status)) { + hdd_err("qdf wait for event failed!!"); + return -EINVAL; + } + } + + /*Try disconnecting if already in connected state */ + status = wlan_hdd_try_disconnect(adapter); + if (0 > status) { + hdd_err("Failed to disconnect the existing IBSS connection"); + return -EALREADY; + } + + roam_profile = hdd_roam_profile(adapter); + + if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) { + hdd_err("Interface type is not set to IBSS"); + return -EINVAL; + } + + /* enable selected protection checks in IBSS mode */ + roam_profile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK; + + /* BSSID is provided by upper layers hence no need to AUTO generate */ + if (params->bssid) { + if (ucfg_mlme_set_ibss_auto_bssid(hdd_ctx->psoc, 0) + == QDF_STATUS_E_FAILURE) { + hdd_err("Unable to update MLME IBSS Auto BSSID config"); + return -EIO; + } + qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE); + } else if (ibss_cfg.coalesing_enable == 0) { + if (ucfg_mlme_set_ibss_auto_bssid(hdd_ctx->psoc, 0) + == QDF_STATUS_E_FAILURE) { + hdd_err("Unable to update MLME IBSS Auto BSSID config"); + return -EIO; + } + qdf_copy_macaddr(&bssid, &ibss_cfg.bssid); + } + + if (cfg_in_range(CFG_BEACON_INTERVAL, params->beacon_interval)) + roam_profile->beaconInterval = params->beacon_interval; + else + roam_profile->beaconInterval = cfg_get(hdd_ctx->psoc, + CFG_BEACON_INTERVAL); + + /* Set Channel */ + if (channelNum) { + /* Set the Operational Channel */ + hdd_debug("set channel %d", channelNum); + roam_profile->ChannelInfo.numOfChannels = 1; + sta_ctx->conn_info.chan_freq = + wlan_reg_chan_to_freq(hdd_ctx->pdev, + channelNum); + roam_profile->ChannelInfo.freq_list = + &sta_ctx->conn_info.chan_freq; + } + + /* Initialize security parameters */ + status = wlan_hdd_cfg80211_set_privacy_ibss(adapter, params); + if (status < 0) { + hdd_err("failed to set security parameters"); + return status; + } + + conn_info_channel = + wlan_reg_freq_to_chan( + hdd_ctx->pdev, + sta_ctx->conn_info.chan_freq); + /* Issue connect start */ + status = wlan_hdd_cfg80211_connect_start(adapter, params->ssid, + params->ssid_len, + bssid.bytes, NULL, + conn_info_channel, + params->chandef.width); + + if (0 > status) { + hdd_err("connect failed"); + return status; + } + hdd_exit(); + return 0; +} + +/** + * wlan_hdd_cfg80211_join_ibss() - join ibss + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @param: Pointer to IBSS join parameters + * + * This function is used to create/join an IBSS network + * + * Return: 0 for success, non-zero for failure + */ +static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ibss_params *params) +{ + int errno; + struct osif_vdev_sync *vdev_sync; + + errno = osif_vdev_sync_op_start(dev, &vdev_sync); + if (errno) + return errno; + + errno = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params); + + osif_vdev_sync_op_stop(vdev_sync); + + return errno; +} + +/** + * __wlan_hdd_cfg80211_leave_ibss() - leave ibss + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * + * This function is used to leave an IBSS network + * + * Return: 0 for success, non-zero for failure + */ +static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy, + struct net_device *dev) +{ + struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + struct csr_roam_profile *roam_profile; + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + int status; + mac_handle_t mac_handle; + unsigned long rc; + tSirUpdateIE update_ie; + + hdd_enter(); + + if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EINVAL; + } + + if (wlan_hdd_validate_vdev_id(adapter->vdev_id)) + return -EINVAL; + + qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_LEAVE_IBSS, + adapter->vdev_id, eCSR_DISCONNECT_REASON_IBSS_LEAVE); + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) + return status; + + hdd_debug("Device_mode %s(%d)", + qdf_opmode_str(adapter->device_mode), adapter->device_mode); + + roam_profile = hdd_roam_profile(adapter); + + /* Issue disconnect only if interface type is set to IBSS */ + if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) { + hdd_err("BSS Type is not set to IBSS"); + return -EINVAL; + } + /* Clearing add IE of beacon */ + qdf_mem_copy(update_ie.bssid.bytes, adapter->mac_addr.bytes, + sizeof(tSirMacAddr)); + update_ie.smeSessionId = adapter->vdev_id; + update_ie.ieBufferlength = 0; + update_ie.pAdditionIEBuffer = NULL; + update_ie.append = true; + update_ie.notify = true; + mac_handle = hdd_ctx->mac_handle; + if (sme_update_add_ie(mac_handle, + &update_ie, + eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) { + hdd_err("Could not pass on PROBE_RSP_BCN data to PE"); + } + + /* Reset WNI_CFG_PROBE_RSP Flags */ + wlan_hdd_reset_prob_rspies(adapter); + + /* Issue Disconnect request */ + INIT_COMPLETION(adapter->disconnect_comp_var); + status = sme_roam_disconnect(mac_handle, + adapter->vdev_id, + eCSR_DISCONNECT_REASON_IBSS_LEAVE); + if (!QDF_IS_STATUS_SUCCESS(status)) { + hdd_err("sme_roam_disconnect failed status: %d", + status); + return -EAGAIN; + } + + /* wait for mc thread to cleanup and then return to upper stack + * so by the time upper layer calls the change interface, we are + * all set to proceed further + */ + rc = wait_for_completion_timeout(&adapter->disconnect_comp_var, + msecs_to_jiffies(SME_DISCONNECT_TIMEOUT)); + if (!rc) { + hdd_err("Failed to disconnect, timed out"); + return -ETIMEDOUT; + } + + hdd_exit(); + return 0; +} + +/** + * wlan_hdd_cfg80211_leave_ibss() - leave ibss + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * + * This function is used to leave an IBSS network + * + * Return: 0 for success, non-zero for failure + */ +static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy, + struct net_device *dev) +{ + int errno; + struct osif_vdev_sync *vdev_sync; + + errno = osif_vdev_sync_op_start(dev, &vdev_sync); + if (errno) + return errno; + + errno = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev); + + osif_vdev_sync_op_stop(vdev_sync); + + return errno; +} +#else +/** + * wlan_hdd_cfg80211_join_ibss() - join ibss + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @param: Pointer to IBSS join parameters + * + * This function is dummy + * + * Return: 0 + */ +static inline int +wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ibss_params *params) +{ + return 0; +} + +/** + * wlan_hdd_cfg80211_leave_ibss() - leave ibss + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * + * This function is dummy + * + * Return: 0 + */ +static inline int +wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy, + struct net_device *dev) +{ + return 0; +} +#endif + #ifdef CRYPTO_SET_KEY_CONVERGED static void wlan_hdd_cfg80211_store_wep_key(struct hdd_adapter *adapter, struct wlan_objmgr_vdev *vdev, @@ -19538,443 +20048,6 @@ static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy, return errno; } -/** - * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy - * @adapter: Pointer to adapter - * @param: Pointer to IBSS parameters - * - * This function is used to initialize the security settings in IBSS mode - * - * Return: 0 for success, non-zero for failure - */ -static int wlan_hdd_cfg80211_set_privacy_ibss(struct hdd_adapter *adapter, - struct cfg80211_ibss_params - *params) -{ - uint32_t ret; - int status = 0; - eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE; - struct hdd_station_ctx *sta_ctx = - WLAN_HDD_GET_STATION_CTX_PTR(adapter); - struct csr_roam_profile *roam_profile; - - hdd_enter(); - - sta_ctx->wpa_versions = 0; - qdf_mem_zero(&sta_ctx->ibss_enc_key, sizeof(tCsrRoamSetKey)); - sta_ctx->ibss_enc_key_installed = 0; - - if (params->ie_len && (params->ie)) { - if (wlan_get_ie_ptr_from_eid(WLAN_EID_RSN, params->ie, - params->ie_len)) { - sta_ctx->wpa_versions = NL80211_WPA_VERSION_2; - encryptionType = eCSR_ENCRYPT_TYPE_AES; - } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) { - tDot11fIEWPA dot11_wpa_ie; - mac_handle_t mac_handle = - hdd_adapter_get_mac_handle(adapter); - const u8 *ie; - - memset(&dot11_wpa_ie, 0, sizeof(dot11_wpa_ie)); - ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_WPA, - params->ie, params->ie_len); - if (ie) { - sta_ctx->wpa_versions = NL80211_WPA_VERSION_1; - /* Unpack the WPA IE - * Skip past the EID byte and length byte - * and four byte WiFi OUI - */ - if (ie[1] < DOT11F_IE_WPA_MIN_LEN || - ie[1] > DOT11F_IE_WPA_MAX_LEN) { - hdd_err("invalid ie len:%d", ie[1]); - return -EINVAL; - } - ret = dot11f_unpack_ie_wpa( - MAC_CONTEXT(mac_handle), - (uint8_t *)&ie[2 + 4], - ie[1] - 4, &dot11_wpa_ie, false); - if (DOT11F_FAILED(ret)) { - hdd_err("unpack failed ret: 0x%x", ret); - return -EINVAL; - } - /* - * Extract the multicast cipher, the - * encType for unicast cipher for - * wpa-none is none - */ - encryptionType = - hdd_translate_wpa_to_csr_encryption_type - (dot11_wpa_ie.multicast_cipher); - } - } - - status = - wlan_hdd_cfg80211_set_ie(adapter, params->ie, - params->ie_len); - - if (0 > status) { - hdd_err("Failed to parse WPA/RSN IE"); - return status; - } - } - - roam_profile = hdd_roam_profile(adapter); - roam_profile->AuthType.authType[0] = - sta_ctx->conn_info.auth_type = eCSR_AUTH_TYPE_OPEN_SYSTEM; - - if (params->privacy) { - /* Security enabled IBSS, At this time there is no information - * available about the security parameters, so initialise the - * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY. - * The correct security parameters will be updated later in - * wlan_hdd_cfg80211_add_key Hal expects encryption type to be - * set inorder enable privacy bit in beacons - */ - - encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; - } - hdd_debug("encryptionType=%d", encryptionType); - sta_ctx->conn_info.uc_encrypt_type = encryptionType; - roam_profile->EncryptionType.numEntries = 1; - roam_profile->EncryptionType.encryptionType[0] = - encryptionType; - return status; -} - -/** - * __wlan_hdd_cfg80211_join_ibss() - join ibss - * @wiphy: Pointer to wiphy - * @dev: Pointer to network device - * @param: Pointer to IBSS join parameters - * - * This function is used to create/join an IBSS network - * - * Return: 0 for success, non-zero for failure - */ -static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, - struct net_device *dev, - struct cfg80211_ibss_params *params) -{ - struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); - struct csr_roam_profile *roam_profile; - int status; - struct hdd_station_ctx *sta_ctx = - WLAN_HDD_GET_STATION_CTX_PTR(adapter); - struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); - struct qdf_mac_addr bssid; - uint8_t channelNum = 0; - mac_handle_t mac_handle; - struct wlan_mlme_ibss_cfg ibss_cfg = {0}; - uint8_t conn_info_channel; - - hdd_enter(); - - if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { - hdd_err("Command not allowed in FTM mode"); - return -EINVAL; - } - - if (wlan_hdd_validate_vdev_id(adapter->vdev_id)) - return -EINVAL; - - qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD, - TRACE_CODE_HDD_CFG80211_JOIN_IBSS, - adapter->vdev_id, adapter->device_mode); - - hdd_debug("Device_mode %s(%d)", - qdf_opmode_str(adapter->device_mode), adapter->device_mode); - - status = wlan_hdd_validate_context(hdd_ctx); - - if (0 != status) - return status; - - if (QDF_IS_STATUS_ERROR(ucfg_mlme_get_ibss_cfg(hdd_ctx->psoc, - &ibss_cfg))) { - return -EINVAL; - } - - mac_handle = hdd_ctx->mac_handle; - if (NULL != - params->chandef.chan) { - uint32_t numChans = CFG_VALID_CHANNEL_LIST_LEN; - uint32_t validChan[CFG_VALID_CHANNEL_LIST_LEN]; - int indx; - - /* Get channel number */ - channelNum = ieee80211_frequency_to_channel( - params-> - chandef. - chan-> - center_freq); - ucfg_mlme_get_valid_channel_freq_list(hdd_ctx->psoc, validChan, - &numChans); - - for (indx = 0; indx < numChans; indx++) { - if (channelNum == - wlan_reg_freq_to_chan(hdd_ctx->pdev, validChan[indx])) - break; - } - if (indx >= numChans) { - hdd_err("Not valid Channel: %d", channelNum); - return -EINVAL; - } - } - - /* Disable NAN Discovery if enabled */ - ucfg_nan_disable_concurrency(hdd_ctx->psoc); - - if (!policy_mgr_allow_concurrency(hdd_ctx->psoc, - PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) { - hdd_err("This concurrency combination is not allowed"); - return -ECONNREFUSED; - } - - status = policy_mgr_reset_connection_update(hdd_ctx->psoc); - if (!QDF_IS_STATUS_SUCCESS(status)) - hdd_err("qdf_reset_connection_update failed status: %d", status); - - status = policy_mgr_current_connections_update(hdd_ctx->psoc, - adapter->vdev_id, channelNum, - POLICY_MGR_UPDATE_REASON_JOIN_IBSS); - if (QDF_STATUS_E_FAILURE == status) { - hdd_err("connections update failed!!"); - return -EINVAL; - } - - if (QDF_STATUS_SUCCESS == status) { - status = policy_mgr_wait_for_connection_update( - hdd_ctx->psoc); - if (!QDF_IS_STATUS_SUCCESS(status)) { - hdd_err("qdf wait for event failed!!"); - return -EINVAL; - } - } - - /*Try disconnecting if already in connected state */ - status = wlan_hdd_try_disconnect(adapter); - if (0 > status) { - hdd_err("Failed to disconnect the existing IBSS connection"); - return -EALREADY; - } - - roam_profile = hdd_roam_profile(adapter); - - if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) { - hdd_err("Interface type is not set to IBSS"); - return -EINVAL; - } - - /* enable selected protection checks in IBSS mode */ - roam_profile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK; - - /* BSSID is provided by upper layers hence no need to AUTO generate */ - if (params->bssid) { - if (ucfg_mlme_set_ibss_auto_bssid(hdd_ctx->psoc, 0) - == QDF_STATUS_E_FAILURE) { - hdd_err("Unable to update MLME IBSS Auto BSSID config"); - return -EIO; - } - qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE); - } else if (ibss_cfg.coalesing_enable == 0) { - if (ucfg_mlme_set_ibss_auto_bssid(hdd_ctx->psoc, 0) - == QDF_STATUS_E_FAILURE) { - hdd_err("Unable to update MLME IBSS Auto BSSID config"); - return -EIO; - } - qdf_copy_macaddr(&bssid, &ibss_cfg.bssid); - } - - if (cfg_in_range(CFG_BEACON_INTERVAL, params->beacon_interval)) - roam_profile->beaconInterval = params->beacon_interval; - else - roam_profile->beaconInterval = cfg_get(hdd_ctx->psoc, - CFG_BEACON_INTERVAL); - - /* Set Channel */ - if (channelNum) { - /* Set the Operational Channel */ - hdd_debug("set channel %d", channelNum); - roam_profile->ChannelInfo.numOfChannels = 1; - sta_ctx->conn_info.chan_freq = - wlan_reg_chan_to_freq(hdd_ctx->pdev, - channelNum); - roam_profile->ChannelInfo.freq_list = - &sta_ctx->conn_info.chan_freq; - } - - /* Initialize security parameters */ - status = wlan_hdd_cfg80211_set_privacy_ibss(adapter, params); - if (status < 0) { - hdd_err("failed to set security parameters"); - return status; - } - - conn_info_channel = - wlan_reg_freq_to_chan( - hdd_ctx->pdev, - sta_ctx->conn_info.chan_freq); - /* Issue connect start */ - status = wlan_hdd_cfg80211_connect_start(adapter, params->ssid, - params->ssid_len, - bssid.bytes, NULL, - conn_info_channel, - params->chandef.width); - - if (0 > status) { - hdd_err("connect failed"); - return status; - } - hdd_exit(); - return 0; -} - -/** - * wlan_hdd_cfg80211_join_ibss() - join ibss - * @wiphy: Pointer to wiphy - * @dev: Pointer to network device - * @param: Pointer to IBSS join parameters - * - * This function is used to create/join an IBSS network - * - * Return: 0 for success, non-zero for failure - */ -static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, - struct net_device *dev, - struct cfg80211_ibss_params *params) -{ - int errno; - struct osif_vdev_sync *vdev_sync; - - errno = osif_vdev_sync_op_start(dev, &vdev_sync); - if (errno) - return errno; - - errno = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params); - - osif_vdev_sync_op_stop(vdev_sync); - - return errno; -} - -/** - * __wlan_hdd_cfg80211_leave_ibss() - leave ibss - * @wiphy: Pointer to wiphy - * @dev: Pointer to network device - * - * This function is used to leave an IBSS network - * - * Return: 0 for success, non-zero for failure - */ -static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy, - struct net_device *dev) -{ - struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); - struct csr_roam_profile *roam_profile; - struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); - int status; - mac_handle_t mac_handle; - unsigned long rc; - tSirUpdateIE update_ie; - - hdd_enter(); - - if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { - hdd_err("Command not allowed in FTM mode"); - return -EINVAL; - } - - if (wlan_hdd_validate_vdev_id(adapter->vdev_id)) - return -EINVAL; - - qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD, - TRACE_CODE_HDD_CFG80211_LEAVE_IBSS, - adapter->vdev_id, eCSR_DISCONNECT_REASON_IBSS_LEAVE); - - status = wlan_hdd_validate_context(hdd_ctx); - if (0 != status) - return status; - - hdd_debug("Device_mode %s(%d)", - qdf_opmode_str(adapter->device_mode), adapter->device_mode); - - roam_profile = hdd_roam_profile(adapter); - - /* Issue disconnect only if interface type is set to IBSS */ - if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) { - hdd_err("BSS Type is not set to IBSS"); - return -EINVAL; - } - /* Clearing add IE of beacon */ - qdf_mem_copy(update_ie.bssid.bytes, adapter->mac_addr.bytes, - sizeof(tSirMacAddr)); - update_ie.smeSessionId = adapter->vdev_id; - update_ie.ieBufferlength = 0; - update_ie.pAdditionIEBuffer = NULL; - update_ie.append = true; - update_ie.notify = true; - mac_handle = hdd_ctx->mac_handle; - if (sme_update_add_ie(mac_handle, - &update_ie, - eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) { - hdd_err("Could not pass on PROBE_RSP_BCN data to PE"); - } - - /* Reset WNI_CFG_PROBE_RSP Flags */ - wlan_hdd_reset_prob_rspies(adapter); - - /* Issue Disconnect request */ - INIT_COMPLETION(adapter->disconnect_comp_var); - status = sme_roam_disconnect(mac_handle, - adapter->vdev_id, - eCSR_DISCONNECT_REASON_IBSS_LEAVE); - if (!QDF_IS_STATUS_SUCCESS(status)) { - hdd_err("sme_roam_disconnect failed status: %d", - status); - return -EAGAIN; - } - - /* wait for mc thread to cleanup and then return to upper stack - * so by the time upper layer calls the change interface, we are - * all set to proceed further - */ - rc = wait_for_completion_timeout(&adapter->disconnect_comp_var, - msecs_to_jiffies(SME_DISCONNECT_TIMEOUT)); - if (!rc) { - hdd_err("Failed to disconnect, timed out"); - return -ETIMEDOUT; - } - - hdd_exit(); - return 0; -} - -/** - * wlan_hdd_cfg80211_leave_ibss() - leave ibss - * @wiphy: Pointer to wiphy - * @dev: Pointer to network device - * - * This function is used to leave an IBSS network - * - * Return: 0 for success, non-zero for failure - */ -static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy, - struct net_device *dev) -{ - int errno; - struct osif_vdev_sync *vdev_sync; - - errno = osif_vdev_sync_op_start(dev, &vdev_sync); - if (errno) - return errno; - - errno = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev); - - osif_vdev_sync_op_stop(vdev_sync); - - return errno; -} - /** * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters * @wiphy: Pointer to wiphy diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index f010f4c605e9..85e885e2f0d5 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -64,13 +64,6 @@ */ #define SIZE_OF_GETCOUNTRYREV_OUTPUT 20 -/* - * Ibss prop IE from command will be of size: - * size = sizeof(oui) + sizeof(oui_data) + 1(Element ID) + 1(EID Length) - * OUI_DATA should be at least 3 bytes long - */ -#define WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH (3) - #ifdef FEATURE_WLAN_ESE #define TID_MIN_VALUE 0 #define TID_MAX_VALUE 15 @@ -149,8 +142,6 @@ struct hdd_drv_cmd { #define WLAN_HDD_MAX_TCP_PORT 65535 #endif -static uint16_t cesium_pid; - /** * drv_cmd_validate() - Validates for space in hdd driver command * @command: pointer to input data (its a NULL terminated string) @@ -249,16 +240,15 @@ static int hdd_get_tsm_stats(struct hdd_adapter *adapter, } #endif /*FEATURE_WLAN_ESE */ -/** - * hdd_get_ibss_peer_info_cb() - IBSS peer Info request callback - * @context: callback context (adapter supplied by caller) - * @peer_info: Peer info response - * - * This is an asynchronous callback function from SME when the peer info - * is received - * - * Return: 0 for success non-zero for failure +#ifdef QCA_IBSS_SUPPORT +/* + * Ibss prop IE from command will be of size: + * size = sizeof(oui) + sizeof(oui_data) + 1(Element ID) + 1(EID Length) + * OUI_DATA should be at least 3 bytes long */ +#define WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH (3) +static uint16_t cesium_pid; + void hdd_get_ibss_peer_info_cb(void *context, tSirPeerInfoRspParams *peer_info) @@ -416,6 +406,649 @@ hdd_parse_get_ibss_peer_info(uint8_t *command, return QDF_STATUS_SUCCESS; } +static void hdd_tx_fail_ind_callback(uint8_t *macaddr, uint8_t seq_no) +{ + int payload_len; + struct sk_buff *skb; + struct nlmsghdr *nlh; + uint8_t *data; + + payload_len = ETH_ALEN; + + if (0 == cesium_pid || !cesium_nl_srv_sock) { + hdd_err("cesium process not registered"); + return; + } + + skb = nlmsg_new(payload_len, GFP_ATOMIC); + if (!skb) { + hdd_err("nlmsg_new() failed for msg size[%d]", + NLMSG_SPACE(payload_len)); + return; + } + + nlh = nlmsg_put(skb, cesium_pid, seq_no, 0, payload_len, NLM_F_REQUEST); + + if (!nlh) { + hdd_err("nlmsg_put() failed for msg size[%d]", + NLMSG_SPACE(payload_len)); + + kfree_skb(skb); + return; + } + + data = nlmsg_data(nlh); + memcpy(data, macaddr, ETH_ALEN); + + if (nlmsg_unicast(cesium_nl_srv_sock, skb, cesium_pid) < 0) { + hdd_err("nlmsg_unicast() failed for msg size[%d]", + NLMSG_SPACE(payload_len)); + } +} + +/** + * hdd_parse_user_params() - return a pointer to the next argument + * @command: Input argument string + * @arg: Output pointer to the next argument + * + * This function parses argument stream and finds the pointer + * to the next argument + * + * Return: 0 if the next argument found; -EINVAL otherwise + */ +static int hdd_parse_user_params(uint8_t *command, uint8_t **arg) +{ + uint8_t *cursor; + + cursor = strnchr(command, strlen(command), SPACE_ASCII_VALUE); + + /* no argument remains ? */ + if (!cursor) + return -EINVAL; + + /* no space after the current arg ? */ + if (SPACE_ASCII_VALUE != *cursor) + return -EINVAL; + + cursor++; + + /* remove empty spaces */ + while (SPACE_ASCII_VALUE == *cursor) + cursor++; + + /* no argument after the spaces ? */ + if ('\0' == *cursor) + return -EINVAL; + + *arg = cursor; + + return 0; +} + +/** + * hdd_parse_ibsstx_fail_event_params - Parse params + * for SETIBSSTXFAILEVENT + * @command: Input ibss tx fail event argument + * @tx_fail_count: (Output parameter) Tx fail counter + * @pid: (Output parameter) PID + * + * Return: 0 if the parsing succeeds; -EINVAL otherwise + */ +static int hdd_parse_ibsstx_fail_event_params(uint8_t *command, + uint8_t *tx_fail_count, + uint16_t *pid) +{ + uint8_t *param = NULL; + int ret; + + ret = hdd_parse_user_params(command, ¶m); + + if (0 == ret && param) { + if (1 != sscanf(param, "%hhu", tx_fail_count)) { + ret = -EINVAL; + goto done; + } + } else { + goto done; + } + + if (0 == *tx_fail_count) { + *pid = 0; + goto done; + } + + command = param; + command++; + + ret = hdd_parse_user_params(command, ¶m); + + if (0 == ret) { + if (1 != sscanf(param, "%hu", pid)) { + ret = -EINVAL; + goto done; + } + } else { + goto done; + } + +done: + return ret; +} + +/* Function header is left blank intentionally */ +static int hdd_parse_set_ibss_oui_data_command(uint8_t *command, uint8_t *ie, + int32_t *oui_length, int32_t limit) +{ + uint8_t len; + uint8_t data; + + while ((SPACE_ASCII_VALUE == *command) && ('\0' != *command)) { + command++; + limit--; + } + + len = 2; + + while ((SPACE_ASCII_VALUE != *command) && ('\0' != *command) && + (limit > 1)) { + sscanf(command, "%02x", (unsigned int *)&data); + ie[len++] = data; + command += 2; + limit -= 2; + } + + *oui_length = len - 2; + + while ((SPACE_ASCII_VALUE == *command) && ('\0' != *command)) { + command++; + limit--; + } + + while ((SPACE_ASCII_VALUE != *command) && ('\0' != *command) && + (limit > 1)) { + sscanf(command, "%02x", (unsigned int *)&data); + ie[len++] = data; + command += 2; + limit -= 2; + } + + ie[0] = WLAN_ELEMID_VENDOR; + ie[1] = len - 2; + + return len; +} + +/** + * drv_cmd_set_ibss_beacon_oui_data() - set ibss oui data command + * @adapter: Pointer to adapter + * @hdd_ctx: Pointer to HDD context + * @command: Pointer to command string + * @command_len : Command length + * @priv_data : Pointer to priv data + * + * Return: + * int status code + */ +static int drv_cmd_set_ibss_beacon_oui_data(struct hdd_adapter *adapter, + struct hdd_context *hdd_ctx, + uint8_t *command, + uint8_t command_len, + struct hdd_priv_data *priv_data) +{ + int i = 0; + int status; + int ret = 0; + uint8_t *ibss_ie; + int32_t oui_length = 0; + uint32_t ibss_ie_length; + uint8_t *value = command; + tSirModifyIE modify_ie; + struct csr_roam_profile *roam_profile; + mac_handle_t mac_handle; + + if (QDF_IBSS_MODE != adapter->device_mode) { + hdd_debug("Device_mode %s(%d) not IBSS", + qdf_opmode_str(adapter->device_mode), + adapter->device_mode); + return ret; + } + + hdd_debug("received command %s", ((char *)value)); + + /* validate argument of command */ + if (strlen(value) <= command_len) { + hdd_err("No arguments in command length %zu", + strlen(value)); + ret = -EFAULT; + goto exit; + } + + /* moving to arguments of commands */ + value = value + command_len; + command_len = strlen(value); + + /* oui_data can't be less than 3 bytes */ + if (command_len < (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH)) { + hdd_err("Invalid SETIBSSBEACONOUIDATA command length %d", + command_len); + ret = -EFAULT; + goto exit; + } + + ibss_ie = qdf_mem_malloc(command_len); + if (!ibss_ie) { + hdd_err("Could not allocate memory for command length %d", + command_len); + ret = -ENOMEM; + goto exit; + } + + ibss_ie_length = hdd_parse_set_ibss_oui_data_command(value, ibss_ie, + &oui_length, + command_len); + if (ibss_ie_length <= (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH)) { + hdd_err("Could not parse command %s return length %d", + value, ibss_ie_length); + ret = -EFAULT; + qdf_mem_free(ibss_ie); + goto exit; + } + + roam_profile = hdd_roam_profile(adapter); + + qdf_copy_macaddr(&modify_ie.bssid, + roam_profile->BSSIDs.bssid); + + modify_ie.smeSessionId = adapter->vdev_id; + modify_ie.notify = true; + modify_ie.ieID = WLAN_ELEMID_VENDOR; + modify_ie.ieIDLen = ibss_ie_length; + modify_ie.ieBufferlength = ibss_ie_length; + modify_ie.pIEBuffer = ibss_ie; + modify_ie.oui_length = oui_length; + + hdd_warn("ibss_ie length %d oui_length %d ibss_ie:", + ibss_ie_length, oui_length); + while (i < modify_ie.ieBufferlength) + hdd_warn("0x%x", ibss_ie[i++]); + + /* Probe Bcn modification */ + mac_handle = hdd_ctx->mac_handle; + sme_modify_add_ie(mac_handle, &modify_ie, eUPDATE_IE_PROBE_BCN); + + /* Populating probe resp frame */ + sme_modify_add_ie(mac_handle, &modify_ie, eUPDATE_IE_PROBE_RESP); + + qdf_mem_free(ibss_ie); + + status = sme_send_cesium_enable_ind(mac_handle, + adapter->vdev_id); + if (QDF_STATUS_SUCCESS != status) { + hdd_err("Could not send cesium enable indication %d", + status); + ret = -EINVAL; + goto exit; + } + +exit: + return ret; +} + +static int drv_cmd_get_ibss_peer_info_all(struct hdd_adapter *adapter, + struct hdd_context *hdd_ctx, + uint8_t *command, + uint8_t command_len, + struct hdd_priv_data *priv_data) +{ + int ret = 0; + int status = QDF_STATUS_SUCCESS; + struct hdd_station_ctx *sta_ctx = NULL; + char *extra = NULL; + int idx = 0; + int length = 0; + uint8_t mac_addr[QDF_MAC_ADDR_SIZE]; + uint32_t print_break_index = 0; + + if (QDF_IBSS_MODE != adapter->device_mode) { + hdd_warn("Unsupported in mode %s(%d)", + qdf_opmode_str(adapter->device_mode), + adapter->device_mode); + return -EINVAL; + } + + sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + hdd_debug("Received GETIBSSPEERINFOALL Command"); + + /* Handle the command */ + status = hdd_cfg80211_get_ibss_peer_info_all(adapter); + if (QDF_STATUS_SUCCESS == status) { + size_t user_size = qdf_min(WLAN_MAX_BUF_SIZE, + priv_data->total_len); + + /* + * The variable extra needed to be allocated on the heap since + * amount of memory required to copy the data for 32 devices + * exceeds the size of 1024 bytes of default stack size. On + * 64 bit devices, the default max stack size of 2048 bytes + */ + extra = qdf_mem_malloc(user_size); + + if (!extra) { + hdd_err("memory allocation failed"); + ret = -ENOMEM; + goto exit; + } + + /* Copy number of stations */ + length = scnprintf(extra, user_size, "%d ", + sta_ctx->ibss_peer_info.numPeers); + print_break_index = length; + for (idx = 0; idx < sta_ctx->ibss_peer_info.numPeers; + idx++) { + int8_t rssi; + uint32_t tx_rate; + + qdf_mem_copy(mac_addr, + sta_ctx->ibss_peer_info.peerInfoParams[idx]. + mac_addr, sizeof(mac_addr)); + + tx_rate = + sta_ctx->ibss_peer_info.peerInfoParams[idx]. + txRate; + /* + * Only lower 3 bytes are rate info. Mask of the MSByte + */ + tx_rate &= 0x00FFFFFF; + + rssi = sta_ctx->ibss_peer_info.peerInfoParams[idx]. + rssi; + + length += scnprintf(extra + length, + user_size - length, + QDF_MAC_ADDR_STR" %d %d ", + QDF_MAC_ADDR_ARRAY(mac_addr), + tx_rate, rssi); + /* + * cdf_trace_msg has limitation of 512 bytes for the + * print buffer. Hence printing the data in two chunks. + * The first chunk will have the data for 16 devices + * and the second chunk will have the rest. + */ + if (idx < NUM_OF_STA_DATA_TO_PRINT) + print_break_index = length; + } + + /* + * Copy the data back into buffer, if the data to copy is + * more than 512 bytes than we will split the data and do + * it in two shots + */ + if (copy_to_user(priv_data->buf, extra, print_break_index)) { + hdd_err("Copy into user data buffer failed"); + ret = -EFAULT; + goto mem_free; + } + + /* This overwrites the last space, which we already copied */ + extra[print_break_index - 1] = '\0'; + hdd_debug("%s", extra); + + if (length > print_break_index) { + if (copy_to_user + (priv_data->buf + print_break_index, + extra + print_break_index, + length - print_break_index + 1)) { + hdd_err("Copy into user data buffer failed"); + ret = -EFAULT; + goto mem_free; + } + hdd_debug("%s", &extra[print_break_index]); + } + } else { + /* Command failed, log error */ + hdd_err("GETIBSSPEERINFOALL command failed with status code %d", + status); + ret = -EINVAL; + goto exit; + } + ret = 0; + +mem_free: + qdf_mem_free(extra); +exit: + return ret; +} + +/* Peer Info command */ +static int drv_cmd_get_ibss_peer_info(struct hdd_adapter *adapter, + struct hdd_context *hdd_ctx, + uint8_t *command, + uint8_t command_len, + struct hdd_priv_data *priv_data) +{ + int ret = 0; + uint8_t *value = command; + QDF_STATUS status; + struct hdd_station_ctx *sta_ctx = NULL; + char extra[128] = { 0 }; + uint32_t length = 0; + uint8_t sta_id = 0; + struct qdf_mac_addr peer_macaddr; + + if (QDF_IBSS_MODE != adapter->device_mode) { + hdd_warn("Unsupported in mode %s(%d)", + qdf_opmode_str(adapter->device_mode), + adapter->device_mode); + return -EINVAL; + } + + sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + + hdd_debug("Received GETIBSSPEERINFO Command"); + + /* if there are no peers, no need to continue with the command */ + if (eConnectionState_IbssConnected != + sta_ctx->conn_info.conn_state) { + hdd_err("No IBSS Peers coalesced"); + ret = -EINVAL; + goto exit; + } + + /* Parse the incoming command buffer */ + status = hdd_parse_get_ibss_peer_info(value, &peer_macaddr); + if (QDF_STATUS_SUCCESS != status) { + hdd_err("Invalid GETIBSSPEERINFO command"); + ret = -EINVAL; + goto exit; + } + + /* Get station index for the peer mac address and sanitize it */ + hdd_get_peer_sta_id(sta_ctx, &peer_macaddr, &sta_id); + + if (sta_id > MAX_PEERS) { + hdd_err("Invalid StaIdx %d returned", sta_id); + ret = -EINVAL; + goto exit; + } + + /* Handle the command */ + status = hdd_cfg80211_get_ibss_peer_info(adapter, sta_id); + if (QDF_STATUS_SUCCESS == status) { + uint32_t tx_rate = + sta_ctx->ibss_peer_info.peerInfoParams[0].txRate; + /* Only lower 3 bytes are rate info. Mask of the MSByte */ + tx_rate &= 0x00FFFFFF; + + length = scnprintf(extra, sizeof(extra), "%d %d", + (int)tx_rate, + (int)sta_ctx->ibss_peer_info. + peerInfoParams[0].rssi); + length = QDF_MIN(priv_data->total_len, length + 1); + + /* Copy the data back into buffer */ + if (copy_to_user(priv_data->buf, &extra, length)) { + hdd_err("copy data to user buffer failed GETIBSSPEERINFO command"); + ret = -EFAULT; + goto exit; + } + } else { + /* Command failed, log error */ + hdd_err("GETIBSSPEERINFO command failed with status code %d", + status); + ret = -EINVAL; + goto exit; + } + + /* Success ! */ + hdd_debug("%s", extra); + ret = 0; + +exit: + return ret; +} + +static int drv_cmd_set_ibss_tx_fail_event(struct hdd_adapter *adapter, + struct hdd_context *hdd_ctx, + uint8_t *command, + uint8_t command_len, + struct hdd_priv_data *priv_data) +{ + int ret = 0; + char *value; + uint8_t tx_fail_count = 0; + uint16_t pid = 0; + mac_handle_t mac_handle; + + value = command; + + ret = hdd_parse_ibsstx_fail_event_params(value, &tx_fail_count, &pid); + + if (0 != ret) { + hdd_err("Failed to parse SETIBSSTXFAILEVENT arguments"); + goto exit; + } + + hdd_debug("tx_fail_cnt=%hhu, pid=%hu", tx_fail_count, pid); + mac_handle = hdd_ctx->mac_handle; + + if (0 == tx_fail_count) { + /* Disable TX Fail Indication */ + if (QDF_STATUS_SUCCESS == + sme_tx_fail_monitor_start_stop_ind(mac_handle, + tx_fail_count, + NULL)) { + cesium_pid = 0; + } else { + hdd_err("failed to disable TX Fail Event"); + ret = -EINVAL; + } + } else { + if (QDF_STATUS_SUCCESS == + sme_tx_fail_monitor_start_stop_ind(mac_handle, + tx_fail_count, + (void *)hdd_tx_fail_ind_callback)) { + cesium_pid = pid; + hdd_debug("Registered Cesium pid %u", + cesium_pid); + } else { + hdd_err("Failed to enable TX Fail Monitoring"); + ret = -EINVAL; + } + } + +exit: + return ret; +} +#else +/** + * drv_cmd_get_ibss_peer_info() - get ibss peer info all + * @adapter: Pointer to adapter + * @hdd_ctx: Pointer to HDD context + * @command: Pointer to command string + * @command_len : Command length + * @priv_data : Pointer to priv data + * + * This function is dummy + * + * Return: 0 + */ +static inline int +drv_cmd_get_ibss_peer_info_all(struct hdd_adapter *adapter, + struct hdd_context *hdd_ctx, + uint8_t *command, + uint8_t command_len, + struct hdd_priv_data *priv_data) +{ + return 0; +} + +/** + * drv_cmd_get_ibss_peer_info() - get ibss peer info + * @adapter: Pointer to adapter + * @hdd_ctx: Pointer to HDD context + * @command: Pointer to command string + * @command_len : Command length + * @priv_data : Pointer to priv data + * + * This function is dummy + * + * Return: 0 + */ +static inline int +drv_cmd_get_ibss_peer_info(struct hdd_adapter *adapter, + struct hdd_context *hdd_ctx, + uint8_t *command, + uint8_t command_len, + struct hdd_priv_data *priv_data) +{ + return 0; +} + +/** + * drv_cmd_set_ibss_tx_fail_event() - set ibss tx fail event + * @adapter: Pointer to adapter + * @hdd_ctx: Pointer to HDD context + * @command: Pointer to command string + * @command_len : Command length + * @priv_data : Pointer to priv data + * + * This function is dummy + * + * Return: 0 + */ +static inline int +drv_cmd_set_ibss_tx_fail_event(struct hdd_adapter *adapter, + struct hdd_context *hdd_ctx, + uint8_t *command, + uint8_t command_len, + struct hdd_priv_data *priv_data) +{ + return 0; +} + +/** + * drv_cmd_set_ibss_beacon_oui_data() - set ibss oui data command + * @adapter: Pointer to adapter + * @hdd_ctx: Pointer to HDD context + * @command: Pointer to command string + * @command_len : Command length + * @priv_data : Pointer to priv data + * + * This function is dummy + * + * Return: 0 + */ +static inline int +drv_cmd_set_ibss_beacon_oui_data(struct hdd_adapter *adapter, + struct hdd_context *hdd_ctx, + uint8_t *command, + uint8_t command_len, + struct hdd_priv_data *priv_data) +{ + return 0; +} +#endif + static void hdd_get_band_helper(struct hdd_context *hdd_ctx, int *ui_band) { enum band_info band = -1; @@ -2382,136 +3015,6 @@ static int wlan_hdd_get_link_status(struct hdd_adapter *adapter) return adapter->link_status; } -static void hdd_tx_fail_ind_callback(uint8_t *macaddr, uint8_t seq_no) -{ - int payload_len; - struct sk_buff *skb; - struct nlmsghdr *nlh; - uint8_t *data; - - payload_len = ETH_ALEN; - - if (0 == cesium_pid || !cesium_nl_srv_sock) { - hdd_err("cesium process not registered"); - return; - } - - skb = nlmsg_new(payload_len, GFP_ATOMIC); - if (!skb) { - hdd_err("nlmsg_new() failed for msg size[%d]", - NLMSG_SPACE(payload_len)); - return; - } - - nlh = nlmsg_put(skb, cesium_pid, seq_no, 0, payload_len, NLM_F_REQUEST); - - if (!nlh) { - hdd_err("nlmsg_put() failed for msg size[%d]", - NLMSG_SPACE(payload_len)); - - kfree_skb(skb); - return; - } - - data = nlmsg_data(nlh); - memcpy(data, macaddr, ETH_ALEN); - - if (nlmsg_unicast(cesium_nl_srv_sock, skb, cesium_pid) < 0) { - hdd_err("nlmsg_unicast() failed for msg size[%d]", - NLMSG_SPACE(payload_len)); - } -} - - -/** - * hdd_parse_user_params() - return a pointer to the next argument - * @command: Input argument string - * @arg: Output pointer to the next argument - * - * This function parses argument stream and finds the pointer - * to the next argument - * - * Return: 0 if the next argument found; -EINVAL otherwise - */ -static int hdd_parse_user_params(uint8_t *command, uint8_t **arg) -{ - uint8_t *cursor; - - cursor = strnchr(command, strlen(command), SPACE_ASCII_VALUE); - - /* no argument remains ? */ - if (!cursor) - return -EINVAL; - - /* no space after the current arg ? */ - if (SPACE_ASCII_VALUE != *cursor) - return -EINVAL; - - cursor++; - - /* remove empty spaces */ - while (SPACE_ASCII_VALUE == *cursor) - cursor++; - - /* no argument after the spaces ? */ - if ('\0' == *cursor) - return -EINVAL; - - *arg = cursor; - - return 0; -} - -/** - * hdd_parse_ibsstx_fail_event_params - Parse params - * for SETIBSSTXFAILEVENT - * @command: Input ibss tx fail event argument - * @tx_fail_count: (Output parameter) Tx fail counter - * @pid: (Output parameter) PID - * - * Return: 0 if the parsing succeeds; -EINVAL otherwise - */ -static int hdd_parse_ibsstx_fail_event_params(uint8_t *command, - uint8_t *tx_fail_count, - uint16_t *pid) -{ - uint8_t *param = NULL; - int ret; - - ret = hdd_parse_user_params(command, ¶m); - - if (0 == ret && param) { - if (1 != sscanf(param, "%hhu", tx_fail_count)) { - ret = -EINVAL; - goto done; - } - } else { - goto done; - } - - if (0 == *tx_fail_count) { - *pid = 0; - goto done; - } - - command = param; - command++; - - ret = hdd_parse_user_params(command, ¶m); - - if (0 == ret) { - if (1 != sscanf(param, "%hu", pid)) { - ret = -EINVAL; - goto done; - } - } else { - goto done; - } - -done: - return ret; -} - #ifdef FEATURE_WLAN_ESE /** * hdd_parse_ese_beacon_req() - Parse ese beacon request @@ -4680,165 +5183,6 @@ exit: return ret; } -/* Function header is left blank intentionally */ -static int hdd_parse_set_ibss_oui_data_command(uint8_t *command, uint8_t *ie, - int32_t *oui_length, int32_t limit) -{ - uint8_t len; - uint8_t data; - - while ((SPACE_ASCII_VALUE == *command) && ('\0' != *command)) { - command++; - limit--; - } - - len = 2; - - while ((SPACE_ASCII_VALUE != *command) && ('\0' != *command) && - (limit > 1)) { - sscanf(command, "%02x", (unsigned int *)&data); - ie[len++] = data; - command += 2; - limit -= 2; - } - - *oui_length = len - 2; - - while ((SPACE_ASCII_VALUE == *command) && ('\0' != *command)) { - command++; - limit--; - } - - while ((SPACE_ASCII_VALUE != *command) && ('\0' != *command) && - (limit > 1)) { - sscanf(command, "%02x", (unsigned int *)&data); - ie[len++] = data; - command += 2; - limit -= 2; - } - - ie[0] = WLAN_ELEMID_VENDOR; - ie[1] = len - 2; - - return len; -} - -/** - * drv_cmd_set_ibss_beacon_oui_data() - set ibss oui data command - * @adapter: Pointer to adapter - * @hdd_ctx: Pointer to HDD context - * @command: Pointer to command string - * @command_len : Command length - * @priv_data : Pointer to priv data - * - * Return: - * int status code - */ -static int drv_cmd_set_ibss_beacon_oui_data(struct hdd_adapter *adapter, - struct hdd_context *hdd_ctx, - uint8_t *command, - uint8_t command_len, - struct hdd_priv_data *priv_data) -{ - int i = 0; - int status; - int ret = 0; - uint8_t *ibss_ie; - int32_t oui_length = 0; - uint32_t ibss_ie_length; - uint8_t *value = command; - tSirModifyIE modify_ie; - struct csr_roam_profile *roam_profile; - mac_handle_t mac_handle; - - if (QDF_IBSS_MODE != adapter->device_mode) { - hdd_debug("Device_mode %s(%d) not IBSS", - qdf_opmode_str(adapter->device_mode), - adapter->device_mode); - return ret; - } - - hdd_debug("received command %s", ((char *)value)); - - /* validate argument of command */ - if (strlen(value) <= command_len) { - hdd_err("No arguments in command length %zu", - strlen(value)); - ret = -EFAULT; - goto exit; - } - - /* moving to arguments of commands */ - value = value + command_len; - command_len = strlen(value); - - /* oui_data can't be less than 3 bytes */ - if (command_len < (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH)) { - hdd_err("Invalid SETIBSSBEACONOUIDATA command length %d", - command_len); - ret = -EFAULT; - goto exit; - } - - ibss_ie = qdf_mem_malloc(command_len); - if (!ibss_ie) { - hdd_err("Could not allocate memory for command length %d", - command_len); - ret = -ENOMEM; - goto exit; - } - - ibss_ie_length = hdd_parse_set_ibss_oui_data_command(value, ibss_ie, - &oui_length, - command_len); - if (ibss_ie_length <= (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH)) { - hdd_err("Could not parse command %s return length %d", - value, ibss_ie_length); - ret = -EFAULT; - qdf_mem_free(ibss_ie); - goto exit; - } - - roam_profile = hdd_roam_profile(adapter); - - qdf_copy_macaddr(&modify_ie.bssid, - roam_profile->BSSIDs.bssid); - - modify_ie.smeSessionId = adapter->vdev_id; - modify_ie.notify = true; - modify_ie.ieID = WLAN_ELEMID_VENDOR; - modify_ie.ieIDLen = ibss_ie_length; - modify_ie.ieBufferlength = ibss_ie_length; - modify_ie.pIEBuffer = ibss_ie; - modify_ie.oui_length = oui_length; - - hdd_warn("ibss_ie length %d oui_length %d ibss_ie:", - ibss_ie_length, oui_length); - while (i < modify_ie.ieBufferlength) - hdd_warn("0x%x", ibss_ie[i++]); - - /* Probe Bcn modification */ - mac_handle = hdd_ctx->mac_handle; - sme_modify_add_ie(mac_handle, &modify_ie, eUPDATE_IE_PROBE_BCN); - - /* Populating probe resp frame */ - sme_modify_add_ie(mac_handle, &modify_ie, eUPDATE_IE_PROBE_RESP); - - qdf_mem_free(ibss_ie); - - status = sme_send_cesium_enable_ind(mac_handle, - adapter->vdev_id); - if (QDF_STATUS_SUCCESS != status) { - hdd_err("Could not send cesium enable indication %d", - status); - ret = -EINVAL; - goto exit; - } - -exit: - return ret; -} - #ifdef FEATURE_WLAN_RMC /* Function header is left blank intentionally */ static int hdd_parse_setrmcenable_command(uint8_t *command, @@ -5146,272 +5490,6 @@ exit: } #endif /* FEATURE_WLAN_RMC */ -static int drv_cmd_get_ibss_peer_info_all(struct hdd_adapter *adapter, - struct hdd_context *hdd_ctx, - uint8_t *command, - uint8_t command_len, - struct hdd_priv_data *priv_data) -{ - int ret = 0; - int status = QDF_STATUS_SUCCESS; - struct hdd_station_ctx *sta_ctx = NULL; - char *extra = NULL; - int idx = 0; - int length = 0; - uint8_t mac_addr[QDF_MAC_ADDR_SIZE]; - uint32_t print_break_index = 0; - - if (QDF_IBSS_MODE != adapter->device_mode) { - hdd_warn("Unsupported in mode %s(%d)", - qdf_opmode_str(adapter->device_mode), - adapter->device_mode); - return -EINVAL; - } - - sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); - hdd_debug("Received GETIBSSPEERINFOALL Command"); - - /* Handle the command */ - status = hdd_cfg80211_get_ibss_peer_info_all(adapter); - if (QDF_STATUS_SUCCESS == status) { - size_t user_size = qdf_min(WLAN_MAX_BUF_SIZE, - priv_data->total_len); - - /* - * The variable extra needed to be allocated on the heap since - * amount of memory required to copy the data for 32 devices - * exceeds the size of 1024 bytes of default stack size. On - * 64 bit devices, the default max stack size of 2048 bytes - */ - extra = qdf_mem_malloc(user_size); - - if (!extra) { - hdd_err("memory allocation failed"); - ret = -ENOMEM; - goto exit; - } - - /* Copy number of stations */ - length = scnprintf(extra, user_size, "%d ", - sta_ctx->ibss_peer_info.numPeers); - print_break_index = length; - for (idx = 0; idx < sta_ctx->ibss_peer_info.numPeers; - idx++) { - int8_t rssi; - uint32_t tx_rate; - - qdf_mem_copy(mac_addr, - sta_ctx->ibss_peer_info.peerInfoParams[idx]. - mac_addr, sizeof(mac_addr)); - - tx_rate = - sta_ctx->ibss_peer_info.peerInfoParams[idx]. - txRate; - /* - * Only lower 3 bytes are rate info. Mask of the MSByte - */ - tx_rate &= 0x00FFFFFF; - - rssi = sta_ctx->ibss_peer_info.peerInfoParams[idx]. - rssi; - - length += scnprintf(extra + length, - user_size - length, - QDF_MAC_ADDR_STR" %d %d ", - QDF_MAC_ADDR_ARRAY(mac_addr), - tx_rate, rssi); - /* - * cdf_trace_msg has limitation of 512 bytes for the - * print buffer. Hence printing the data in two chunks. - * The first chunk will have the data for 16 devices - * and the second chunk will have the rest. - */ - if (idx < NUM_OF_STA_DATA_TO_PRINT) - print_break_index = length; - } - - /* - * Copy the data back into buffer, if the data to copy is - * more than 512 bytes than we will split the data and do - * it in two shots - */ - if (copy_to_user(priv_data->buf, extra, print_break_index)) { - hdd_err("Copy into user data buffer failed"); - ret = -EFAULT; - goto mem_free; - } - - /* This overwrites the last space, which we already copied */ - extra[print_break_index - 1] = '\0'; - hdd_debug("%s", extra); - - if (length > print_break_index) { - if (copy_to_user - (priv_data->buf + print_break_index, - extra + print_break_index, - length - print_break_index + 1)) { - hdd_err("Copy into user data buffer failed"); - ret = -EFAULT; - goto mem_free; - } - hdd_debug("%s", &extra[print_break_index]); - } - } else { - /* Command failed, log error */ - hdd_err("GETIBSSPEERINFOALL command failed with status code %d", - status); - ret = -EINVAL; - goto exit; - } - ret = 0; - -mem_free: - qdf_mem_free(extra); -exit: - return ret; -} - -/* Peer Info command */ -static int drv_cmd_get_ibss_peer_info(struct hdd_adapter *adapter, - struct hdd_context *hdd_ctx, - uint8_t *command, - uint8_t command_len, - struct hdd_priv_data *priv_data) -{ - int ret = 0; - uint8_t *value = command; - QDF_STATUS status; - struct hdd_station_ctx *sta_ctx = NULL; - char extra[128] = { 0 }; - uint32_t length = 0; - uint8_t sta_id = 0; - struct qdf_mac_addr peer_macaddr; - - if (QDF_IBSS_MODE != adapter->device_mode) { - hdd_warn("Unsupported in mode %s(%d)", - qdf_opmode_str(adapter->device_mode), - adapter->device_mode); - return -EINVAL; - } - - sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); - - hdd_debug("Received GETIBSSPEERINFO Command"); - - /* if there are no peers, no need to continue with the command */ - if (eConnectionState_IbssConnected != - sta_ctx->conn_info.conn_state) { - hdd_err("No IBSS Peers coalesced"); - ret = -EINVAL; - goto exit; - } - - /* Parse the incoming command buffer */ - status = hdd_parse_get_ibss_peer_info(value, &peer_macaddr); - if (QDF_STATUS_SUCCESS != status) { - hdd_err("Invalid GETIBSSPEERINFO command"); - ret = -EINVAL; - goto exit; - } - - /* Get station index for the peer mac address and sanitize it */ - hdd_get_peer_sta_id(sta_ctx, &peer_macaddr, &sta_id); - - if (sta_id > MAX_PEERS) { - hdd_err("Invalid StaIdx %d returned", sta_id); - ret = -EINVAL; - goto exit; - } - - /* Handle the command */ - status = hdd_cfg80211_get_ibss_peer_info(adapter, sta_id); - if (QDF_STATUS_SUCCESS == status) { - uint32_t tx_rate = - sta_ctx->ibss_peer_info.peerInfoParams[0].txRate; - /* Only lower 3 bytes are rate info. Mask of the MSByte */ - tx_rate &= 0x00FFFFFF; - - length = scnprintf(extra, sizeof(extra), "%d %d", - (int)tx_rate, - (int)sta_ctx->ibss_peer_info. - peerInfoParams[0].rssi); - length = QDF_MIN(priv_data->total_len, length + 1); - - /* Copy the data back into buffer */ - if (copy_to_user(priv_data->buf, &extra, length)) { - hdd_err("copy data to user buffer failed GETIBSSPEERINFO command"); - ret = -EFAULT; - goto exit; - } - } else { - /* Command failed, log error */ - hdd_err("GETIBSSPEERINFO command failed with status code %d", - status); - ret = -EINVAL; - goto exit; - } - - /* Success ! */ - hdd_debug("%s", extra); - ret = 0; - -exit: - return ret; -} - -static int drv_cmd_set_ibss_tx_fail_event(struct hdd_adapter *adapter, - struct hdd_context *hdd_ctx, - uint8_t *command, - uint8_t command_len, - struct hdd_priv_data *priv_data) -{ - int ret = 0; - char *value; - uint8_t tx_fail_count = 0; - uint16_t pid = 0; - mac_handle_t mac_handle; - - value = command; - - ret = hdd_parse_ibsstx_fail_event_params(value, &tx_fail_count, &pid); - - if (0 != ret) { - hdd_err("Failed to parse SETIBSSTXFAILEVENT arguments"); - goto exit; - } - - hdd_debug("tx_fail_cnt=%hhu, pid=%hu", tx_fail_count, pid); - mac_handle = hdd_ctx->mac_handle; - - if (0 == tx_fail_count) { - /* Disable TX Fail Indication */ - if (QDF_STATUS_SUCCESS == - sme_tx_fail_monitor_start_stop_ind(mac_handle, - tx_fail_count, - NULL)) { - cesium_pid = 0; - } else { - hdd_err("failed to disable TX Fail Event"); - ret = -EINVAL; - } - } else { - if (QDF_STATUS_SUCCESS == - sme_tx_fail_monitor_start_stop_ind(mac_handle, - tx_fail_count, - (void *)hdd_tx_fail_ind_callback)) { - cesium_pid = pid; - hdd_debug("Registered Cesium pid %u", - cesium_pid); - } else { - hdd_err("Failed to enable TX Fail Monitoring"); - ret = -EINVAL; - } - } - -exit: - return ret; -} - #ifdef FEATURE_WLAN_ESE static int drv_cmd_set_ccx_roam_scan_channels(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx, diff --git a/core/hdd/src/wlan_hdd_ioctl.h b/core/hdd/src/wlan_hdd_ioctl.h index f2e608f65b2c..5296724e4a0b 100644 --- a/core/hdd/src/wlan_hdd_ioctl.h +++ b/core/hdd/src/wlan_hdd_ioctl.h @@ -48,5 +48,25 @@ QDF_STATUS hdd_update_smps_antenna_mode(struct hdd_context *hdd_ctx, int mode); int hdd_set_antenna_mode(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx, int mode); +#ifdef QCA_IBSS_SUPPORT +/** + * hdd_get_ibss_peer_info_cb() - IBSS peer Info request callback + * @context: callback context (adapter supplied by caller) + * @peer_info: Peer info response + * + * This is an asynchronous callback function from SME when the peer info + * is received + * + * Return: 0 for success non-zero for failure + */ +void hdd_get_ibss_peer_info_cb(void *context, + tSirPeerInfoRspParams *peer_info); +#else +static inline void +hdd_get_ibss_peer_info_cb(void *context, + tSirPeerInfoRspParams *peer_info) +{ +} +#endif #endif /* end #if !defined(WLAN_HDD_IOCTL_H) */ diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index afccdc99639c..24af2fec551b 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1340,17 +1340,7 @@ bool wlan_hdd_validate_modules_state(struct hdd_context *hdd_ctx) return true; } -/** - * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA. - * @struct hdd_adapter Hdd adapter. - * - * This function sets the IBSS power save config parameters to WMA - * which will send it to firmware if FW supports IBSS power save - * before vdev start. - * - * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE - * on failure. - */ +#ifdef QCA_IBSS_SUPPORT QDF_STATUS hdd_set_ibss_power_save_params(struct hdd_adapter *adapter) { struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); @@ -1363,6 +1353,7 @@ QDF_STATUS hdd_set_ibss_power_save_params(struct hdd_adapter *adapter) return ucfg_mlme_ibss_power_save_setup(hdd_ctx->psoc, adapter->vdev_id); } +#endif #ifdef FEATURE_RUNTIME_PM /** diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 24fe6f765d6a..5115ae93e17d 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -3328,6 +3328,7 @@ int hdd_wlan_dump_stats(struct hdd_adapter *adapter, int value) return ret; } +#ifdef QCA_IBSS_SUPPORT /** * hdd_wlan_get_ibss_peer_info() - Print IBSS peer information * @adapter: Adapter upon which the IBSS client is active @@ -3432,6 +3433,37 @@ static QDF_STATUS hdd_wlan_get_ibss_peer_info_all(struct hdd_adapter *adapter) return status; } +#else +/** + * hdd_wlan_get_ibss_peer_info() - Print IBSS peer information + * @adapter: Adapter upon which the IBSS client is active + * @sta_id: Station index of the IBSS peer + * + * This function is dummy + * + * Return: QDF_STATUS_STATUS + */ +static inline QDF_STATUS +hdd_wlan_get_ibss_peer_info(struct hdd_adapter *adapter, + uint8_t sta_id) +{ + return QDF_STATUS_SUCCESS; +} + +/** + * hdd_wlan_get_ibss_peer_info_all() - Print all IBSS peers + * @adapter: Adapter upon which the IBSS clients are active + * + * This function is dummy + * + * Return: QDF_STATUS_STATUS + */ +static inline QDF_STATUS +hdd_wlan_get_ibss_peer_info_all(struct hdd_adapter *adapter) +{ + return QDF_STATUS_SUCCESS; +} +#endif /** * hdd_get_ldpc() - Get adapter LDPC