diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.c b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.c index ca82b046b72d..479bfaec20f4 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.c @@ -39,8 +39,11 @@ #include "reg_build_chan_list.h" #include "wlan_cm_bss_score_param.h" #include "wmi_unified_param.h" +#include "qdf_str.h" #define DEFAULT_WORLD_REGDMN 0x60 +#define FCC3_FCCA 0x3A +#define FCC6_FCCA 0x14 #define IS_VALID_PSOC_REG_OBJ(psoc_priv_obj) (psoc_priv_obj) #define IS_VALID_PDEV_REG_OBJ(pdev_priv_obj) (pdev_priv_obj) @@ -180,6 +183,48 @@ bool reg_is_etsi_alpha2(uint8_t *alpha2) return false; } +static +const char *reg_get_power_mode_string(uint16_t reg_dmn_pair_id) +{ + switch (reg_dmn_pair_id) { + case FCC3_FCCA: + case FCC6_FCCA: + return "NON_VLP"; + default: + return "VLP"; + } +} + +static bool reg_ctry_domain_supports_vlp(uint8_t *alpha2) +{ + uint16_t i; + int no_of_countries; + + reg_get_num_countries(&no_of_countries); + for (i = 0; i < no_of_countries; i++) { + if (g_all_countries[i].alpha2[0] == alpha2[0] && + g_all_countries[i].alpha2[1] == alpha2[1]) { + if (!qdf_str_cmp(reg_get_power_mode_string( + g_all_countries[i].reg_dmn_pair_id), "NON_VLP")) + return false; + else + return true; + } + } + return true; +} + +bool reg_ctry_support_vlp(uint8_t *alpha2) +{ + if (((alpha2[0] == 'A') && (alpha2[1] == 'E')) || + ((alpha2[0] == 'P') && (alpha2[1] == 'E')) || + ((alpha2[0] == 'U') && (alpha2[1] == 'S')) || + !reg_ctry_domain_supports_vlp(alpha2)) + return false; + else + return true; +} + QDF_STATUS reg_set_country(struct wlan_objmgr_pdev *pdev, uint8_t *country) { @@ -329,53 +374,85 @@ QDF_STATUS reg_get_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, } #ifdef CONFIG_REG_CLIENT +#ifdef CONFIG_BAND_6GHZ QDF_STATUS reg_get_6g_power_type_for_ctry(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev, uint8_t *ap_ctry, uint8_t *sta_ctry, enum reg_6g_ap_type *pwr_type_6g, bool *ctry_code_match, enum reg_6g_ap_type ap_pwr_type) { - *pwr_type_6g = REG_INDOOR_AP; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; - if (qdf_mem_cmp(ap_ctry, sta_ctry, REG_ALPHA2_LEN)) { - reg_debug("Country IE:%c%c, STA country:%c%c", ap_ctry[0], - ap_ctry[1], sta_ctry[0], sta_ctry[1]); - *ctry_code_match = false; + *pwr_type_6g = ap_pwr_type; + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!pdev_priv_obj) { + reg_err("pdev priv obj null"); + return QDF_STATUS_E_FAILURE; + } - /** - * Do not return if Wi-Fi safe mode or RF test mode is - * enabled, rather STA should operate in LPI mode. - * wlan_cm_get_check_6ghz_security API returns true if - * neither Safe mode nor RF test mode are enabled. - */ - if (wlan_reg_is_us(sta_ctry) && - wlan_cm_get_check_6ghz_security(psoc)) { - reg_err("US VLP not in place yet, connection not allowed"); - return QDF_STATUS_E_NOSUPPORT; - } + reg_debug("STA country: %c%c, AP country: %c%c, AP power type: %d", + sta_ctry[0], sta_ctry[1], ap_ctry[0], ap_ctry[1], + ap_pwr_type); - if (wlan_reg_is_etsi(sta_ctry) && - ap_pwr_type != REG_MAX_AP_TYPE) { - if (!(wlan_reg_is_us(ap_ctry) && - ap_pwr_type == REG_INDOOR_AP)) { - reg_debug("STA ctry:%c%c, doesn't match with AP ctry, switch to VLP", - sta_ctry[0], sta_ctry[1]); - *pwr_type_6g = REG_VERY_LOW_POWER_AP; + if (!qdf_mem_cmp(ap_ctry, sta_ctry, REG_ALPHA2_LEN)) { + *ctry_code_match = true; + if (ap_pwr_type == REG_VERY_LOW_POWER_AP) { + if (!pdev_priv_obj->reg_rules.num_of_6g_client_reg_rules[ap_pwr_type]) { + reg_err("VLP not supported, can't connect"); + return QDF_STATUS_E_NOSUPPORT; } } + return QDF_STATUS_SUCCESS; + } - if (wlan_reg_is_us(ap_ctry) && ap_pwr_type == REG_INDOOR_AP) { - reg_debug("AP ctry:%c%c, AP power type:%d, allow STA IN LPI", - ap_ctry[0], ap_ctry[1], ap_pwr_type); - *pwr_type_6g = REG_INDOOR_AP; + *ctry_code_match = false; + /* + * If reg_info=0 not included, STA should operate in VLP mode. + * If STA country doesn't support VLP, do not return if Wi-Fi + * safe mode or RF test mode or enable relaxed connection policy, + * rather STA should operate in LPI mode. + * wlan_cm_get_check_6ghz_security API returns true if + * neither Safe mode nor RF test mode are enabled. + */ + if (ap_pwr_type != REG_INDOOR_AP) { + if (wlan_reg_ctry_support_vlp(sta_ctry)) + *pwr_type_6g = REG_VERY_LOW_POWER_AP; + if (!wlan_reg_ctry_support_vlp(sta_ctry) && + wlan_cm_get_check_6ghz_security(psoc)) { + reg_err("VLP not supported, can't connect"); + return QDF_STATUS_E_NOSUPPORT; } - } else { - *ctry_code_match = true; + } + + if (wlan_reg_ctry_support_vlp(sta_ctry) && + wlan_reg_ctry_support_vlp(ap_ctry) && + ap_pwr_type == REG_INDOOR_AP) { + reg_debug("STA ctry doesn't match with AP ctry, switch to VLP"); + *pwr_type_6g = REG_VERY_LOW_POWER_AP; + } + + if (!wlan_reg_ctry_support_vlp(ap_ctry) && + ap_pwr_type == REG_INDOOR_AP) { + reg_debug("VLP not supported by AP, allow STA IN LPI"); + *pwr_type_6g = REG_INDOOR_AP; } return QDF_STATUS_SUCCESS; } +#else +QDF_STATUS +reg_get_6g_power_type_for_ctry(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev, + uint8_t *ap_ctry, uint8_t *sta_ctry, + enum reg_6g_ap_type *pwr_type_6g, + bool *ctry_code_match, + enum reg_6g_ap_type ap_pwr_type) +{ + return QDF_STATUS_SUCCESS; +} +#endif #endif #ifdef CONFIG_CHAN_NUM_API diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.h b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.h index e151a8fd3b94..069a04220aed 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.h @@ -260,6 +260,14 @@ bool reg_is_us_alpha2(uint8_t *alpha2); */ bool reg_is_etsi_alpha2(uint8_t *alpha2); +/** + * reg_ctry_support_vlp - Does country code supports VLP + * @alpha2: country code pointer + * + * Return: true or false + */ +bool reg_ctry_support_vlp(uint8_t *alpha2); + /** * reg_set_country() - Set the current regulatory country * @pdev: pdev device for country information @@ -292,6 +300,8 @@ QDF_STATUS reg_get_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, #ifdef CONFIG_REG_CLIENT /** * reg_get_6g_power_type_for_ctry() - Return power type for 6G based on cntry IE + * @psoc: pointer to psoc + * @pdev: pointer to pdev * @ap_ctry: ptr to country string in country IE * @sta_ctry: ptr to sta programmed country * @pwr_type_6g: ptr to 6G power type @@ -301,6 +311,7 @@ QDF_STATUS reg_get_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, */ QDF_STATUS reg_get_6g_power_type_for_ctry(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev, uint8_t *ap_ctry, uint8_t *sta_ctry, enum reg_6g_ap_type *pwr_type_6g, bool *ctry_code_match, @@ -443,6 +454,11 @@ static inline bool reg_is_world_alpha2(uint8_t *alpha2) return false; } +static inline bool reg_ctry_support_vlp(uint8_t *alpha2) +{ + return false; +} + static inline bool reg_is_us_alpha2(uint8_t *alpha2) { return false; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h index 99a67981c385..5019ea4e8afe 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -543,6 +543,8 @@ QDF_STATUS wlan_reg_read_current_country(struct wlan_objmgr_psoc *psoc, /** * wlan_reg_get_6g_power_type_for_ctry() - Return power type for 6G based * on country IE + * @psoc: pointer to psoc + * @pdev: pointer to pdev * @ap_ctry: ptr to country string in country IE * @sta_ctry: ptr to sta programmed country * @pwr_type_6g: ptr to 6G power type @@ -552,6 +554,7 @@ QDF_STATUS wlan_reg_read_current_country(struct wlan_objmgr_psoc *psoc, */ QDF_STATUS wlan_reg_get_6g_power_type_for_ctry(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev, uint8_t *ap_ctry, uint8_t *sta_ctry, enum reg_6g_ap_type *pwr_type_6g, bool *ctry_code_match, @@ -1062,6 +1065,14 @@ bool wlan_reg_chan_is_49ghz(struct wlan_objmgr_pdev *pdev, uint8_t chan_num); #endif /* CONFIG_CHAN_NUM_API */ +/** + * wlan_reg_ctry_support_vlp() - Country supports VLP or not + * @country: The country information + * + * Return: true or false + */ +bool wlan_reg_ctry_support_vlp(uint8_t *country); + /** * wlan_reg_set_country() - Set the current regulatory country * @pdev: The physical dev to set current country for diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/src/wlan_reg_services_api.c b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/src/wlan_reg_services_api.c index b9bec25b2e6d..95ed22420a5b 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/src/wlan_reg_services_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/src/wlan_reg_services_api.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -88,12 +88,13 @@ QDF_STATUS wlan_reg_get_max_5g_bw_from_regdomain(uint16_t regdmn, #ifdef CONFIG_REG_CLIENT QDF_STATUS wlan_reg_get_6g_power_type_for_ctry(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev, uint8_t *ap_ctry, uint8_t *sta_ctry, enum reg_6g_ap_type *pwr_type_6g, bool *ctry_code_match, enum reg_6g_ap_type ap_pwr_type) { - return reg_get_6g_power_type_for_ctry(psoc, ap_ctry, sta_ctry, + return reg_get_6g_power_type_for_ctry(psoc, pdev, ap_ctry, sta_ctry, pwr_type_6g, ctry_code_match, ap_pwr_type); } @@ -667,6 +668,11 @@ bool wlan_reg_is_etsi(uint8_t *country) return reg_is_etsi_alpha2(country); } +bool wlan_reg_ctry_support_vlp(uint8_t *country) +{ + return reg_ctry_support_vlp(country); +} + void wlan_reg_register_chan_change_callback(struct wlan_objmgr_psoc *psoc, void *cbk, void *arg) { diff --git a/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_utils_api.c index 49be228eac36..bff9e3b812c4 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -2642,9 +2642,9 @@ util_scan_parse_beacon_frame(struct wlan_objmgr_pdev *pdev, mbssid_ie = util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, (uint8_t *)&bcn->ie, ie_len); if (mbssid_ie) { - if (mbssid_ie[1] <= 0) { + if (mbssid_ie[TAG_LEN_POS] < VALID_ELEM_LEAST_LEN) { scm_debug("MBSSID IE length is wrong %d", - mbssid_ie[1]); + mbssid_ie[TAG_LEN_POS]); return status; } qdf_mem_copy(&mbssid_info.trans_bssid,