From bc4261fe8ca65cab5391bd5405fcb1274f5ff11c Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Thu, 14 Mar 2019 13:21:57 +0530 Subject: [PATCH] qcacld-3.0: Send HW mode change while switching STA channel in 2x2 DBS If DBS 2x2 mode is supported, to operate in 2.4Ghz the driver needs to be in DBS mode before vdev start/restart is sent on 2.4Ghz channel. If STA is connected to a 5Ghz channel and the PEER AP switch from 5Ghz to 2.4Ghz channel, it sends vdev restart without sending the HW mode change to firmware. Fix is to set HW mode before the initiating vdev restart if new channel is 2.4Ghz and 2x2 DBS is supported and current HW mode is not DBS Change-Id: I6dc57f37e155f0e29b17840e4e246de773f42b3e CRs-Fixed: 2419642 --- .../policy_mgr/inc/wlan_policy_mgr_api.h | 13 ++++++ .../policy_mgr/src/wlan_policy_mgr_action.c | 41 +++++++++++++++++++ core/mac/inc/wni_api.h | 3 +- .../mac/src/pe/lim/lim_process_action_frame.c | 8 ++++ .../src/pe/lim/lim_process_message_queue.c | 3 ++ .../src/pe/lim/lim_process_sme_req_messages.c | 6 +++ core/mac/src/pe/lim/lim_types.h | 9 ++++ .../src/sys/legacy/src/utils/src/mac_trace.c | 1 + core/sme/src/common/sme_api.c | 4 ++ core/sme/src/csr/csr_api_roam.c | 20 +++++++++ core/sme/src/csr/csr_inside_api.h | 9 ++++ 11 files changed, 116 insertions(+), 1 deletion(-) 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,