diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 14a01260702d..30425346521f 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1897,6 +1897,8 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel) int ret = 0; hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); hdd_context_t *pHddCtx = NULL; + hdd_adapter_t *sta_adapter; + hdd_station_ctx_t *sta_ctx; #ifndef WLAN_FEATURE_MBSSID v_CONTEXT_t p_cds_context = @@ -1910,6 +1912,21 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel) return ret; } + sta_adapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); + /* + * conc_custom_rule1: + * Force SCC for SAP + STA + * if STA is already connected then we shouldn't allow + * channel switch in SAP interface. + */ + if (sta_adapter && pHddCtx->config->conc_custom_rule1) { + sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(sta_adapter); + if (hdd_conn_is_connected(sta_ctx)) { + hdd_err("Channel switch not allowed after STA connection with conc_custom_rule1 enabled"); + return -EBUSY; + } + } + if (pHddCtx->dfs_radar_found == true) { hddLog(LOGE, FL("Channel switch in progress!!")); return -EBUSY; diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index b54f6563e4e0..dd4d05fd4ecf 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -598,6 +598,33 @@ void wlan_sap_set_vht_ch_width(void *ctx, uint32_t vht_channel_width) sap_ctx->ch_params.ch_width = vht_channel_width; } +/** + * wlan_sap_validate_channel_switch() - validate target channel switch w.r.t + * concurreny rules set to avoid channel interference. + * @hal - Hal context + * @sap_ch - channel to switch + * @sap_context - sap session context + * + * Return: true if there is no channel interference else return false + */ +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +static bool wlan_sap_validate_channel_switch(tHalHandle hal, uint16_t sap_ch, + ptSapContext sap_context) +{ + return sme_validate_sap_channel_switch( + hHal, + sap_ch, + sap_context->csr_roamProfile.phyMode, + sap_context->cc_switch_mode, + sap_context->sessionId); +} +#else +static inline bool wlan_sap_validate_channel_switch(tHalHandle hal, + uint16_t sap_ch, ptSapContext sap_context) +{ + return true; +} +#endif /** * wlansap_start_bss() - start BSS * @pCtx: Pointer to the global cds context; a handle to SAP's control block @@ -1399,6 +1426,8 @@ wlansap_set_channel_change_with_csa(void *p_cds_gctx, uint32_t targetChannel) tWLAN_SAPEvent sapEvent; tpAniSirGlobal pMac = NULL; void *hHal = NULL; + bool valid; + tSmeConfigParams *sme_config; sapContext = CDS_GET_SAP_CB(p_cds_gctx); if (NULL == sapContext) { @@ -1425,6 +1454,18 @@ wlansap_set_channel_change_with_csa(void *p_cds_gctx, uint32_t targetChannel) (cds_get_channel_state(targetChannel) == CHANNEL_STATE_DFS && !cds_concurrent_open_sessions_running()))) { + /* + * validate target channel switch w.r.t various concurrency + * rules set. + */ + valid = wlan_sap_validate_channel_switch(hHal, targetChannel, + sapContext); + if (!valid) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Channel switch to %u is not allowed due to concurrent channel interference"), + targetChannel); + return CDF_STATUS_E_FAULT; + } /* * Post a CSA IE request to SAP state machine with * target channel information and also CSA IE required @@ -1432,6 +1473,27 @@ wlansap_set_channel_change_with_csa(void *p_cds_gctx, uint32_t targetChannel) * state. */ if (eSAP_STARTED == sapContext->sapsMachine) { + /* + * currently OBSS scan is done in hostapd, so to avoid + * SAP coming up in HT40 on channel switch we are + * disabling channel bonding in 2.4Ghz. + */ + if (targetChannel <= RF_CHAN_14) { + sme_config = + cdf_mem_malloc(sizeof(*sme_config)); + if (!sme_config) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + FL("memory allocation failed for sme_config")); + return CDF_STATUS_E_NOMEM; + } + sme_get_config_param(pMac, sme_config); + sme_config->csrConfig.channelBondingMode24GHz = + eCSR_INI_SINGLE_CHANNEL_CENTERED; + sme_update_config(pMac, sme_config); + cdf_mem_free(sme_config); + } + /* * Copy the requested target channel * to sap context. diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index f335b0d99c57..aa8eba8c7185 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -990,6 +990,7 @@ typedef struct tagCsrRoamSession { /* This count represents the number of bssid's we try to join. */ uint8_t join_bssid_count; struct csr_roam_stored_profile stored_roam_profile; + bool ch_switch_in_progress; } tCsrRoamSession; typedef struct tagCsrRoamStruct { diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index b931dc43f43d..b80ae17a0ed6 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -1053,4 +1053,7 @@ void sme_add_set_thermal_level_callback(tHalHandle hal, sme_set_thermal_level_callback callback); void sme_update_tgt_services(tHalHandle hal, struct wma_tgt_services *cfg); +bool sme_validate_sap_channel_switch(tHalHandle hal, + uint16_t sap_ch, eCsrPhyMode sap_phy_mode, + uint8_t cc_switch_mode, uint8_t session_id); #endif /* #if !defined( __SME_API_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 4cfe7d661154..5ef7f247f385 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -13862,6 +13862,48 @@ CDF_STATUS sme_handle_dfs_chan_scan(tHalHandle h_hal, uint8_t dfs_flag) return status; } +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +/** + * sme_validate_sap_channel_switch() - validate target channel switch w.r.t + * concurreny rules set to avoid channel interference. + * @hal - Hal context + * @sap_ch - channel to switch + * @sap_phy_mode - phy mode of SAP + * @cc_switch_mode - concurreny switch mode + * @session_id - sme session id. + * + * Return: true if there is no channel interference else return false + */ +bool sme_validate_sap_channel_switch(tHalHandle hal, + uint16_t sap_ch, eCsrPhyMode sap_phy_mode, uint8_t cc_switch_mode, + uint8_t session_id) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + tCsrRoamSession *session = CSR_GET_SESSION(mac, session_id); + uint16_t intf_channel = 0; + + if (!session) + return false; + + session->ch_switch_in_progress = true; + status = sme_acquire_global_lock(&mac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + intf_channel = csr_check_concurrent_channel_overlap(mac, sap_ch, + sap_phy_mode, + cc_switch_mode); + sme_release_global_lock(&mac->sme); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("sme_acquire_global_lock error!")); + session->ch_switch_in_progress = false; + return false; + } + + session->ch_switch_in_progress = false; + return (intf_channel == 0) ? true : false; +} +#endif /** * sme_configure_stats_avg_factor() - function to config avg. stats factor diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index 42e351a91029..a6796d9adc92 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -704,6 +704,9 @@ uint16_t csr_check_concurrent_channel_overlap(tpAniSirGlobal mac_ctx, CDF_SAP_MODE)) && (session->connectState != eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED)) { + if (pSession->ch_switch_in_progress) + continue; + csr_handle_conc_chnl_overlap_for_sap_go(mac_ctx, session, &sap_ch, &sap_hbw, &sap_cfreq, &intf_ch, &intf_hbw, &intf_cfreq);