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 473b6b651a5f..a2da9ba87ad4 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 @@ -1774,6 +1774,19 @@ QDF_STATUS policy_mgr_set_hw_mode_on_channel_switch( QDF_STATUS policy_mgr_set_hw_mode_before_channel_switch( struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, uint8_t chan); +/** + * policy_mgr_check_and_set_hw_mode_sta_channel_switch() - check if hw mode + * change is required before channel switch for STA, + * this is required if DBS mode is 2x2 + * @psoc: PSOC object information + * @vdev_id: vdev id on which channel switch is required + * @chan: New channel to which channel switch is requested + * + * Return: QDF_STATUS, success if HW mode change is required else Failure + */ +QDF_STATUS policy_mgr_check_and_set_hw_mode_sta_channel_switch( + struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, uint8_t chan); + /** * policy_mgr_set_do_hw_mode_change_flag() - Set flag to indicate hw mode change * @psoc: PSOC object information 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 be74e940701d..605cb7c5b214 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 @@ -1944,6 +1944,47 @@ QDF_STATUS policy_mgr_set_hw_mode_before_channel_switch( return status; } +QDF_STATUS policy_mgr_check_and_set_hw_mode_sta_channel_switch( + struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, uint8_t chan) +{ + QDF_STATUS status; + struct policy_mgr_conc_connection_info info; + uint8_t num_cxn_del = 0; + + if (!policy_mgr_is_hw_dbs_capable(psoc) || + !policy_mgr_is_hw_dbs_2x2_capable(psoc)) { + policy_mgr_err("2x2 DBS is not enabled"); + return QDF_STATUS_E_NOSUPPORT; + } + + if (policy_mgr_is_current_hwmode_dbs(psoc)) { + policy_mgr_err("Already in DBS mode"); + return QDF_STATUS_E_ALREADY; + } + + if (!WLAN_CHAN_IS_2GHZ(chan)) { + policy_mgr_err("DBS is not required for 5Ghz chan"); + return QDF_STATUS_E_NOSUPPORT; + } + /* + * Store the connection's parameter and temporarily delete it + * from the concurrency table. This way the allow concurrency + * check can be used as though a new connection is coming up, + * after check, restore the connection to concurrency table. + */ + policy_mgr_store_and_del_conn_info_by_vdev_id(psoc, vdev_id, + &info, &num_cxn_del); + + status = policy_mgr_current_connections_update(psoc, vdev_id, chan, + POLICY_MGR_UPDATE_REASON_CHANNEL_SWITCH_STA); + + /* Restore the connection entry */ + if (num_cxn_del) + policy_mgr_restore_deleted_conn_info(psoc, &info, num_cxn_del); + + return status; +} + void policy_mgr_checkn_update_hw_mode_single_mac_mode( struct wlan_objmgr_psoc *psoc, uint8_t channel) { diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h index 80c586ca64d1..b0cbf1472666 100644 --- a/core/mac/inc/wni_api.h +++ b/core/mac/inc/wni_api.h @@ -236,7 +236,8 @@ enum eWniMsgTypes { /* To indicate Hidden ssid start complition to upper layer */ eWNI_SME_HIDDEN_SSID_RESTART_RSP = SIR_SME_MSG_TYPES_BEGIN + 151, eWNI_SME_FW_STATUS_IND = SIR_SME_MSG_TYPES_BEGIN + 152, - eWNI_SME_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 153 + eWNI_SME_STA_CSA_CONTINUE_REQ = SIR_SME_MSG_TYPES_BEGIN + 153, + eWNI_SME_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 154 }; typedef struct sAniCfgTxRateCtrs { diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c index b1d453ef6d7a..753daa00bf1f 100644 --- a/core/mac/src/pe/lim/lim_process_action_frame.c +++ b/core/mac/src/pe/lim/lim_process_action_frame.c @@ -72,6 +72,7 @@ static last_processed_msg rrm_link_action_frm; void lim_stop_tx_and_switch_channel(struct mac_context *mac, uint8_t sessionId) { struct pe_session *pe_session; + QDF_STATUS status; pe_session = pe_find_session_by_session_id(mac, sessionId); @@ -89,6 +90,13 @@ void lim_stop_tx_and_switch_channel(struct mac_context *mac, uint8_t sessionId) pe_session->gLimChannelSwitch.switchMode); mac->lim.limTimers.gLimChannelSwitchTimer.sessionId = sessionId; + status = policy_mgr_check_and_set_hw_mode_sta_channel_switch(mac->psoc, + pe_session->smeSessionId, + pe_session->gLimChannelSwitch.primaryChannel); + if (QDF_IS_STATUS_SUCCESS(status)) { + pe_info("Channel change will continue after HW mode change"); + return; + } /* change the channel immediately only if * the channel switch count is 0 */ diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index 883c713f4339..a43636111828 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -2075,6 +2075,9 @@ static void lim_process_messages(struct mac_context *mac_ctx, lim_send_csa_restart_req(mac_ctx, msg->bodyval); break; #endif + case eWNI_SME_STA_CSA_CONTINUE_REQ: + lim_continue_sta_csa_req(mac_ctx, msg->bodyval); + break; case WMA_SEND_BCN_RSP: lim_send_bcn_rsp(mac_ctx, (tpSendbeaconParams)msg->bodyptr); qdf_mem_free((void *)msg->bodyptr); diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 6a48f83d56d8..60641f28c6d9 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -6239,6 +6239,12 @@ void lim_send_csa_restart_req(struct mac_context *mac_ctx, uint8_t vdev_id) } #endif +void lim_continue_sta_csa_req(struct mac_context *mac_ctx, uint8_t vdev_id) +{ + pe_info("Continue CSA for STA vdev id %d", vdev_id); + lim_process_channel_switch_timeout(mac_ctx); +} + void lim_remove_duplicate_bssid_node(struct sir_rssi_disallow_lst *entry, qdf_list_t *list) { diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index f132a9fb3bd3..3d9c7e5edbd4 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -1056,6 +1056,15 @@ void lim_send_mgmt_frame_tx(struct mac_context *mac_ctx, */ void lim_send_csa_restart_req(struct mac_context *mac_ctx, uint8_t vdev_id); +/** + * lim_continue_sta_csa_req() - continue with CSA req after HW mode change + * @mac_ctx Pointer to Global MAC structure + * @vdev_id: vdev id + * + * Return: None + */ +void lim_continue_sta_csa_req(struct mac_context *mac_ctx, uint8_t vdev_id); + /** * lim_process_mlm_start_req() - process MLM_START_REQ message * diff --git a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c index 47465306764d..71fe945836ca 100644 --- a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c +++ b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c @@ -369,6 +369,7 @@ uint8_t *mac_trace_get_sme_msg_string(uint16_t sme_msg) CASE_RETURN_STRING(eWNI_SME_CSA_RESTART_RSP); CASE_RETURN_STRING(eWNI_SME_MSG_TYPES_END); CASE_RETURN_STRING(eWNI_SME_HIDDEN_SSID_RESTART_RSP); + CASE_RETURN_STRING(eWNI_SME_STA_CSA_CONTINUE_REQ); default: return (uint8_t *) "UNKNOWN"; break; diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index a8a3ee29c4ba..430aa3a6674c 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -210,6 +210,10 @@ static QDF_STATUS sme_process_set_hw_mode_resp(struct mac_context *mac, uint8_t } csr_saved_scan_cmd_free_fields(mac, session); } + if (reason == POLICY_MGR_UPDATE_REASON_CHANNEL_SWITCH_STA) { + sme_debug(" Continue channel switch for STA"); + csr_sta_continue_csa(mac, session_id); + } end: found = csr_nonscan_active_ll_remove_entry(mac, entry, diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 486fd0cf38d0..a993d26a82c6 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -20297,6 +20297,26 @@ QDF_STATUS csr_roam_send_chan_sw_ie_request(struct mac_context *mac_ctx, return status; } + +QDF_STATUS csr_sta_continue_csa(struct mac_context *mac_ctx, uint8_t vdev_id) +{ + QDF_STATUS status; + struct scheduler_msg message = {0}; + + /* Serialize the req through MC thread */ + message.bodyval = vdev_id; + message.type = eWNI_SME_STA_CSA_CONTINUE_REQ; + status = scheduler_post_message(QDF_MODULE_ID_SME, QDF_MODULE_ID_PE, + QDF_MODULE_ID_PE, &message); + if (!QDF_IS_STATUS_SUCCESS(status)) { + sme_err("eWNI_SME_STA_CSA_CONTINUE_REQ failed!(err=%d)", + status); + status = QDF_STATUS_E_FAILURE; + } + + return status; +} + #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR /** * csr_roaming_report_diag_event() - Diag events for LFR3 diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index b4ea0e504441..5445565085ef 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -852,6 +852,15 @@ QDF_STATUS csr_send_ext_change_channel(struct mac_context *mac_ctx, QDF_STATUS csr_csa_restart(struct mac_context *mac_ctx, uint8_t session_id); #endif +/** + * csr_sta_continue_csa() - Continue for CSA for STA after HW mode change + * @mac_ctx: handle returned by mac_open + * @vdev_id: STA VDEV ID + * + * Return: QDF_STATUS + */ +QDF_STATUS csr_sta_continue_csa(struct mac_context *mac_ctx, + uint8_t vdev_id); #ifdef QCA_HT_2040_COEX QDF_STATUS csr_set_ht2040_mode(struct mac_context *mac, uint32_t sessionId,