From 63af5758662c3d48dae6270ee9bfd13fb1ed3483 Mon Sep 17 00:00:00 2001 From: Priyadarshnee Srinivasan Date: Wed, 8 Jun 2022 14:31:50 +0530 Subject: [PATCH] qcacmn: Add AFC changes for 320 MHz Fetch sub-channels of 320 MHz in reg_get_subchannels_for_opclass API. Change MAX_AFC_BW to 320 and REG_MAX_20M_SUB_CH to 16 in case of 11BE. Add cen320 as an input to reg_get_best_pwr_mode to fetch the eirp afc power for the corresponding cen320 from the afc response. Add dispatcher API for reg_get_chan_state_for_320. Add band_center_320 as an argument to reg_get_chan_state_for_320 to fetch the channel state for the input 320 MHz band center. Add logic in reg_find_eirp_in_afc_eirp_obj to fetch the eirp power for the given center freq. CRs-Fixed: 3211744 Change-Id: Ic37bfe6790385836f81a156dd6ccc071245ea1bb --- .../regulatory/core/src/reg_build_chan_list.c | 58 +++++++--- .../regulatory/core/src/reg_build_chan_list.h | 15 ++- umac/regulatory/core/src/reg_opclass.c | 3 + .../regulatory/core/src/reg_services_common.c | 107 ++++++++++++------ .../regulatory/core/src/reg_services_common.h | 44 ++++++- .../dispatcher/inc/wlan_reg_services_api.h | 47 +++++++- .../dispatcher/src/wlan_reg_services_api.c | 21 +++- 7 files changed, 237 insertions(+), 58 deletions(-) diff --git a/umac/regulatory/core/src/reg_build_chan_list.c b/umac/regulatory/core/src/reg_build_chan_list.c index 68781d3077..86bf154234 100644 --- a/umac/regulatory/core/src/reg_build_chan_list.c +++ b/umac/regulatory/core/src/reg_build_chan_list.c @@ -3827,6 +3827,43 @@ reg_fill_min_max_bw_for_afc_list( } } +/** + * reg_fill_subchan_centers() - Fill the subchannels for the given cfi. + * @nchans: Number of sub-channels + * @cfi: Center frequency index + * @subchannels: Array of subchannels to be filled + * + * eg: subchannels[0] = cfi - 6 : The second left hand channel is + * 4 MHz to the left of the previous channel. + * subchannels[1] = cfi - 2 : The first left hand channel is 2 MHz + * to the left of the CFI. + * subchannels[2] = cfi + 2 : The first right hand channel is 2 MHz + * to the right of the center (or CFI) as the distance between + * two IEEE channels is 4 MHz. + * subchannels[3] = cfi + 6 : The second right hand channel is 4 MHz to the + * right the of previous channel + * + * Return: void + */ +static void +reg_fill_subchan_centers(uint8_t nchans, uint8_t cfi, uint8_t *subchannels) +{ + uint8_t last_idx = nchans - 1; + uint8_t offset = HALF_IEEE_CH_SEP; + uint8_t i; + + if (nchans == 1) { + subchannels[0] = cfi; + return; + } + + for (i = nchans / 2; i < nchans; i++) { + subchannels[i] = cfi + offset; + subchannels[last_idx - i] = cfi - offset; + offset += IEEE_20MHZ_CH_SEP; + } +} + /** * reg_get_subchannels_for_opclass() - Get the list of subchannels based on the * the channel frequency index and opclass. @@ -3846,36 +3883,27 @@ uint8_t reg_get_subchannels_for_opclass(uint8_t cfi, case 131: case 136: nchans = 1; - subchannels[0] = cfi; break; case 132: nchans = 2; - subchannels[0] = cfi - 2; - subchannels[1] = cfi + 2; break; case 133: nchans = 4; - subchannels[0] = cfi - 6; - subchannels[1] = cfi - 2; - subchannels[2] = cfi + 2; - subchannels[3] = cfi + 6; break; case 134: nchans = 8; - subchannels[0] = cfi - 14; - subchannels[1] = cfi - 10; - subchannels[2] = cfi - 6; - subchannels[3] = cfi - 2; - subchannels[4] = cfi + 2; - subchannels[5] = cfi + 6; - subchannels[6] = cfi + 10; - subchannels[7] = cfi + 14; break; + case 137: + nchans = 16; + break; + default: nchans = 0; break; } + reg_fill_subchan_centers(nchans, cfi, subchannels); + return nchans; } diff --git a/umac/regulatory/core/src/reg_build_chan_list.h b/umac/regulatory/core/src/reg_build_chan_list.h index ae81004203..c10d8f0f31 100644 --- a/umac/regulatory/core/src/reg_build_chan_list.h +++ b/umac/regulatory/core/src/reg_build_chan_list.h @@ -29,11 +29,24 @@ #define CHAN_12_CENT_FREQ 2467 #define CHAN_13_CENT_FREQ 2472 -#define REG_MAX_20M_SUB_CH 8 + +#ifdef WLAN_FEATURE_11BE +#define REG_MAX_20M_SUB_CH 16 +#else +#define REG_MAX_20M_SUB_CH 8 +#endif + #ifdef CONFIG_AFC_SUPPORT #define MIN_AFC_BW 2 +#ifdef WLAN_FEATURE_11BE +#define MAX_AFC_BW 320 +#else #define MAX_AFC_BW 160 #endif +#endif + +#define HALF_IEEE_CH_SEP 2 +#define IEEE_20MHZ_CH_SEP 4 #include "reg_priv_objs.h" /** diff --git a/umac/regulatory/core/src/reg_opclass.c b/umac/regulatory/core/src/reg_opclass.c index 2d82ab16df..8a7fa2865d 100644 --- a/umac/regulatory/core/src/reg_opclass.c +++ b/umac/regulatory/core/src/reg_opclass.c @@ -525,6 +525,9 @@ static const struct reg_dmn_op_class_map_t { const struct reg_dmn_op_class_map_t *class = NULL; + if (!country) + return global_op_class; + reg_debug_rl("Country %c%c 0x%x", country[0], country[1], country[2]); switch (country[2]) { diff --git a/umac/regulatory/core/src/reg_services_common.c b/umac/regulatory/core/src/reg_services_common.c index 01a995190a..847170eda2 100644 --- a/umac/regulatory/core/src/reg_services_common.c +++ b/umac/regulatory/core/src/reg_services_common.c @@ -4745,22 +4745,11 @@ reg_get_320_bonded_channel_state(struct wlan_objmgr_pdev *pdev, } #endif -/** - * reg_get_chan_state_for_320() - Get the channel state of a 320MHZ - * bonded channel. - * @pdev: Pointer to wlan_objmgr_pdev - * @freq: Primary frequency - * @ch_width: Channel width - * bonded_chan_ptr_ptr: Pointer to bonded channel pointer - * treat_nol_chan_as_disabled: Bool to treat nol chan as enabled/disabled - * @in_pwr_type: Input 6g power type - * - * Return - Channel state - */ #ifdef WLAN_FEATURE_11BE -static enum channel_state +enum channel_state reg_get_chan_state_for_320(struct wlan_objmgr_pdev *pdev, uint16_t freq, + qdf_freq_t band_center_320, enum phy_ch_width ch_width, const struct bonded_channel_freq **bonded_chan_ptr_ptr, @@ -4776,7 +4765,7 @@ reg_get_chan_state_for_320(struct wlan_objmgr_pdev *pdev, /* For now sending band center freq as 0 */ num_bonded_pairs = - reg_get_320_bonded_chan_array(pdev, freq, 0, + reg_get_320_bonded_chan_array(pdev, freq, band_center_320, bonded_chan_320mhz_list_freq, array_size, bonded_ch_ptr); if (!num_bonded_pairs) { @@ -4793,18 +4782,6 @@ reg_get_chan_state_for_320(struct wlan_objmgr_pdev *pdev, in_6g_pwr_type, treat_nol_chan_as_disabled); } -#else -static enum channel_state -reg_get_chan_state_for_320(struct wlan_objmgr_pdev *pdev, - uint16_t freq, - enum phy_ch_width ch_width, - const struct bonded_channel_freq - **bonded_chan_ptr_ptr, - enum supported_6g_pwr_types in_pwr_type, - bool treat_nol_chan_as_disabled) -{ - return CHANNEL_STATE_INVALID; -} #endif #ifdef WLAN_FEATURE_11BE @@ -5365,7 +5342,8 @@ reg_get_5g_bonded_channel_for_freq(struct wlan_objmgr_pdev *pdev, return reg_get_channel_state_for_freq(pdev, freq); if (reg_is_ch_width_320(ch_width)) { - return reg_get_chan_state_for_320(pdev, freq, ch_width, + return reg_get_chan_state_for_320(pdev, freq, 0, + ch_width, bonded_chan_ptr_ptr, REG_CURRENT_PWR_MODE, true); @@ -5396,7 +5374,7 @@ reg_get_5g_bonded_channel_for_pwrmode(struct wlan_objmgr_pdev *pdev, in_6g_pwr_mode); if (reg_is_ch_width_320(ch_width)) - return reg_get_chan_state_for_320(pdev, freq, + return reg_get_chan_state_for_320(pdev, freq, 0, ch_width, bonded_chan_ptr_ptr, in_6g_pwr_mode, true); @@ -8975,12 +8953,47 @@ reg_get_eirp_for_non_sp(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq, } #ifdef CONFIG_AFC_SUPPORT +/** + * reg_compute_6g_center_freq_from_cfi() - Given the IEEE value of the + * 6 GHz center frequency, find the 6 GHz center frequency. + * @ieee_6g_cfi: IEEE value of 6 GHz cfi + * Return: Center frequency in MHz + */ +static qdf_freq_t +reg_compute_6g_center_freq_from_cfi(uint8_t ieee_6g_cfi) +{ + return (SIXG_START_FREQ + ieee_6g_cfi * FREQ_TO_CHAN_SCALE); +} + +#ifdef WLAN_FEATURE_11BE +/** + * reg_is_320_opclass: Find out if the opclass computed from freq and + * width of 320 is same as the input op_class. + * @freq: Frequency in MHz + * @in_opclass: Input Opclass number + * Return: true if opclass is 320 supported, false otherwise. + */ +static bool reg_is_320_opclass(qdf_freq_t freq, uint8_t in_opclass) +{ + uint8_t local_op_class = + reg_dmn_get_opclass_from_freq_width(NULL, freq, BW_320_MHZ, + BIT(BEHAV_NONE)); + return (in_opclass == local_op_class); +} +#else +static inline bool reg_is_320_opclass(qdf_freq_t freq, uint8_t op_class) +{ + return false; +} +#endif + /** * reg_find_eirp_in_afc_eirp_obj() - Get eirp power from the AFC eirp object * based on the channel center frequency and operating class * @pdev: Pointer to pdev * @eirp_obj: Pointer to eirp_obj - * @freq: Frequency in mhz + * @freq: Frequency in MHz + * @cen320: 320 MHz band center frequency * @op_class: Operating class * * Return: EIRP power @@ -8988,12 +9001,23 @@ reg_get_eirp_for_non_sp(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq, static uint8_t reg_find_eirp_in_afc_eirp_obj(struct wlan_objmgr_pdev *pdev, struct chan_eirp_obj *eirp_obj, qdf_freq_t freq, + qdf_freq_t cen320, uint8_t op_class) { uint8_t k; uint8_t subchannels[NUM_20_MHZ_CHAN_IN_320_MHZ_CHAN]; uint8_t nchans; + if (reg_is_320_opclass(freq, op_class)) { + qdf_freq_t cfi_freq = + reg_compute_6g_center_freq_from_cfi(eirp_obj->cfi); + + if (cfi_freq == cen320) + return eirp_obj->eirp_power / EIRP_PWR_SCALE; + + return 0; + } + nchans = reg_get_subchannels_for_opclass(eirp_obj->cfi, op_class, subchannels); @@ -9011,7 +9035,8 @@ static uint8_t reg_find_eirp_in_afc_eirp_obj(struct wlan_objmgr_pdev *pdev, * object based on the channel center frequency and operating class * @pdev: Pointer to pdev * @chan_obj: Pointer to chan_obj - * @freq: Frequency in mhz + * @freq: Frequency in MHz + * @cen320: 320 MHz band center frequency * @op_class: Operating class * * Return: EIRP power @@ -9019,6 +9044,7 @@ static uint8_t reg_find_eirp_in_afc_eirp_obj(struct wlan_objmgr_pdev *pdev, static uint8_t reg_find_eirp_in_afc_chan_obj(struct wlan_objmgr_pdev *pdev, struct afc_chan_obj *chan_obj, qdf_freq_t freq, + qdf_freq_t cen320, uint8_t op_class) { uint8_t j; @@ -9031,7 +9057,8 @@ static uint8_t reg_find_eirp_in_afc_chan_obj(struct wlan_objmgr_pdev *pdev, struct chan_eirp_obj *eirp_obj = &chan_obj->chan_eirp_info[j]; afc_eirp = reg_find_eirp_in_afc_eirp_obj(pdev, eirp_obj, - freq, op_class); + freq, cen320, + op_class); if (afc_eirp) return afc_eirp; @@ -9045,13 +9072,15 @@ static uint8_t reg_find_eirp_in_afc_chan_obj(struct wlan_objmgr_pdev *pdev, * corresponding EIRP values from the afc power info array. The minimum of found * EIRP and regulatory max EIRP is returned * @pdev: Pointer to pdev - * @freq: Frequency in mhz + * @freq: Frequency in MHz + * @cen320: 320 MHz band center frequency * @bw: Bandwidth in mhz * * Return: EIRP */ static uint8_t reg_get_sp_eirp(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq, + qdf_freq_t cen320, uint16_t bw) { uint8_t i, op_class = 0, chan_num = 0, afc_eirp_pwr = 0; @@ -9097,6 +9126,7 @@ static uint8_t reg_get_sp_eirp(struct wlan_objmgr_pdev *pdev, afc_eirp_pwr = reg_find_eirp_in_afc_chan_obj(pdev, chan_obj, freq, + cen320, op_class); if (afc_eirp_pwr) break; @@ -9110,6 +9140,7 @@ static uint8_t reg_get_sp_eirp(struct wlan_objmgr_pdev *pdev, #else static uint8_t reg_get_sp_eirp(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq, + qdf_freq_t cen320, uint16_t bw) { struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; @@ -9159,23 +9190,26 @@ reg_get_best_pwr_mode_from_eirp_list(uint8_t *eirp_list, uint8_t size) /** * reg_get_eirp_pwr() - Get eirp power based on the AP power mode * @pdev: Pointer to pdev - * @freq: Frequency in mhz - * @bw: Bandwidth in mhz + * @freq: Frequency in MHz + * @cen320: 320 MHz Band center frequency + * @bw: Bandwidth in MHz * @ap_pwr_type: AP power type * * Return: EIRP power */ static uint8_t reg_get_eirp_pwr(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq, + qdf_freq_t cen320, uint16_t bw, enum reg_6g_ap_type ap_pwr_type) { if (ap_pwr_type == REG_STANDARD_POWER_AP) - return reg_get_sp_eirp(pdev, freq, bw); + return reg_get_sp_eirp(pdev, freq, cen320, bw); return reg_get_eirp_for_non_sp(pdev, freq, bw, ap_pwr_type); } enum reg_6g_ap_type reg_get_best_pwr_mode(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq, + qdf_freq_t cen320, uint16_t bw) { uint8_t eirp_list[REG_MAX_SUPP_AP_TYPE + 1]; @@ -9184,7 +9218,8 @@ enum reg_6g_ap_type reg_get_best_pwr_mode(struct wlan_objmgr_pdev *pdev, for (ap_pwr_type = REG_INDOOR_AP; ap_pwr_type <= REG_VERY_LOW_POWER_AP; ap_pwr_type++) eirp_list[ap_pwr_type] = - reg_get_eirp_pwr(pdev, freq, bw, ap_pwr_type); + reg_get_eirp_pwr(pdev, freq, cen320, bw, + ap_pwr_type); return reg_get_best_pwr_mode_from_eirp_list(eirp_list, REG_MAX_SUPP_AP_TYPE + 1); diff --git a/umac/regulatory/core/src/reg_services_common.h b/umac/regulatory/core/src/reg_services_common.h index 163d70f5f2..a7be714ec3 100644 --- a/umac/regulatory/core/src/reg_services_common.h +++ b/umac/regulatory/core/src/reg_services_common.h @@ -101,7 +101,7 @@ center_freq - HALF_20MHZ_BW) #define SIX_GIG_ENDING_EDGE_FREQ (channel_map_global[MAX_6GHZ_CHANNEL]. \ center_freq + HALF_20MHZ_BW) - +#define SIXG_START_FREQ 5950 #define FREQ_LEFT_SHIFT 55 #define SIX_GHZ_NON_ORPHAN_START_FREQ \ (channel_map_global[MIN_6GHZ_NON_ORPHAN_CHANNEL].center_freq - 5) @@ -2383,13 +2383,16 @@ qdf_freq_t reg_get_thresh_priority_freq(struct wlan_objmgr_pdev *pdev); * AP's operating bandwidth to return the best power mode, which is calculated * based on the maximum EIRP power among the 3 AP types, i.e, LPI, SP and VLP * @pdev: Pointer to pdev - * @freq: Primary channel center frequency in mhz + * @freq: Primary channel center frequency in MHz + * @cen320: Band center of 320 MHz. (For other BW, this param is ignored during + * processing) * @bw: AP's operating bandwidth in mhz * * Return: Best power mode */ enum reg_6g_ap_type reg_get_best_pwr_mode(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq, + qdf_freq_t cen320, uint16_t bw); #endif /* CONFIG_BAND_6GHZ */ @@ -2500,4 +2503,41 @@ enum channel_state reg_get_chan_state(struct wlan_objmgr_pdev *pdev, enum supported_6g_pwr_types in_6g_pwr_mode, bool treat_nol_chan_as_disabled); +/** + * reg_get_chan_state_for_320() - Get the channel state of a 320 MHz + * bonded channel. + * @pdev: Pointer to wlan_objmgr_pdev + * @freq: Primary frequency + * @center_320: Band center of 320 MHz + * @ch_width: Channel width + * @bonded_chan_ptr_ptr: Pointer to bonded channel pointer + * @treat_nol_chan_as_disabled: Bool to treat nol chan as enabled/disabled + * @in_pwr_type: Input 6g power type + * + * Return: Channel state + */ +#ifdef WLAN_FEATURE_11BE +enum channel_state +reg_get_chan_state_for_320(struct wlan_objmgr_pdev *pdev, + uint16_t freq, + qdf_freq_t center_320, + enum phy_ch_width ch_width, + const struct bonded_channel_freq + **bonded_chan_ptr_ptr, + enum supported_6g_pwr_types in_pwr_type, + bool treat_nol_chan_as_disabled); +#else +static inline enum channel_state +reg_get_chan_state_for_320(struct wlan_objmgr_pdev *pdev, + uint16_t freq, + qdf_freq_t center_320, + enum phy_ch_width ch_width, + const struct bonded_channel_freq + **bonded_chan_ptr_ptr, + enum supported_6g_pwr_types in_pwr_type, + bool treat_nol_chan_as_disabled) +{ + return CHANNEL_STATE_INVALID; +} +#endif #endif diff --git a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h index ade6dcd806..438cfa3af9 100644 --- a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h +++ b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h @@ -2376,14 +2376,16 @@ QDF_STATUS wlan_reg_psd_2_eirp(struct wlan_objmgr_pdev *pdev, * wlan_reg_get_best_pwr_mode() - Get the best power mode based on input freq * and bandwidth. The mode that provides the best EIRP is the best power mode. * @pdev: Pointer to pdev - * @freq: Frequency in mhz - * @bw: Bandwidth in mhz + * @freq: Frequency in MHz + * @cen320: 320 MHz band center frequency. For other BW, this param is + * ignored while processing + * @bw: Bandwidth in MHz * * Return: Best power mode */ enum reg_6g_ap_type wlan_reg_get_best_pwr_mode(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq, - uint16_t bw); + qdf_freq_t cen320, uint16_t bw); #else static inline qdf_freq_t wlan_reg_get_thresh_priority_freq(struct wlan_objmgr_pdev *pdev) @@ -2393,6 +2395,7 @@ qdf_freq_t wlan_reg_get_thresh_priority_freq(struct wlan_objmgr_pdev *pdev) static inline enum reg_6g_ap_type wlan_reg_get_best_pwr_mode(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq, + qdf_freq_t cen320, uint16_t bw) { return REG_MAX_AP_TYPE; @@ -2414,4 +2417,42 @@ static inline QDF_STATUS wlan_reg_psd_2_eirp(struct wlan_objmgr_pdev *pdev, * Return: phy_ch_width */ enum phy_ch_width wlan_reg_find_chwidth_from_bw(uint16_t bw); + +/** + * wlan_reg_get_chan_state_for_320() - Get the channel state of a 320 MHz + * bonded channel. + * @pdev: Pointer to wlan_objmgr_pdev + * @freq: Primary frequency + * @center_320: Band center of 320 MHz + * @ch_width: Channel width + * @bonded_chan_ptr_ptr: Pointer to bonded channel pointer + * @treat_nol_chan_as_disabled: Bool to treat nol chan as enabled/disabled + * @in_pwr_type: Input 6g power type + * + * Return: Channel state + */ +#ifdef WLAN_FEATURE_11BE +enum channel_state +wlan_reg_get_chan_state_for_320(struct wlan_objmgr_pdev *pdev, + uint16_t freq, + qdf_freq_t center_320, + enum phy_ch_width ch_width, + const struct bonded_channel_freq + **bonded_chan_ptr_ptr, + enum supported_6g_pwr_types in_6g_pwr_type, + bool treat_nol_chan_as_disabled); +#else +static inline enum channel_state +wlan_reg_get_chan_state_for_320(struct wlan_objmgr_pdev *pdev, + uint16_t freq, + qdf_freq_t center_320, + enum phy_ch_width ch_width, + const struct bonded_channel_freq + **bonded_chan_ptr_ptr, + enum supported_6g_pwr_types in_6g_pwr_type, + bool treat_nol_chan_as_disabled) +{ + return CHANNEL_STATE_INVALID; +} +#endif #endif diff --git a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c index cc399e77c4..653e0ac266 100644 --- a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c +++ b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c @@ -1818,9 +1818,10 @@ qdf_export_symbol(wlan_reg_psd_2_eirp); enum reg_6g_ap_type wlan_reg_get_best_pwr_mode(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq, + qdf_freq_t cen320, uint16_t bw) { - return reg_get_best_pwr_mode(pdev, freq, bw); + return reg_get_best_pwr_mode(pdev, freq, cen320, bw); } #endif /* CONFIG_BAND_6GHZ */ @@ -1828,3 +1829,21 @@ enum phy_ch_width wlan_reg_find_chwidth_from_bw(uint16_t bw) { return reg_find_chwidth_from_bw(bw); } + +#ifdef WLAN_FEATURE_11BE +enum channel_state +wlan_reg_get_chan_state_for_320(struct wlan_objmgr_pdev *pdev, + uint16_t freq, + qdf_freq_t center_320, + enum phy_ch_width ch_width, + const struct bonded_channel_freq + **bonded_chan_ptr_ptr, + enum supported_6g_pwr_types in_6g_pwr_type, + bool treat_nol_chan_as_disabled) +{ + return reg_get_chan_state_for_320(pdev, freq, center_320, + ch_width, bonded_chan_ptr_ptr, + in_6g_pwr_type, + treat_nol_chan_as_disabled); +} +#endif