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 1716caa948..fb5c339d5c 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 @@ -1606,6 +1606,20 @@ bool policy_mgr_is_sap_mandatory_channel_set(struct wlan_objmgr_psoc *psoc); bool policy_mgr_list_has_24GHz_channel(uint8_t *channel_list, uint32_t list_len); +/** + * policy_mgr_get_valid_chans_from_range() - get valid channel from given range + * @psoc: PSOC object information + * @ch_list: Pointer to the channel list + * @ch_cnt: Pointer to the length of the channel list + * @mode: Device mode + * + * Return: QDF_STATUS + */ +QDF_STATUS policy_mgr_get_valid_chans_from_range(struct wlan_objmgr_psoc *psoc, + uint8_t *ch_list, + uint32_t *ch_cnt, + enum policy_mgr_con_mode mode); + /** * policy_mgr_get_valid_chans() - Get the valid channel list * @psoc: PSOC object information diff --git a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c index 5570b45626..83f59109a9 100644 --- a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c +++ b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c @@ -32,6 +32,7 @@ #include "qdf_trace.h" #include "wlan_objmgr_global_obj.h" #include "wlan_utility.h" +#include "wlan_mlme_ucfg_api.h" /** * first_connection_pcl_table - table which provides PCL for the @@ -328,6 +329,102 @@ uint8_t policy_mgr_get_channel(struct wlan_objmgr_psoc *psoc, return 0; } +/** + * policy_mgr_skip_dfs_ch() - skip dfs channel or not + * @psoc: pointer to soc + * @skip_dfs_channel: pointer to result + * + * Return: QDF_STATUS + */ +static QDF_STATUS policy_mgr_skip_dfs_ch(struct wlan_objmgr_psoc *psoc, + bool *skip_dfs_channel) +{ + bool sta_sap_scc_on_dfs_chan; + bool dfs_master_capable = true; + QDF_STATUS status; + + status = ucfg_mlme_get_dfs_master_capability(psoc, + &dfs_master_capable); + if (QDF_IS_STATUS_ERROR(status)) { + policy_mgr_err("failed to get dfs master capable"); + return status; + } + + *skip_dfs_channel = false; + if (!dfs_master_capable) { + policy_mgr_debug("skip DFS ch for SAP/Go dfs master cap %d", + dfs_master_capable); + *skip_dfs_channel = true; + } + + if (!*skip_dfs_channel) { + sta_sap_scc_on_dfs_chan = + policy_mgr_is_sta_sap_scc_allowed_on_dfs_chan(psoc); + if ((policy_mgr_mode_specific_connection_count(psoc, + PM_STA_MODE, + NULL) > 0) && + !sta_sap_scc_on_dfs_chan) { + policy_mgr_debug("SAP/Go skips DFS ch if sta connects"); + *skip_dfs_channel = true; + } + } + + return status; +} + +/** + * policy_mgr_modify_sap_pcl_based_on_dfs() - filter out DFS channel if needed + * @psoc: pointer to soc + * @pcl_list_org: channel list to filter out + * @weight_list_org: weight of channel list + * @pcl_len_org: length of channel list + * + * Return: QDF_STATUS + */ +static QDF_STATUS policy_mgr_modify_sap_pcl_based_on_dfs( + struct wlan_objmgr_psoc *psoc, + uint8_t *pcl_list_org, + uint8_t *weight_list_org, + uint32_t *pcl_len_org) +{ + size_t i, pcl_len = 0; + struct policy_mgr_psoc_priv_obj *pm_ctx; + bool skip_dfs_channel = false; + QDF_STATUS status; + + pm_ctx = policy_mgr_get_context(psoc); + if (!pm_ctx) { + policy_mgr_err("Invalid Context"); + return QDF_STATUS_E_FAILURE; + } + if (*pcl_len_org > QDF_MAX_NUM_CHAN) { + policy_mgr_err("Invalid PCL List Length %d", *pcl_len_org); + return QDF_STATUS_E_FAILURE; + } + + status = policy_mgr_skip_dfs_ch(psoc, &skip_dfs_channel); + if (QDF_IS_STATUS_ERROR(status)) { + policy_mgr_err("failed to get dfs channel skip info"); + return status; + } + + if (!skip_dfs_channel) { + policy_mgr_debug("No more operation on DFS channel"); + return QDF_STATUS_SUCCESS; + } + + for (i = 0; i < *pcl_len_org; i++) { + if (!wlan_reg_is_dfs_ch(pm_ctx->pdev, pcl_list_org[i])) { + pcl_list_org[pcl_len] = pcl_list_org[i]; + weight_list_org[pcl_len++] = weight_list_org[i]; + } + } + + *pcl_len_org = pcl_len; + + return QDF_STATUS_SUCCESS; +} + static QDF_STATUS policy_mgr_modify_sap_pcl_based_on_nol( struct wlan_objmgr_psoc *psoc, uint8_t *pcl_list_org, @@ -421,10 +518,11 @@ static QDF_STATUS policy_mgr_pcl_modification_for_sap( status = policy_mgr_modify_sap_pcl_based_on_mandatory_channel( psoc, pcl_channels, pcl_weight, len); if (QDF_IS_STATUS_ERROR(status)) { - policy_mgr_err("failed to get modified pcl for SAP"); + policy_mgr_err( + "failed to get mandatory modified pcl for SAP"); return status; } - policy_mgr_debug("modified pcl len:%d", *len); + policy_mgr_debug("mandatory modified pcl len:%d", *len); for (i = 0; i < *len; i++) policy_mgr_debug("chan:%d weight:%d", pcl_channels[i], pcl_weight[i]); @@ -433,18 +531,29 @@ static QDF_STATUS policy_mgr_pcl_modification_for_sap( status = policy_mgr_modify_sap_pcl_based_on_nol( psoc, pcl_channels, pcl_weight, len); if (QDF_IS_STATUS_ERROR(status)) { - policy_mgr_err("failed to get modified pcl for SAP"); + policy_mgr_err("failed to get nol modified pcl for SAP"); return status; } - policy_mgr_debug("modified pcl len:%d", *len); + policy_mgr_debug("nol modified pcl len:%d", *len); for (i = 0; i < *len; i++) policy_mgr_debug("chan:%d weight:%d", pcl_channels[i], pcl_weight[i]); + status = policy_mgr_modify_sap_pcl_based_on_dfs( + psoc, pcl_channels, pcl_weight, len); + if (QDF_IS_STATUS_ERROR(status)) { + policy_mgr_err("failed to get dfs modified pcl for SAP"); + return status; + } + policy_mgr_debug("dfs modified pcl len:%d", *len); + for (i = 0; i < *len; i++) + policy_mgr_debug("chan:%d weight:%d", + pcl_channels[i], pcl_weight[i]); + status = policy_mgr_modify_sap_pcl_based_on_srd (psoc, pcl_channels, pcl_weight, len); if (QDF_IS_STATUS_ERROR(status)) { - policy_mgr_err("failed to get modified pcl for SAP"); + policy_mgr_err("failed to get srd modified pcl for SAP"); return status; } policy_mgr_debug("modified final pcl len:%d", *len); @@ -1545,6 +1654,51 @@ static void policy_mgr_remove_dsrc_channels(uint8_t *chan_list, *num_channels = num_chan_temp; } +QDF_STATUS policy_mgr_get_valid_chans_from_range(struct wlan_objmgr_psoc *psoc, + uint8_t *ch_list, + uint32_t *ch_cnt, + enum policy_mgr_con_mode mode) +{ + uint8_t ch_weight_list[QDF_MAX_NUM_CHAN] = {0}; + uint32_t ch_weight_len; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + size_t chan_index = 0; + + if (!ch_list || !ch_cnt) { + policy_mgr_err("NULL parameters"); + return QDF_STATUS_E_FAILURE; + } + + for (chan_index = 0; chan_index < *ch_cnt; chan_index++) + ch_weight_list[chan_index] = WEIGHT_OF_GROUP1_PCL_CHANNELS; + + ch_weight_len = *ch_cnt; + + /* check the channel avoidance list for beaconing entities */ + if (mode == PM_SAP_MODE || mode == PM_P2P_GO_MODE) + policy_mgr_update_with_safe_channel_list(psoc, ch_list, + ch_cnt, ch_weight_list, + ch_weight_len); + + status = policy_mgr_mode_specific_modification_on_pcl( + psoc, ch_list, ch_weight_list, ch_cnt, mode); + + if (QDF_IS_STATUS_ERROR(status)) { + policy_mgr_err("failed to get modified pcl for mode %d", mode); + return status; + } + + status = policy_mgr_modify_pcl_based_on_dnbs(psoc, ch_list, + ch_weight_list, ch_cnt); + + if (QDF_IS_STATUS_ERROR(status)) { + policy_mgr_err("failed to get modified pcl based on DNBS"); + return status; + } + + return status; +} + QDF_STATUS policy_mgr_get_valid_chans(struct wlan_objmgr_psoc *psoc, uint8_t *chan_list, uint32_t *list_len) { diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 8e4989f08b..c99f2b4c38 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -8546,63 +8546,6 @@ static void hdd_set_thermal_level_cb(hdd_handle_t hdd_handle, u_int8_t level) /* restore original concurrency mode */ ucfg_ipa_send_mcc_scc_msg(hdd_ctx->pdev, hdd_ctx->mcc_mode); } - -/** - * hdd_get_safe_channel() - Get safe channel from current regulatory - * @hdd_ctx: pointer to hdd context - * @adapter: pointer to softap adapter - * - * This function is used to get safe channel from current regulatory valid - * channels to restart SAP if failed to get safe channel from PCL. - * - * Return: Channel number to restart SAP in case of success. In case of any - * failure, the channel number returned is zero. - */ -static uint8_t -hdd_get_safe_channel(struct hdd_context *hdd_ctx, - struct hdd_adapter *adapter) -{ - struct sir_pcl_list pcl = {0}; - uint32_t i, j; - bool found = false; - int ret; - - /* Try for safe channel from all valid channel */ - pcl.pcl_len = MAX_NUM_CHAN; - ret = hdd_get_valid_chan(hdd_ctx, pcl.pcl_list, - &pcl.pcl_len); - if (ret) { - hdd_err("error %d in getting valid channel list", ret); - return INVALID_CHANNEL_ID; - } - - for (i = 0; i < pcl.pcl_len; i++) { - hdd_debug("chan[%d]:%d", i, pcl.pcl_list[i]); - found = false; - for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) { - if (pcl.pcl_list[i] == - hdd_ctx->unsafe_channel_list[j]) { - hdd_debug("unsafe chan:%d", pcl.pcl_list[i]); - found = true; - break; - } - } - - if (found) - continue; - - if ((pcl.pcl_list[i] >= - adapter->session.ap.sap_config.acs_cfg.start_ch) && - (pcl.pcl_list[i] <= - adapter->session.ap.sap_config.acs_cfg.end_ch)) { - hdd_debug("found safe chan:%d", pcl.pcl_list[i]); - return pcl.pcl_list[i]; - } - } - - return INVALID_CHANNEL_ID; -} - #else /** * hdd_set_thermal_level_cb() - set thermal level callback function @@ -8617,97 +8560,8 @@ hdd_get_safe_channel(struct hdd_context *hdd_ctx, static void hdd_set_thermal_level_cb(hdd_handle_t hdd_handle, u_int8_t level) { } - -/** - * hdd_get_safe_channel() - Get safe channel from current regulatory - * @hdd_ctx: pointer to hdd context - * @adapter: pointer to softap adapter - * - * This function is used to get safe channel from current regulatory valid - * channels to restart SAP if failed to get safe channel from PCL. - * - * Return: Channel number to restart SAP in case of success. In case of any - * failure, the channel number returned is zero. - */ -static uint8_t -hdd_get_safe_channel(struct hdd_context *hdd_ctx, - struct hdd_adapter *adapter) -{ - return 0; -} #endif -/** - * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP - * restart - * @adapter: AP adapter, which should be checked for NULL - * - * Get a safe channel to restart SAP. PCL already takes into account the - * unsafe channels. So, the PCL is validated with the ACS range to provide - * a safe channel for the SAP to restart. - * - * Return: Channel number to restart SAP in case of success. In case of any - * failure, the channel number returned is zero. - */ -static uint8_t -hdd_get_safe_channel_from_pcl_and_acs_range(struct hdd_adapter *adapter) -{ - struct sir_pcl_list pcl; - QDF_STATUS status; - uint32_t i; - mac_handle_t mac_handle; - struct hdd_context *hdd_ctx; - - hdd_ctx = WLAN_HDD_GET_CTX(adapter); - if (!hdd_ctx) { - hdd_err("invalid HDD context"); - return INVALID_CHANNEL_ID; - } - - mac_handle = hdd_ctx->mac_handle; - if (!mac_handle) { - hdd_err("invalid MAC handle"); - return INVALID_CHANNEL_ID; - } - - status = policy_mgr_get_pcl_for_existing_conn(hdd_ctx->psoc, - PM_SAP_MODE, pcl.pcl_list, &pcl.pcl_len, - pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list), - false); - if (QDF_IS_STATUS_ERROR(status)) { - hdd_err("Get PCL failed"); - return INVALID_CHANNEL_ID; - } - - /* - * In some scenarios, like hw dbs disabled, sap+sap case, if operating - * channel is unsafe channel, the pcl may be empty, instead of return, - * try to choose a safe channel from acs range. - */ - if (!pcl.pcl_len) - hdd_debug("pcl length is zero!"); - - hdd_debug("start:%d end:%d", - adapter->session.ap.sap_config.acs_cfg.start_ch, - adapter->session.ap.sap_config.acs_cfg.end_ch); - - /* PCL already takes unsafe channel into account */ - for (i = 0; i < pcl.pcl_len; i++) { - hdd_debug("chan[%d]:%d", i, pcl.pcl_list[i]); - if ((pcl.pcl_list[i] >= - adapter->session.ap.sap_config.acs_cfg.start_ch) && - (pcl.pcl_list[i] <= - adapter->session.ap.sap_config.acs_cfg.end_ch)) { - hdd_debug("found PCL safe chan:%d", pcl.pcl_list[i]); - return pcl.pcl_list[i]; - } - } - - hdd_debug("no safe channel from PCL found in ACS range"); - - return hdd_get_safe_channel(hdd_ctx, adapter); -} - /** * hdd_switch_sap_channel() - Move SAP to the given channel * @adapter: AP adapter @@ -8866,8 +8720,8 @@ void hdd_unsafe_channel_restart_sap(struct hdd_context *hdd_ctxt) continue; } else restart_chan = - hdd_get_safe_channel_from_pcl_and_acs_range( - adapter); + wlansap_get_safe_channel_from_pcl_and_acs_range( + WLAN_HDD_GET_SAP_CTX_PTR(adapter)); if (!restart_chan) { hdd_err("fail to restart SAP"); } else { @@ -8934,7 +8788,8 @@ static void hdd_lte_coex_restart_sap(struct hdd_adapter *adapter, { uint8_t restart_chan; - restart_chan = hdd_get_safe_channel_from_pcl_and_acs_range(adapter); + restart_chan = wlansap_get_safe_channel_from_pcl_and_acs_range( + WLAN_HDD_GET_SAP_CTX_PTR(adapter)); if (!restart_chan) { hdd_alert("fail to restart SAP"); return; @@ -14904,7 +14759,8 @@ void hdd_check_and_restart_sap_with_non_dfs_acs(void) hdd_warn("STA-AP Mode DFS not supported, Switch SAP channel to Non DFS"); restart_chan = - hdd_get_safe_channel_from_pcl_and_acs_range(ap_adapter); + wlansap_get_safe_channel_from_pcl_and_acs_range( + WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter)); if (!restart_chan || wlan_reg_is_dfs_ch(hdd_ctx->pdev, restart_chan)) restart_chan = SAP_DEFAULT_5GHZ_CHANNEL; diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h index 5dea9b6a35..91ad3c693a 100644 --- a/core/sap/inc/sap_api.h +++ b/core/sap/inc/sap_api.h @@ -1375,6 +1375,32 @@ QDF_STATUS wlansap_update_owe_info(struct sap_context *sap_ctx, uint8_t *peer, const uint8_t *ie, uint32_t ie_len, uint16_t owe_status); +/** + * wlansap_filter_ch_based_acs() -filter out channel based on acs + * @sap_ctx: sap context + * @ch_list: pointer to channel list + * @ch_cnt: channel number of channel list + * + * Return: QDF_STATUS + */ +QDF_STATUS wlansap_filter_ch_based_acs(struct sap_context *sap_ctx, + uint8_t *ch_list, + uint32_t *ch_cnt); + +/** + * wlansap_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP + * restart + * @sap_ctx: sap context + * + * Get a safe channel to restart SAP. PCL already takes into account the + * unsafe channels. So, the PCL is validated with the ACS range to provide + * a safe channel for the SAP to restart. + * + * Return: Channel number to restart SAP in case of success. In case of any + * failure, the channel number returned is zero. + */ +uint8_t +wlansap_get_safe_channel_from_pcl_and_acs_range(struct sap_context *sap_ctx); #ifdef __cplusplus } #endif diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index d80b90933f..b01ad625f6 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -2690,3 +2690,167 @@ QDF_STATUS wlansap_update_owe_info(struct sap_context *sap_ctx, return status; } + +QDF_STATUS wlansap_filter_ch_based_acs(struct sap_context *sap_ctx, + uint8_t *ch_list, + uint32_t *ch_cnt) +{ + size_t ch_index; + size_t target_ch_cnt = 0; + + if (!sap_ctx || !ch_list || !ch_cnt) { + sap_err("NULL parameters"); + return QDF_STATUS_E_FAULT; + } + + for (ch_index = 0; ch_index < *ch_cnt; ch_index++) { + if (ch_list[ch_index] >= sap_ctx->acs_cfg->start_ch && + ch_list[ch_index] <= sap_ctx->acs_cfg->end_ch) + ch_list[target_ch_cnt++] = ch_list[ch_index]; + } + + *ch_cnt = target_ch_cnt; + + return QDF_STATUS_SUCCESS; +} + +#if defined(FEATURE_WLAN_CH_AVOID) +/** + * wlansap_get_safe_channel() - Get safe channel from current regulatory + * @sap_ctx: Pointer to SAP context + * + * This function is used to get safe channel from current regulatory valid + * channels to restart SAP if failed to get safe channel from PCL. + * + * Return: Channel number to restart SAP in case of success. In case of any + * failure, the channel number returned is zero. + */ +static uint8_t +wlansap_get_safe_channel(struct sap_context *sap_ctx) +{ + struct mac_context *mac; + struct sir_pcl_list pcl = {0}; + QDF_STATUS status; + mac_handle_t mac_handle; + + if (!sap_ctx) { + sap_err("NULL parameter"); + return INVALID_CHANNEL_ID; + } + + mac = sap_get_mac_context(); + if (!mac) { + sap_err("Invalid MAC context"); + return INVALID_CHANNEL_ID; + } + mac_handle = MAC_HANDLE(mac); + + /* get the channel list for current domain */ + status = policy_mgr_get_valid_chans(mac->psoc, + pcl.pcl_list, + &pcl.pcl_len); + if (QDF_IS_STATUS_ERROR(status)) { + sap_err("Error in getting valid channels"); + return INVALID_CHANNEL_ID; + } + + status = wlansap_filter_ch_based_acs(sap_ctx, + pcl.pcl_list, + &pcl.pcl_len); + if (QDF_IS_STATUS_ERROR(status)) { + sap_err("failed to filter ch from acs %d", status); + return INVALID_CHANNEL_ID; + } + + if (pcl.pcl_len) { + status = policy_mgr_get_valid_chans_from_range(mac->psoc, + pcl.pcl_list, + &pcl.pcl_len, + PM_SAP_MODE); + if (QDF_IS_STATUS_ERROR(status)) { + sap_err("failed to get valid channel: %d", status); + return INVALID_CHANNEL_ID; + } + + if (pcl.pcl_len) { + sap_debug("select %d from valid channel list", + pcl.pcl_list[0]); + return pcl.pcl_list[0]; + } + } + + return INVALID_CHANNEL_ID; +} +#else +/** + * wlansap_get_safe_channel() - Get safe channel from current regulatory + * @sap_ctx: Pointer to SAP context + * + * This function is used to get safe channel from current regulatory valid + * channels to restart SAP if failed to get safe channel from PCL. + * + * Return: Channel number to restart SAP in case of success. In case of any + * failure, the channel number returned is zero. + */ +static uint8_t +wlansap_get_safe_channel(struct sap_context *sap_ctx) +{ + return 0; +} +#endif + +uint8_t +wlansap_get_safe_channel_from_pcl_and_acs_range(struct sap_context *sap_ctx) +{ + struct mac_context *mac; + struct sir_pcl_list pcl = {0}; + QDF_STATUS status; + mac_handle_t mac_handle; + + if (!sap_ctx) { + sap_err("NULL parameter"); + return INVALID_CHANNEL_ID; + } + + mac = sap_get_mac_context(); + if (!mac) { + sap_err("Invalid MAC context"); + return INVALID_CHANNEL_ID; + } + mac_handle = MAC_HANDLE(mac); + + status = policy_mgr_get_pcl_for_existing_conn( + mac->psoc, PM_SAP_MODE, pcl.pcl_list, &pcl.pcl_len, + pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list), + false); + if (QDF_IS_STATUS_ERROR(status)) { + sap_err("Get PCL failed"); + return INVALID_CHANNEL_ID; + } + + if (pcl.pcl_len) { + status = wlansap_filter_ch_based_acs(sap_ctx, + pcl.pcl_list, + &pcl.pcl_len); + if (QDF_IS_STATUS_ERROR(status)) { + sap_err("failed to filter ch from acs %d", status); + return INVALID_CHANNEL_ID; + } + + if (pcl.pcl_len) { + sap_debug("select %d from valid channel list", + pcl.pcl_list[0]); + return pcl.pcl_list[0]; + } + sap_debug("no safe channel from PCL found in ACS range"); + } else { + sap_debug("pcl length is zero!"); + } + + /* + * In some scenarios, like hw dbs disabled, sap+sap case, if operating + * channel is unsafe channel, the pcl may be empty, instead of return, + * try to choose a safe channel from acs range. + */ + return wlansap_get_safe_channel(sap_ctx); +}