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 3392006141bb..abf54efc8467 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 @@ -76,6 +76,7 @@ typedef const enum policy_mgr_conc_next_action * @CSA_REASON_UNSAFE_CHANNEL: Unsafe channel. * @CSA_REASON_LTE_COEX: LTE coex. * @CSA_REASON_CONCURRENT_NAN_EVENT: NAN concurrency. + * @CSA_REASON_BAND_RESTRICTED: band disabled or re-enabled * */ enum sap_csa_reason_code { @@ -87,7 +88,8 @@ enum sap_csa_reason_code { CSA_REASON_CONCURRENT_STA_CHANGED_CHANNEL, CSA_REASON_UNSAFE_CHANNEL, CSA_REASON_LTE_COEX, - CSA_REASON_CONCURRENT_NAN_EVENT + CSA_REASON_CONCURRENT_NAN_EVENT, + CSA_REASON_BAND_RESTRICTED }; /** diff --git a/core/hdd/src/wlan_hdd_regulatory.c b/core/hdd/src/wlan_hdd_regulatory.c index 632e3392df6d..7150cf117429 100644 --- a/core/hdd/src/wlan_hdd_regulatory.c +++ b/core/hdd/src/wlan_hdd_regulatory.c @@ -1425,6 +1425,9 @@ static void hdd_regulatory_dyn_cbk(struct wlan_objmgr_psoc *psoc, struct hdd_context *hdd_ctx; enum country_src cc_src; uint8_t alpha2[REG_ALPHA2_LEN + 1]; + struct hdd_adapter *adapter = NULL; + struct hdd_ap_ctx *ap_ctx; + enum band_info current_band; pdev_priv = wlan_pdev_get_ospriv(pdev); wiphy = pdev_priv->wiphy; @@ -1456,6 +1459,21 @@ static void hdd_regulatory_dyn_cbk(struct wlan_objmgr_psoc *psoc, else sme_generic_change_country_code(hdd_ctx->mac_handle, hdd_ctx->reg.alpha2); + + if (ucfg_reg_get_curr_band(hdd_ctx->pdev, ¤t_band) != + QDF_STATUS_SUCCESS) { + hdd_err("Failed to get current band config"); + return; + } + hdd_for_each_adapter(hdd_ctx, adapter) { + ap_ctx = &adapter->session.ap; + if ((adapter->device_mode == QDF_SAP_MODE || + adapter->device_mode == QDF_P2P_GO_MODE)) { + wlansap_set_band_csa(ap_ctx->sap_context, + &ap_ctx->sap_config, + current_band); + } + } } int hdd_update_regulatory_config(struct hdd_context *hdd_ctx) diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h index be81f5543027..1605502efb66 100644 --- a/core/sap/inc/sap_api.h +++ b/core/sap/inc/sap_api.h @@ -1459,6 +1459,21 @@ QDF_STATUS wlansap_filter_ch_based_acs(struct sap_context *sap_ctx, */ uint32_t wlansap_get_safe_channel_from_pcl_and_acs_range(struct sap_context *sap_ctx); + +/** + * wlansap_set_band_csa() - sap channel switch for band change + * @sap_ctx: sap context pointer + * @sap_config: sap config pointer + * + * Sap/p2p go channel switch from 5G to 2G by CSA when 5G band disabled to + * avoid conflict with modem N79. + * Sap/p2p go channel restore to 5G when 5G band enabled. + * + * Return - none + */ +void wlansap_set_band_csa(struct sap_context *sap_ctx, + struct sap_config *sap_config, + enum band_info band); #ifdef __cplusplus } #endif diff --git a/core/sap/src/sap_internal.h b/core/sap/src/sap_internal.h index 3ccfc4f419a4..1b698984b764 100644 --- a/core/sap/src/sap_internal.h +++ b/core/sap/src/sap_internal.h @@ -171,7 +171,8 @@ struct sap_context { uint8_t num_of_channel; uint16_t ch_width_orig; struct ch_params ch_params; - + uint32_t chan_freq_before_switch_band; + enum phy_ch_width chan_width_before_switch_band; uint32_t auto_channel_select_weight; bool enableOverLapCh; struct sap_acs_cfg *acs_cfg; diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index 2798bbd26d20..266568b7337a 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -1358,6 +1358,8 @@ static char *sap_get_csa_reason_str(enum sap_csa_reason_code reason) return "LTE_COEX"; case CSA_REASON_CONCURRENT_NAN_EVENT: return "CONCURRENT_NAN_EVENT"; + case CSA_REASON_BAND_RESTRICTED: + return "BAND_RESTRICTED"; default: return "UNKNOWN"; } @@ -3090,3 +3092,119 @@ wlansap_get_safe_channel_from_pcl_and_acs_range(struct sap_context *sap_ctx) */ return wlansap_get_safe_channel(sap_ctx); } + +static uint32_t wlansap_get_2g_first_safe_chan_freq(struct sap_context *sap_ctx) +{ + uint32_t i; + uint32_t freq; + enum channel_state state; + struct regulatory_channel *cur_chan_list; + struct wlan_objmgr_pdev *pdev; + struct wlan_objmgr_psoc *psoc; + uint32_t *acs_freq_list; + uint8_t acs_list_count; + + pdev = sap_ctx->vdev->vdev_objmgr.wlan_pdev; + psoc = pdev->pdev_objmgr.wlan_psoc; + + cur_chan_list = qdf_mem_malloc(NUM_CHANNELS * + sizeof(struct regulatory_channel)); + if (!cur_chan_list) + return TWOG_CHAN_6_IN_MHZ; + + if (wlan_reg_get_current_chan_list(pdev, cur_chan_list) != + QDF_STATUS_SUCCESS) { + freq = TWOG_CHAN_6_IN_MHZ; + goto err; + } + + acs_freq_list = sap_ctx->acs_cfg->master_freq_list; + acs_list_count = sap_ctx->acs_cfg->master_ch_list_count; + for (i = 0; i < NUM_CHANNELS; i++) { + freq = cur_chan_list[i].center_freq; + state = wlan_reg_get_channel_state_for_freq(pdev, freq); + if (state != CHANNEL_STATE_DISABLE && + state != CHANNEL_STATE_INVALID && + wlan_reg_is_24ghz_ch_freq(freq) && + policy_mgr_is_safe_channel(psoc, freq) && + wlansap_is_channel_present_in_acs_list(freq, + acs_freq_list, + acs_list_count)) { + sap_debug("find a 2g channel: %d", freq); + goto err; + } + } + + freq = TWOG_CHAN_6_IN_MHZ; +err: + qdf_mem_free(cur_chan_list); + return freq; +} + +void wlansap_set_band_csa(struct sap_context *sap_ctx, + struct sap_config *sap_config, + enum band_info band) +{ + uint8_t restart_chan; + uint32_t restart_freq; + enum phy_ch_width restart_ch_width; + uint8_t intf_ch; + uint32_t phy_mode; + struct mac_context *mac; + uint8_t cc_mode; + uint8_t vdev_id; + enum reg_wifi_band sap_band; + + sap_band = wlan_reg_freq_to_band(sap_ctx->chan_freq); + sap_debug("SAP/Go current band: %d, pdev band capability: %d", + sap_band, band); + if (sap_band == REG_BAND_5G && band == BAND_2G) { + if (sap_ctx->chan_freq_before_switch_band == + sap_ctx->chan_freq) + return; + sap_ctx->chan_freq_before_switch_band = sap_ctx->chan_freq; + sap_ctx->chan_width_before_switch_band = + sap_ctx->ch_params.ch_width; + sap_debug("Save chan info before switch: %d, width: %d", + sap_ctx->chan_freq, sap_ctx->ch_params.ch_width); + restart_freq = wlansap_get_2g_first_safe_chan_freq(sap_ctx); + restart_ch_width = sap_ctx->ch_params.ch_width; + if (restart_ch_width > CH_WIDTH_40MHZ) { + sap_debug("set 40M when switch SAP to 2G"); + restart_ch_width = CH_WIDTH_40MHZ; + } + } else if (sap_band == REG_BAND_2G && + (band == BAND_ALL || band == BAND_5G)) { + if (sap_ctx->chan_freq_before_switch_band == 0) + return; + restart_freq = sap_ctx->chan_freq_before_switch_band; + restart_ch_width = sap_ctx->chan_width_before_switch_band; + sap_debug("Restore chan freq: %d, width: %d", + restart_freq, restart_ch_width); + sap_ctx->chan_freq_before_switch_band = 0; + sap_ctx->chan_width_before_switch_band = CH_WIDTH_INVALID; + + } else { + sap_debug("No need switch SAP/Go channel"); + return; + } + + mac = cds_get_context(QDF_MODULE_ID_PE); + restart_chan = wlan_reg_freq_to_chan(mac->pdev, restart_freq); + cc_mode = sap_ctx->cc_switch_mode; + phy_mode = sap_ctx->csr_roamProfile.phyMode; + intf_ch = sme_check_concurrent_channel_overlap(MAC_HANDLE(mac), + restart_freq, + phy_mode, + cc_mode); + if (intf_ch) + restart_chan = intf_ch; + sap_ctx->csa_reason = CSA_REASON_BAND_RESTRICTED; + vdev_id = sap_ctx->vdev->vdev_objmgr.vdev_id; + restart_freq = wlan_chan_to_freq(restart_chan); + sap_debug("vdev: %d, CSA target channel: %d, width: %d", + vdev_id, restart_freq, restart_ch_width); + policy_mgr_change_sap_channel_with_csa(mac->psoc, vdev_id, + restart_freq, + restart_ch_width, true); +} diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index c957b65eff3c..5f4f0bef52b7 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -21593,6 +21593,21 @@ static QDF_STATUS csr_process_roam_sync_callback(struct mac_context *mac_ctx, case SIR_ROAM_SYNCH_PROPAGATION: break; case SIR_ROAM_SYNCH_COMPLETE: + /* Handle one race condition that if candidate is already + *selected & FW has gone ahead with roaming or about to go + * ahead when set_band comes, it will be complicated for FW + * to stop the current roaming. Instead, host will check the + * roam sync to make sure the new AP is on 2G, or disconnect + * the AP. + */ + if (wlan_reg_is_disable_for_freq(mac_ctx->pdev, + roam_synch_data->chan_freq)) { + csr_roam_disconnect(mac_ctx, session_id, + eCSR_DISCONNECT_REASON_DEAUTH); + sme_debug("Roaming Failed for disabled channel or band"); + vdev_roam_params->roam_invoke_in_progress = false; + goto end; + } /* * Following operations need to be done once roam sync * completion is sent to FW, hence called here: