diff --git a/umac/regulatory/core/src/reg_utils.c b/umac/regulatory/core/src/reg_utils.c index 10dd2cb43c10..f05f4e306c96 100644 --- a/umac/regulatory/core/src/reg_utils.c +++ b/umac/regulatory/core/src/reg_utils.c @@ -373,15 +373,70 @@ QDF_STATUS reg_get_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, return QDF_STATUS_SUCCESS; } +static inline bool reg_is_state_allowed(enum channel_state chan_state) +{ + return !((chan_state == CHANNEL_STATE_INVALID) || + (chan_state == CHANNEL_STATE_DISABLE)); +} + #ifdef CONFIG_REG_CLIENT #ifdef CONFIG_BAND_6GHZ +/** + * reg_check_if_6g_pwr_type_supp_for_chan() - Check if 6 GHz power type is + * supported for the channel + * @pdev: Pointer to pdev + * @pwr_type: 6 GHz power type + * @chan_idx: Connection channel index + * + * Return: Return QDF_STATUS_SUCCESS if 6 GHz power type supported for + * the given channel, else return QDF_STATUS_E_FAILURE. + */ +static +QDF_STATUS reg_check_if_6g_pwr_type_supp_for_chan( + struct wlan_objmgr_pdev *pdev, + enum reg_6g_ap_type pwr_type, + enum channel_enum chan_idx) +{ + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + struct regulatory_channel *ch_info; + enum reg_6g_client_type client_type; + uint16_t ch_idx_6g; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!pdev_priv_obj) { + reg_err("pdev priv obj null"); + return QDF_STATUS_E_FAILURE; + } + + ch_idx_6g = reg_convert_enum_to_6g_idx(chan_idx); + if (ch_idx_6g >= NUM_6GHZ_CHANNELS) { + reg_err("Invalid channel"); + return QDF_STATUS_E_NOSUPPORT; + } + + if (QDF_IS_STATUS_ERROR(reg_get_cur_6g_client_type(pdev, &client_type))) + return QDF_STATUS_E_FAILURE; + + ch_info = &pdev_priv_obj->mas_chan_list_6g_client[pwr_type][client_type][ch_idx_6g]; + + if (reg_is_state_allowed(ch_info->state) && + !(ch_info->chan_flags & REGULATORY_CHAN_DISABLED)) + return QDF_STATUS_SUCCESS; + + reg_err("6 GHz power type = %d not supported by STA %d index %d", + pwr_type, client_type, ch_idx_6g); + return QDF_STATUS_E_NOSUPPORT; +} + QDF_STATUS reg_get_best_6g_power_type(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_pdev *pdev, enum reg_6g_ap_type *pwr_type_6g, - enum reg_6g_ap_type ap_pwr_type) + enum reg_6g_ap_type ap_pwr_type, + uint32_t chan_freq) { struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + enum channel_enum chan_idx = reg_get_chan_enum_for_freq(chan_freq); *pwr_type_6g = ap_pwr_type; pdev_priv_obj = reg_get_pdev_obj(pdev); @@ -390,14 +445,21 @@ reg_get_best_6g_power_type(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_E_FAILURE; } - if (pdev_priv_obj->reg_rules.num_of_6g_client_reg_rules[ap_pwr_type]) { + if (pdev_priv_obj->reg_rules.num_of_6g_client_reg_rules[ap_pwr_type] && + QDF_IS_STATUS_SUCCESS(reg_check_if_6g_pwr_type_supp_for_chan( + pdev, + ap_pwr_type, chan_idx))) { reg_debug("AP power type: %d , is supported by client", ap_pwr_type); return QDF_STATUS_SUCCESS; } if (ap_pwr_type == REG_INDOOR_AP) { - if (pdev_priv_obj->reg_rules.num_of_6g_client_reg_rules[REG_VERY_LOW_POWER_AP]) { + if (pdev_priv_obj->reg_rules.num_of_6g_client_reg_rules[REG_VERY_LOW_POWER_AP] && + QDF_IS_STATUS_SUCCESS( + reg_check_if_6g_pwr_type_supp_for_chan(pdev, + REG_VERY_LOW_POWER_AP, + chan_idx))) { *pwr_type_6g = REG_VERY_LOW_POWER_AP; reg_debug("AP power type = %d, selected power type = %d", ap_pwr_type, *pwr_type_6g); @@ -406,7 +468,11 @@ reg_get_best_6g_power_type(struct wlan_objmgr_psoc *psoc, goto no_support; } } else if (ap_pwr_type == REG_STANDARD_POWER_AP) { - if (pdev_priv_obj->reg_rules.num_of_6g_client_reg_rules[REG_VERY_LOW_POWER_AP]) { + if (pdev_priv_obj->reg_rules.num_of_6g_client_reg_rules[REG_VERY_LOW_POWER_AP] && + QDF_IS_STATUS_SUCCESS( + reg_check_if_6g_pwr_type_supp_for_chan(pdev, + REG_VERY_LOW_POWER_AP, + chan_idx))) { *pwr_type_6g = REG_VERY_LOW_POWER_AP; reg_debug("AP power type = %d, selected power type = %d", ap_pwr_type, *pwr_type_6g); @@ -425,7 +491,8 @@ QDF_STATUS reg_get_best_6g_power_type(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_pdev *pdev, enum reg_6g_ap_type *pwr_type_6g, - enum reg_6g_ap_type ap_pwr_type) + enum reg_6g_ap_type ap_pwr_type, + uint32_t chan_freq) { return QDF_STATUS_SUCCESS; } diff --git a/umac/regulatory/core/src/reg_utils.h b/umac/regulatory/core/src/reg_utils.h index 4e26b3cfb64f..7a44506fa4c8 100644 --- a/umac/regulatory/core/src/reg_utils.h +++ b/umac/regulatory/core/src/reg_utils.h @@ -304,6 +304,7 @@ QDF_STATUS reg_get_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, * @pdev: pointer to pdev * @pwr_type_6g: ptr to 6G power type * @ap_pwr_type: AP's power type as advertised in HE ops IE + * @chan_freq: Connection channel frequency * * This function computes best power type for 6 GHz connection. * SP power type is selected only if AP advertises SP and client supports SP. @@ -319,7 +320,8 @@ QDF_STATUS reg_get_best_6g_power_type(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_pdev *pdev, enum reg_6g_ap_type *pwr_type_6g, - enum reg_6g_ap_type ap_pwr_type); + enum reg_6g_ap_type ap_pwr_type, + uint32_t chan_freq); #endif /** diff --git a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h index 2e67a4b432e2..d8c7ad95a133 100644 --- a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h +++ b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h @@ -551,13 +551,15 @@ QDF_STATUS wlan_reg_read_current_country(struct wlan_objmgr_psoc *psoc, * @pwr_type_6g: ptr to 6G power type * @ctry_code_match: Check for country IE and sta country code match * @ap_pwr_type: AP's power type for 6G as advertised in HE ops IE + * @chan_freq: Connection channel frequency * Return: QDF_STATUS */ QDF_STATUS wlan_reg_get_best_6g_power_type(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_pdev *pdev, enum reg_6g_ap_type *pwr_type_6g, - enum reg_6g_ap_type ap_pwr_type); + enum reg_6g_ap_type ap_pwr_type, + uint32_t chan_freq); #endif #ifdef CONFIG_CHAN_NUM_API diff --git a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c index 326b8cb92cb5..2b720dee6ca6 100644 --- a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c +++ b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c @@ -90,10 +90,11 @@ QDF_STATUS wlan_reg_get_best_6g_power_type(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_pdev *pdev, enum reg_6g_ap_type *pwr_type_6g, - enum reg_6g_ap_type ap_pwr_type) + enum reg_6g_ap_type ap_pwr_type, + uint32_t chan_freq) { return reg_get_best_6g_power_type(psoc, pdev, pwr_type_6g, - ap_pwr_type); + ap_pwr_type, chan_freq); } #endif