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__ */