diff --git a/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h b/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h index f26e3b4c3a28..aa5987cf5458 100644 --- a/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h +++ b/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h @@ -990,6 +990,23 @@ policy_mgr_current_connections_update(struct wlan_objmgr_psoc *psoc, enum policy_mgr_conn_update_reason, uint32_t request_id); +/** + * policy_mgr_change_hw_mode_sta_connect() - Change HW mode for STA connect + * @psoc: psoc object + * @scan_list: candidates for conenction + * @vdev_id: vdev id for STA/CLI + * @connect_id: connect id of the conenct request + * + * When a new connection is about to come up, change hw mode for STA/CLI + * based upon the scan results and hw type. + * + * Return: status ifset HW mode is fail or already taken care of. + */ +QDF_STATUS +policy_mgr_change_hw_mode_sta_connect(struct wlan_objmgr_psoc *psoc, + qdf_list_t *scan_list, uint8_t vdev_id, + uint32_t connect_id); + /** * policy_mgr_is_dbs_allowed_for_concurrency() - If dbs is allowed for current * concurreny diff --git a/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h b/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h index 82281bd14f4e..f272a5c0062f 100644 --- a/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h +++ b/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h @@ -905,6 +905,7 @@ enum policy_mgr_band { * to the other DBS mode. This reason code indicates such condition. * @POLICY_MGR_UPDATE_REASON_NAN_DISCOVERY: NAN Discovery related * @POLICY_MGR_UPDATE_REASON_NDP_UPDATE: NAN Datapath related update + * @POLICY_MGR_UPDATE_REASON_STA_CONNECT: STA/CLI connection to peer */ enum policy_mgr_conn_update_reason { POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN, @@ -922,6 +923,7 @@ enum policy_mgr_conn_update_reason { POLICY_MGR_UPDATE_REASON_NAN_DISCOVERY, POLICY_MGR_UPDATE_REASON_NDP_UPDATE, POLICY_MGR_UPDATE_REASON_LFR2_ROAM, + POLICY_MGR_UPDATE_REASON_STA_CONNECT, }; /** diff --git a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c index e7396070205f..7a105caecdea 100644 --- a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c +++ b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c @@ -907,6 +907,116 @@ policy_mgr_get_next_action(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } +static bool +policy_mgr_is_hw_mode_change_required(struct wlan_objmgr_psoc *psoc, + uint32_t ch_freq, uint8_t vdev_id) +{ + if (policy_mgr_is_hw_dbs_required_for_band(psoc, HW_MODE_MAC_BAND_2G)) { + if (WLAN_REG_IS_24GHZ_CH_FREQ(ch_freq)) + return true; + } else { + if (WLAN_REG_IS_24GHZ_CH_FREQ(ch_freq) && + policy_mgr_is_any_mode_active_on_band_along_with_session + (psoc, vdev_id, POLICY_MGR_BAND_5)) + return true; + + if (WLAN_REG_IS_5GHZ_CH_FREQ(ch_freq) && + policy_mgr_is_any_mode_active_on_band_along_with_session + (psoc, vdev_id, POLICY_MGR_BAND_24)) + return true; + } + + return false; +} + +static uint32_t +policy_mgr_check_for_hw_mode_change(struct wlan_objmgr_psoc *psoc, + qdf_list_t *scan_list, uint8_t vdev_id) +{ + + struct scan_cache_node *scan_node = NULL; + qdf_list_node_t *cur_node = NULL, *next_node = NULL; + uint32_t ch_freq = 0; + struct scan_cache_entry *entry; + + if (!scan_list || !qdf_list_size(scan_list)) { + policy_mgr_debug("Scan list is NULL or No BSSIDs present"); + goto end; + } + + if (!policy_mgr_is_hw_dbs_capable(psoc)) { + policy_mgr_debug("Driver isn't DBS capable"); + goto end; + } + + if (!policy_mgr_is_dbs_allowed_for_concurrency(psoc, QDF_STA_MODE)) { + policy_mgr_debug("DBS not allowed for concurrency combo"); + goto end; + } + + if (!policy_mgr_is_hw_dbs_2x2_capable(psoc) && + !policy_mgr_is_hw_dbs_required_for_band(psoc, + HW_MODE_MAC_BAND_2G) && + !policy_mgr_get_connection_count(psoc)) { + policy_mgr_debug("1x1 DBS with no existing connection, HW mode change not required"); + goto end; + } + + qdf_list_peek_front(scan_list, &cur_node); + + while (cur_node) { + qdf_list_peek_next(scan_list, cur_node, &next_node); + + scan_node = qdf_container_of(cur_node, struct scan_cache_node, + node); + entry = scan_node->entry; + ch_freq = entry->channel.chan_freq; + + if (policy_mgr_is_hw_mode_change_required(psoc, ch_freq, + vdev_id)) { + policy_mgr_debug("Scan list has BSS of freq %d hw mode required", + ch_freq); + break; + } + + cur_node = next_node; + next_node = NULL; + } + +end: + return ch_freq; +} + +QDF_STATUS +policy_mgr_change_hw_mode_sta_connect(struct wlan_objmgr_psoc *psoc, + qdf_list_t *scan_list, uint8_t vdev_id, + uint32_t connect_id) +{ + QDF_STATUS status; + uint32_t ch_freq; + + ch_freq = policy_mgr_check_for_hw_mode_change(psoc, scan_list, vdev_id); + + if (!ch_freq) + return QDF_STATUS_E_ALREADY; + + status = policy_mgr_current_connections_update(psoc, vdev_id, ch_freq, + POLICY_MGR_UPDATE_REASON_STA_CONNECT, connect_id); + + /* + * If status is success then the callback of policy mgr hw mode change + * would be called. + * If status is no support then the DUT is already in required HW mode. + */ + + if (status == QDF_STATUS_E_FAILURE) + policy_mgr_err("Hw mode change failed"); + else if (status == QDF_STATUS_E_NOSUPPORT) + status = QDF_STATUS_E_ALREADY; + + return status; +} + QDF_STATUS policy_mgr_current_connections_update(struct wlan_objmgr_psoc *psoc, uint32_t session_id, uint32_t ch_freq, diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 5d9f231bc9a9..29b2bbd57c2f 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -67,6 +67,7 @@ #include "mac_init_api.h" #include "wlan_cm_roam_api.h" #include "wlan_cm_tgt_if_tx_api.h" +#include "wlan_cm_api.h" static QDF_STATUS init_sme_cmd_list(struct mac_context *mac); @@ -161,6 +162,7 @@ static QDF_STATUS sme_process_set_hw_mode_resp(struct mac_context *mac, uint8_t enum policy_mgr_conn_update_reason reason; struct csr_roam_session *session; uint32_t session_id; + uint32_t request_id; param = (struct sir_set_hw_mode_resp *)msg; if (!param) { @@ -190,6 +192,7 @@ static QDF_STATUS sme_process_set_hw_mode_resp(struct mac_context *mac, uint8_t callback = command->u.set_hw_mode_cmd.set_hw_mode_cb; reason = command->u.set_hw_mode_cmd.reason; session_id = command->u.set_hw_mode_cmd.session_id; + request_id = command->u.set_hw_mode_cmd.request_id; sme_debug("reason: %d session: %d", command->u.set_hw_mode_cmd.reason, @@ -257,6 +260,18 @@ static QDF_STATUS sme_process_set_hw_mode_resp(struct mac_context *mac, uint8_t if (reason == POLICY_MGR_UPDATE_REASON_LFR2_ROAM) csr_continue_lfr2_connect(mac, session_id); + if (reason == POLICY_MGR_UPDATE_REASON_STA_CONNECT) { + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + sme_info("Continue connect on vdev %d", session_id); + if (param->status == SET_HW_MODE_STATUS_OK || + param->status == SET_HW_MODE_STATUS_ALREADY) + status = QDF_STATUS_SUCCESS; + + wlan_cm_hw_mode_change_resp(mac->pdev, session_id, request_id, + status); + } + end: found = csr_nonscan_active_ll_remove_entry(mac, entry, LL_ACCESS_LOCK);