From 3f78053b879acc35dbac2fcecc24790a8524654c Mon Sep 17 00:00:00 2001 From: Tushnim Bhattacharyya Date: Wed, 1 Aug 2018 19:11:40 -0700 Subject: [PATCH] qcacld-3.0: Do HW mode change based on all the candidate APs for STA The driver currently changes the hw_mode based upon the first candidate found in the scan list, and tries to connect to it. It may happen that the connection fails, and the STA then tries to connect to the AP on same channel as the concurrent adapter. It would result in hw_mode = DBS, as it is not updated after connection success/failure. Also if the first AP channel is in same band as that of concurrent adapter, and the connection fails, and the STA tries to connect to an AP in a different band, this too is not allowed as hw_mode is not DBS Fix is to change the hw_mode based upon the scan list. If the driver finds any scan result which may lead to DBS connection, the hw_mode should be set to DBS. Once the connection is done or failed, the driver can check and update the hw_mode again. Change-Id: I42ffe0c63371e048771e2b9b00b887e9c6c65d6c CRs-Fixed: 2288572 --- core/hdd/src/wlan_hdd_assoc.c | 5 +- core/sme/src/csr/csr_api_roam.c | 9 ++- core/sme/src/csr/csr_api_scan.c | 92 +++++++++++++++++++++++++++++++ core/sme/src/csr/csr_inside_api.h | 21 ++++++- 4 files changed, 124 insertions(+), 3 deletions(-) diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index ab026f3b097a..08c6a25c1a54 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -3254,9 +3254,12 @@ hdd_association_completion_handler(struct hdd_adapter *adapter, hdd_debug("check for SAP restart"); policy_mgr_check_concurrent_intf_and_restart_sap( hdd_ctx->hdd_psoc); + policy_mgr_checkn_update_hw_mode_single_mac_mode + (hdd_ctx->hdd_psoc, roam_info->pBssDesc->channelId); } else { bool connect_timeout = false; - + /* do we need to change the HW mode */ + policy_mgr_check_n_start_opportunistic_timer(hdd_ctx->hdd_psoc); if (roam_info && roam_info->is_fils_connection && eCSR_ROAM_RESULT_SCAN_FOR_SSID_FAILURE == roamResult) qdf_copy_macaddr(&roam_info->bssid, diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 86032c54bd9e..849077a83da3 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -8820,6 +8820,7 @@ QDF_STATUS csr_roam_connect(tpAniSirGlobal pMac, uint32_t sessionId, bool fCallCallback = false; struct csr_roam_session *pSession = CSR_GET_SESSION(pMac, sessionId); tSirBssDescription *first_ap_profile; + uint8_t channel_id = 0; if (NULL == pSession) { sme_err("session does not exist for given sessionId: %d", @@ -8951,8 +8952,14 @@ QDF_STATUS csr_roam_connect(tpAniSirGlobal pMac, uint32_t sessionId, status = QDF_STATUS_E_INVAL; goto error; } + + channel_id = csr_get_channel_for_hw_mode_change + (pMac, hBSSList, sessionId); + if (!channel_id) + channel_id = first_ap_profile->channelId; + status = policy_mgr_handle_conc_multiport(pMac->psoc, - sessionId, first_ap_profile->channelId); + sessionId, channel_id); if ((QDF_IS_STATUS_SUCCESS(status)) && (!csr_wait_for_connection_update(pMac, true))) { sme_debug("conn update error"); diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index af8de7796ff0..194a04271439 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -2102,6 +2102,98 @@ csr_get_bssdescr_from_scan_handle(tScanResultHandle result_handle, return bss_descr; } +uint8_t +csr_get_channel_for_hw_mode_change(tpAniSirGlobal mac_ctx, + tScanResultHandle result_handle, + uint32_t session_id) +{ + tListElem *next_element = NULL; + struct tag_csrscan_result *scan_result = NULL; + struct scan_result_list *bss_list = + (struct scan_result_list *)result_handle; + uint8_t channel_id = 0; + + if (NULL == bss_list) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + FL("Empty bss_list")); + goto end; + } + + if (policy_mgr_is_hw_dbs_capable(mac_ctx->psoc) == false) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, + FL("driver isn't dbs capable")); + goto end; + } + + if (policy_mgr_is_current_hwmode_dbs(mac_ctx->psoc)) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, + FL("driver is already in DBS")); + goto end; + } + + if (!policy_mgr_is_dbs_allowed_for_concurrency(mac_ctx->psoc, + QDF_STA_MODE)) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, + FL("DBS is not allowed for this concurrency combo")); + goto end; + } + + if (!policy_mgr_is_hw_dbs_2x2_capable(mac_ctx->psoc) && + !policy_mgr_get_connection_count(mac_ctx->psoc)) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, + FL("1x1 DBS HW with no prior connection")); + goto end; + } + + if (csr_ll_is_list_empty(&bss_list->List, LL_ACCESS_NOLOCK)) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + FL("bss_list->List is empty")); + qdf_mem_free(bss_list); + goto end; + } + + next_element = csr_ll_peek_head(&bss_list->List, LL_ACCESS_NOLOCK); + while (next_element) { + scan_result = GET_BASE_ADDR(next_element, + struct tag_csrscan_result, + Link); + if (policy_mgr_is_hw_dbs_2x2_capable(mac_ctx->psoc)) { + if (WLAN_REG_IS_24GHZ_CH + (scan_result->Result.BssDescriptor.channelId)) { + channel_id = + scan_result-> + Result.BssDescriptor.channelId; + break; + } + } else { + if (WLAN_REG_IS_24GHZ_CH + (scan_result->Result.BssDescriptor.channelId) && + policy_mgr_is_any_mode_active_on_band_along_with_session + (mac_ctx->psoc, + session_id, POLICY_MGR_BAND_5)) { + channel_id = + scan_result-> + Result.BssDescriptor.channelId; + break; + } + if (WLAN_REG_IS_5GHZ_CH + (scan_result->Result.BssDescriptor.channelId) && + policy_mgr_is_any_mode_active_on_band_along_with_session + (mac_ctx->psoc, + session_id, POLICY_MGR_BAND_24)) { + channel_id = + scan_result-> + Result.BssDescriptor.channelId; + break; + } + } + next_element = csr_ll_next(&bss_list->List, next_element, + LL_ACCESS_NOLOCK); + } +end: + return channel_id; +} + static enum wlan_auth_type csr_covert_auth_type_new(eCsrAuthType auth) { switch (auth) { diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index de6206d5a69c..d7fa9d748140 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -1095,5 +1095,24 @@ static inline void csr_update_session_he_cap(tpAniSirGlobal mac_ctx, { } #endif - +/** + * csr_get_channel_for_hw_mode_change() - This function to find + * out if HW mode change + * is needed for any of + * the candidate AP which + * STA could join + * @mac_ctx: mac context + * @result_handle: an object for the result. + * @session_id: STA session ID + * + * This function is written to find out for any bss from scan + * handle a HW mode change to DBS will be needed or not. + * + * Return: AP channel for which DBS HW mode will be needed. 0 + * means no HW mode change is needed. + */ +uint8_t +csr_get_channel_for_hw_mode_change(tpAniSirGlobal mac_ctx, + tScanResultHandle result_handle, + uint32_t session_id); #endif /* CSR_INSIDE_API_H__ */