diff --git a/umac/regulatory/core/src/reg_build_chan_list.c b/umac/regulatory/core/src/reg_build_chan_list.c new file mode 100644 index 000000000000..b63f807731cc --- /dev/null +++ b/umac/regulatory/core/src/reg_build_chan_list.c @@ -0,0 +1,901 @@ +/* + * Copyright (c) 2014-2019 The Linux Foundation. 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: reg_build_chan_list.c + * This file defines the API to build master and current channel list. + */ + +#include +#include +#include +#include +#include "reg_priv_objs.h" +#include "reg_getset.h" +#include "reg_callbacks.h" +#include "reg_services_common.h" +#include "reg_db.h" +#include "reg_db_parser.h" +#include "reg_host_11d.h" +#include +#include "reg_build_chan_list.h" +#include + +#define CHAN_12_CENT_FREQ 2467 +#define MAX_PWR_FCC_CHAN_12 8 +#define CHAN_13_CENT_FREQ 2472 +#define MAX_PWR_FCC_CHAN_13 2 +#define CHAN_144_CENT_FREQ 5720 + +/** + * reg_fill_channel_info() - Populate TX power, antenna gain, channel state, + * channel flags, min and max bandwidth to master channel list. + * @chan_enum: Channel enum. + * @reg_rule: Pointer to regulatory rule which has tx power and antenna gain. + * @master_list: Pointer to master channel list. + * @min_bw: minimum bandwidth to be used for given channel. + */ +static void reg_fill_channel_info(enum channel_enum chan_enum, + struct cur_reg_rule *reg_rule, + struct regulatory_channel *master_list, + uint16_t min_bw) +{ + master_list[chan_enum].chan_flags &= ~REGULATORY_CHAN_DISABLED; + + master_list[chan_enum].tx_power = reg_rule->reg_power; + master_list[chan_enum].ant_gain = reg_rule->ant_gain; + master_list[chan_enum].state = CHANNEL_STATE_ENABLE; + + if (reg_rule->flags & REGULATORY_CHAN_NO_IR) { + master_list[chan_enum].chan_flags |= REGULATORY_CHAN_NO_IR; + master_list[chan_enum].state = CHANNEL_STATE_DFS; + } + + if (reg_rule->flags & REGULATORY_CHAN_RADAR) { + master_list[chan_enum].chan_flags |= REGULATORY_CHAN_RADAR; + master_list[chan_enum].state = CHANNEL_STATE_DFS; + } + + if (reg_rule->flags & REGULATORY_CHAN_INDOOR_ONLY) + master_list[chan_enum].chan_flags |= + REGULATORY_CHAN_INDOOR_ONLY; + + if (reg_rule->flags & REGULATORY_CHAN_NO_OFDM) + master_list[chan_enum].chan_flags |= REGULATORY_CHAN_NO_OFDM; + + master_list[chan_enum].min_bw = min_bw; + if (master_list[chan_enum].max_bw == 20) + master_list[chan_enum].max_bw = reg_rule->max_bw; +} + +/** + * reg_populate_band_channels() - For all the valid regdb channels in the master + * channel list, find the regulatory rules and call reg_fill_channel_info() to + * populate master channel list with txpower, antennagain, BW info, etc. + * @start_chan: Start channel enum. + * @end_chan: End channel enum. + * @rule_start_ptr: Pointer to regulatory rules. + * @num_reg_rules: Number of regulatory rules. + * @min_reg_bw: Minimum regulatory bandwidth. + * @mas_chan_list: Pointer to master channel list. + */ +static void reg_populate_band_channels(enum channel_enum start_chan, + enum channel_enum end_chan, + struct cur_reg_rule *rule_start_ptr, + uint32_t num_reg_rules, + uint16_t min_reg_bw, + struct regulatory_channel *mas_chan_list) +{ + struct cur_reg_rule *found_rule_ptr; + struct cur_reg_rule *cur_rule_ptr; + struct regulatory_channel; + enum channel_enum chan_enum; + uint32_t rule_num, bw; + uint16_t max_bw; + uint16_t min_bw; + + for (chan_enum = start_chan; chan_enum <= end_chan; chan_enum++) { + found_rule_ptr = NULL; + + max_bw = QDF_MIN((uint16_t)20, channel_map[chan_enum].max_bw); + min_bw = QDF_MAX(min_reg_bw, channel_map[chan_enum].min_bw); + + if (channel_map[chan_enum].chan_num == INVALID_CHANNEL_NUM) + continue; + + for (bw = max_bw; bw >= min_bw; bw = bw / 2) { + for (rule_num = 0, cur_rule_ptr = rule_start_ptr; + rule_num < num_reg_rules; + cur_rule_ptr++, rule_num++) { + if ((cur_rule_ptr->start_freq <= + mas_chan_list[chan_enum].center_freq - + bw / 2) && + (cur_rule_ptr->end_freq >= + mas_chan_list[chan_enum].center_freq + + bw / 2) && (min_bw <= bw)) { + found_rule_ptr = cur_rule_ptr; + break; + } + } + + if (found_rule_ptr) + break; + } + + if (found_rule_ptr) { + mas_chan_list[chan_enum].max_bw = bw; + reg_fill_channel_info(chan_enum, found_rule_ptr, + mas_chan_list, min_bw); + /* Disable 2.4 Ghz channels that dont have 20 mhz bw */ + if (start_chan == MIN_24GHZ_CHANNEL && + mas_chan_list[chan_enum].max_bw < 20) { + mas_chan_list[chan_enum].chan_flags |= + REGULATORY_CHAN_DISABLED; + mas_chan_list[chan_enum].state = + REGULATORY_CHAN_DISABLED; + } + } + } +} + +/** + * reg_update_max_bw_per_rule() - Update max bandwidth value for given regrules. + * @num_reg_rules: Number of regulatory rules. + * @reg_rule_start: Pointer to regulatory rules. + * @max_bw: Maximum bandwidth + */ +static void reg_update_max_bw_per_rule(uint32_t num_reg_rules, + struct cur_reg_rule *reg_rule_start, + uint16_t max_bw) +{ + uint32_t count; + + for (count = 0; count < num_reg_rules; count++) + reg_rule_start[count].max_bw = + min(reg_rule_start[count].max_bw, max_bw); +} + +/** + * reg_do_auto_bw_correction() - Calculate and update the maximum bandwidth + * value. + * @num_reg_rules: Number of regulatory rules. + * @reg_rule_ptr: Pointer to regulatory rules. + * @max_bw: Maximum bandwidth + */ +static void reg_do_auto_bw_correction(uint32_t num_reg_rules, + struct cur_reg_rule *reg_rule_ptr, + uint16_t max_bw) +{ + uint32_t count; + uint16_t new_bw; + + for (count = 0; count < num_reg_rules - 1; count++) { + if ((reg_rule_ptr[count].end_freq == + reg_rule_ptr[count + 1].start_freq) && + ((reg_rule_ptr[count].max_bw + + reg_rule_ptr[count + 1].max_bw) <= max_bw)) { + new_bw = reg_rule_ptr[count].max_bw + + reg_rule_ptr[count + 1].max_bw; + reg_rule_ptr[count].max_bw = new_bw; + reg_rule_ptr[count + 1].max_bw = new_bw; + } + } +} + +/** + * reg_modify_chan_list_for_dfs_channels() - disable the DFS channels if + * dfs_enable set to false. + * @chan_list: Pointer to regulatory channel list. + * @dfs_enabled: if false, then disable the DFS channels. + */ +static void reg_modify_chan_list_for_dfs_channels( + struct regulatory_channel *chan_list, bool dfs_enabled) +{ + enum channel_enum chan_enum; + + if (dfs_enabled) + return; + + for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { + if (chan_list[chan_enum].state == CHANNEL_STATE_DFS) { + chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; + chan_list[chan_enum].chan_flags |= + REGULATORY_CHAN_DISABLED; + } + } +} + +/** + * reg_modify_chan_list_for_indoor_channels() - Disable the indoor channels if + * indoor_chan_enabled flag is set to false. + * @pdev_priv_obj: Pointer to regulatory private pdev structure. + */ +static void reg_modify_chan_list_for_indoor_channels( + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) +{ + enum channel_enum chan_enum; + struct regulatory_channel *chan_list = pdev_priv_obj->cur_chan_list; + + if (pdev_priv_obj->indoor_chan_enabled) + return; + + if (!pdev_priv_obj->force_ssc_disable_indoor_channel) { + for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { + if (REGULATORY_CHAN_INDOOR_ONLY & + chan_list[chan_enum].chan_flags) { + chan_list[chan_enum].state = + CHANNEL_STATE_DISABLE; + chan_list[chan_enum].chan_flags |= + REGULATORY_CHAN_DISABLED; + } + } + } else { + for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { + if (pdev_priv_obj->sap_state) { + if (REGULATORY_CHAN_INDOOR_ONLY & + chan_list[chan_enum].chan_flags) { + chan_list[chan_enum].state = + CHANNEL_STATE_DISABLE; + chan_list[chan_enum].chan_flags |= + REGULATORY_CHAN_DISABLED; + } + } else { + if (REGULATORY_CHAN_INDOOR_ONLY & + chan_list[chan_enum].chan_flags) { + chan_list[chan_enum].state = + CHANNEL_STATE_DFS; + chan_list[chan_enum].chan_flags |= + REGULATORY_CHAN_NO_IR; + } + } + } + } +} + +/** + * reg_modify_chan_list_for_band() - Based on the input band value, either + * disable 2GHz or 5GHz channels. + * @chan_list: Pointer to regulatory channel list. + * @band_val: Input band value. + */ +static void reg_modify_chan_list_for_band(struct regulatory_channel *chan_list, + enum band_info band_val) +{ + enum channel_enum chan_enum; + + if (band_val == BAND_2G) { + for (chan_enum = MIN_5GHZ_CHANNEL; + chan_enum <= MAX_5GHZ_CHANNEL; chan_enum++) { + chan_list[chan_enum].chan_flags |= + REGULATORY_CHAN_DISABLED; + chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; + } + } + + if (band_val == BAND_5G) { + for (chan_enum = MIN_24GHZ_CHANNEL; + chan_enum <= MAX_24GHZ_CHANNEL; chan_enum++) { + chan_list[chan_enum].chan_flags |= + REGULATORY_CHAN_DISABLED; + chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; + } + } +} + +/** + * reg_modify_chan_list_for_fcc_channel() - Set maximum FCC txpower for channel + * 12 and 13 if set_fcc_channel flag is set to true. + * @chan_list: Pointer to regulatory channel list. + * @set_fcc_channel: If this flag is set to true, then set the max FCC txpower + * for channel 12 and 13. + */ +static void reg_modify_chan_list_for_fcc_channel( + struct regulatory_channel *chan_list, bool set_fcc_channel) +{ + enum channel_enum chan_enum; + + if (!set_fcc_channel) + return; + + for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { + if (chan_list[chan_enum].center_freq == CHAN_12_CENT_FREQ) + chan_list[chan_enum].tx_power = MAX_PWR_FCC_CHAN_12; + + if (chan_list[chan_enum].center_freq == CHAN_13_CENT_FREQ) + chan_list[chan_enum].tx_power = MAX_PWR_FCC_CHAN_13; + } +} + +/** + * reg_modify_chan_list_for_chan_144() - Disable channel 144 if en_chan_144 flag + * is set to false. + * @chan_list: Pointer to regulatory channel list. + * @en_chan_144: if false, then disable channel 144. + */ +static void reg_modify_chan_list_for_chan_144( + struct regulatory_channel *chan_list, bool en_chan_144) +{ + enum channel_enum chan_enum; + + if (en_chan_144) + return; + + for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { + if (chan_list[chan_enum].center_freq == CHAN_144_CENT_FREQ) { + chan_list[chan_enum].chan_flags |= + REGULATORY_CHAN_DISABLED; + chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; + } + } +} + +/** + * reg_modify_chan_list_for_nol_list() - Disable the channel if nol_chan flag is + * set. + * @chan_list: Pointer to regulatory channel list. + */ +static void reg_modify_chan_list_for_nol_list( + struct regulatory_channel *chan_list) +{ + enum channel_enum chan_enum; + + for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { + if (chan_list[chan_enum].nol_chan) { + chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; + chan_list[chan_enum].chan_flags |= + REGULATORY_CHAN_DISABLED; + } + } +} + +/** + * reg_find_low_limit_chan_enum() - Find low limit 2G and 5G channel enums. + * @chan_list: Pointer to regulatory channel list. + * @low_freq: low limit frequency. + * @low_limit: pointer to output low limit enum. + * + * Return: None + */ +static void reg_find_low_limit_chan_enum( + struct regulatory_channel *chan_list, uint32_t low_freq, + uint32_t *low_limit) +{ + enum channel_enum chan_enum; + uint16_t min_bw; + uint16_t max_bw; + uint32_t center_freq; + + for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { + min_bw = chan_list[chan_enum].min_bw; + max_bw = chan_list[chan_enum].max_bw; + center_freq = chan_list[chan_enum].center_freq; + + if ((center_freq - min_bw / 2) >= low_freq) { + if ((center_freq - max_bw / 2) < low_freq) { + if (max_bw <= 20) + max_bw = ((center_freq - low_freq) * 2); + if (max_bw < min_bw) + max_bw = min_bw; + chan_list[chan_enum].max_bw = max_bw; + } + *low_limit = chan_enum; + break; + } + } +} + +/** + * reg_find_high_limit_chan_enum() - Find high limit 2G and 5G channel enums. + * @chan_list: Pointer to regulatory channel list. + * @high_freq: high limit frequency. + * @high_limit: pointer to output high limit enum. + * + * Return: None + */ +static void reg_find_high_limit_chan_enum( + struct regulatory_channel *chan_list, uint32_t high_freq, + uint32_t *high_limit) +{ + enum channel_enum chan_enum; + uint16_t min_bw; + uint16_t max_bw; + uint32_t center_freq; + + for (chan_enum = NUM_CHANNELS - 1; chan_enum >= 0; chan_enum--) { + min_bw = chan_list[chan_enum].min_bw; + max_bw = chan_list[chan_enum].max_bw; + center_freq = chan_list[chan_enum].center_freq; + + if (center_freq + min_bw / 2 <= high_freq) { + if ((center_freq + max_bw / 2) > high_freq) { + if (max_bw <= 20) + max_bw = ((high_freq - + center_freq) * 2); + if (max_bw < min_bw) + max_bw = min_bw; + chan_list[chan_enum].max_bw = max_bw; + } + *high_limit = chan_enum; + break; + } + + if (chan_enum == 0) + break; + } +} + +/** + * reg_modify_chan_list_for_freq_range() - Modify channel list for the given low + * and high frequency range. + * @chan_list: Pointer to regulatory channel list. + * @low_freq_2g: Low frequency 2G. + * @high_freq_2g: High frequency 2G. + * @low_freq_5g: Low frequency 5G. + * @high_freq_5g: High frequency 5G. + * + * Return: None + */ +static void +reg_modify_chan_list_for_freq_range(struct regulatory_channel *chan_list, + uint32_t low_freq_2g, + uint32_t high_freq_2g, + uint32_t low_freq_5g, + uint32_t high_freq_5g) +{ + uint32_t low_limit_2g = NUM_CHANNELS; + uint32_t high_limit_2g = NUM_CHANNELS; + uint32_t low_limit_5g = NUM_CHANNELS; + uint32_t high_limit_5g = NUM_CHANNELS; + enum channel_enum chan_enum; + bool chan_in_range; + + reg_find_low_limit_chan_enum(chan_list, low_freq_2g, &low_limit_2g); + reg_find_low_limit_chan_enum(chan_list, low_freq_5g, &low_limit_5g); + reg_find_high_limit_chan_enum(chan_list, high_freq_2g, &high_limit_2g); + reg_find_high_limit_chan_enum(chan_list, high_freq_5g, &high_limit_5g); + + for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { + chan_in_range = false; + if ((low_limit_2g <= chan_enum) && + (high_limit_2g >= chan_enum) && + (low_limit_2g != NUM_CHANNELS) && + (high_limit_2g != NUM_CHANNELS)) + chan_in_range = true; + + if ((low_limit_5g <= chan_enum) && + (high_limit_5g >= chan_enum) && + (low_limit_5g != NUM_CHANNELS) && + (high_limit_5g != NUM_CHANNELS)) + chan_in_range = true; + + if (!chan_in_range) { + chan_list[chan_enum].chan_flags |= + REGULATORY_CHAN_DISABLED; + chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; + } + } +} + +void reg_init_pdev_mas_chan_list( + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj, + struct mas_chan_params *mas_chan_params) +{ + qdf_mem_copy(pdev_priv_obj->mas_chan_list, + mas_chan_params->mas_chan_list, + NUM_CHANNELS * sizeof(struct regulatory_channel)); + + pdev_priv_obj->dfs_region = mas_chan_params->dfs_region; + + pdev_priv_obj->phybitmap = mas_chan_params->phybitmap; + + pdev_priv_obj->reg_dmn_pair = mas_chan_params->reg_dmn_pair; + pdev_priv_obj->ctry_code = mas_chan_params->ctry_code; + + pdev_priv_obj->def_region_domain = mas_chan_params->reg_dmn_pair; + pdev_priv_obj->def_country_code = mas_chan_params->ctry_code; + + qdf_mem_copy(pdev_priv_obj->default_country, + mas_chan_params->default_country, REG_ALPHA2_LEN + 1); + + qdf_mem_copy(pdev_priv_obj->current_country, + mas_chan_params->current_country, REG_ALPHA2_LEN + 1); +} + +/** + * reg_modify_chan_list_for_cached_channels() - If num_cache_channels are + * non-zero, then disable the pdev channels which is given in + * cache_disable_chan_list. + * @pdev_priv_obj: Pointer to regulatory pdev private object. + */ +#ifdef DISABLE_CHANNEL_LIST +static void reg_modify_chan_list_for_cached_channels( + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) +{ + uint32_t i, j; + uint32_t num_cache_channels = pdev_priv_obj->num_cache_channels; + struct regulatory_channel *chan_list = pdev_priv_obj->cur_chan_list; + struct regulatory_channel *cache_chan_list = + pdev_priv_obj->cache_disable_chan_list; + + if (!num_cache_channels) + return; + + if (pdev_priv_obj->disable_cached_channels) { + for (i = 0; i < num_cache_channels; i++) + for (j = 0; j < NUM_CHANNELS; j++) + if (cache_chan_list[i].chan_num == + chan_list[j].chan_num) { + chan_list[j].state = + CHANNEL_STATE_DISABLE; + chan_list[j].chan_flags |= + REGULATORY_CHAN_DISABLED; + } + } +} +#else +static void reg_modify_chan_list_for_cached_channels( + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) +{ +} +#endif + +void reg_compute_pdev_current_chan_list( + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) +{ + qdf_mem_copy(pdev_priv_obj->cur_chan_list, pdev_priv_obj->mas_chan_list, + NUM_CHANNELS * sizeof(struct regulatory_channel)); + + reg_modify_chan_list_for_freq_range(pdev_priv_obj->cur_chan_list, + pdev_priv_obj->range_2g_low, + pdev_priv_obj->range_2g_high, + pdev_priv_obj->range_5g_low, + pdev_priv_obj->range_5g_high); + + reg_modify_chan_list_for_band(pdev_priv_obj->cur_chan_list, + pdev_priv_obj->band_capability); + + reg_modify_chan_list_for_dfs_channels(pdev_priv_obj->cur_chan_list, + pdev_priv_obj->dfs_enabled); + + reg_modify_chan_list_for_nol_list(pdev_priv_obj->cur_chan_list); + + reg_modify_chan_list_for_indoor_channels(pdev_priv_obj); + + reg_modify_chan_list_for_fcc_channel(pdev_priv_obj->cur_chan_list, + pdev_priv_obj->set_fcc_channel); + + reg_modify_chan_list_for_chan_144(pdev_priv_obj->cur_chan_list, + pdev_priv_obj->en_chan_144); + + reg_modify_chan_list_for_cached_channels(pdev_priv_obj); +} + +void reg_reset_reg_rules(struct reg_rule_info *reg_rules) +{ + qdf_mem_zero(reg_rules, sizeof(*reg_rules)); +} + +void reg_save_reg_rules_to_pdev( + struct reg_rule_info *psoc_reg_rules, + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) +{ + uint32_t reg_rule_len; + struct reg_rule_info *pdev_reg_rules; + + qdf_spin_lock_bh(&pdev_priv_obj->reg_rules_lock); + + pdev_reg_rules = &pdev_priv_obj->reg_rules; + reg_reset_reg_rules(pdev_reg_rules); + + pdev_reg_rules->num_of_reg_rules = psoc_reg_rules->num_of_reg_rules; + if (!pdev_reg_rules->num_of_reg_rules) { + qdf_spin_unlock_bh(&pdev_priv_obj->reg_rules_lock); + reg_err("no reg rules in psoc"); + return; + } + + reg_rule_len = pdev_reg_rules->num_of_reg_rules * + sizeof(struct cur_reg_rule); + qdf_mem_copy(pdev_reg_rules->reg_rules, psoc_reg_rules->reg_rules, + reg_rule_len); + + qdf_mem_copy(pdev_reg_rules->alpha2, pdev_priv_obj->current_country, + REG_ALPHA2_LEN + 1); + pdev_reg_rules->dfs_region = pdev_priv_obj->dfs_region; + + qdf_spin_unlock_bh(&pdev_priv_obj->reg_rules_lock); +} + +void reg_propagate_mas_chan_list_to_pdev(struct wlan_objmgr_psoc *psoc, + void *object, void *arg) +{ + struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)object; + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + enum direction *dir = arg; + uint32_t pdev_id; + struct wlan_lmac_if_reg_tx_ops *reg_tx_ops; + struct reg_rule_info *psoc_reg_rules; + + psoc_priv_obj = (struct wlan_regulatory_psoc_priv_obj *) + wlan_objmgr_psoc_get_comp_private_obj( + psoc, WLAN_UMAC_COMP_REGULATORY); + + if (!psoc_priv_obj) { + reg_err("psoc priv obj is NULL"); + return; + } + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev priv obj is NULL"); + return; + } + + pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + reg_init_pdev_mas_chan_list( + pdev_priv_obj, + &psoc_priv_obj->mas_chan_params[pdev_id]); + psoc_reg_rules = &psoc_priv_obj->mas_chan_params[pdev_id].reg_rules; + reg_save_reg_rules_to_pdev(psoc_reg_rules, pdev_priv_obj); + reg_compute_pdev_current_chan_list(pdev_priv_obj); + + reg_tx_ops = reg_get_psoc_tx_ops(psoc); + if (reg_tx_ops->fill_umac_legacy_chanlist) { + reg_tx_ops->fill_umac_legacy_chanlist( + pdev, pdev_priv_obj->cur_chan_list); + } else { + if (*dir == NORTHBOUND) + reg_send_scheduler_msg_nb(psoc, pdev); + else + reg_send_scheduler_msg_sb(psoc, pdev); + } +} + +QDF_STATUS reg_process_master_chan_list( + struct cur_regulatory_info *regulat_info) +{ + struct wlan_regulatory_psoc_priv_obj *soc_reg; + uint32_t num_2g_reg_rules, num_5g_reg_rules; + struct cur_reg_rule *reg_rule_2g, *reg_rule_5g; + uint16_t min_bw_2g, max_bw_2g, min_bw_5g, max_bw_5g; + struct regulatory_channel *mas_chan_list; + struct wlan_objmgr_psoc *psoc; + enum channel_enum chan_enum; + wlan_objmgr_ref_dbgid dbg_id; + enum direction dir; + uint8_t phy_id; + struct wlan_objmgr_pdev *pdev; + struct wlan_lmac_if_reg_tx_ops *tx_ops; + struct reg_rule_info *reg_rules; + QDF_STATUS status; + + psoc = regulat_info->psoc; + soc_reg = reg_get_psoc_obj(psoc); + + if (!IS_VALID_PSOC_REG_OBJ(soc_reg)) { + reg_err("psoc reg component is NULL"); + return QDF_STATUS_E_FAILURE; + } + + tx_ops = reg_get_psoc_tx_ops(psoc); + phy_id = regulat_info->phy_id; + + if (reg_ignore_default_country(soc_reg, regulat_info)) { + status = reg_set_curr_country(soc_reg, regulat_info, tx_ops); + if (QDF_IS_STATUS_SUCCESS(status)) { + reg_debug("WLAN restart - Ignore default CC for phy_id: %u", + phy_id); + return QDF_STATUS_SUCCESS; + } + } + + reg_debug("process reg master chan list"); + + if (soc_reg->offload_enabled) { + dbg_id = WLAN_REGULATORY_NB_ID; + dir = NORTHBOUND; + } else { + dbg_id = WLAN_REGULATORY_SB_ID; + dir = SOUTHBOUND; + } + + if (regulat_info->status_code != REG_SET_CC_STATUS_PASS) { + reg_err("Setting country code failed, status code is %d", + regulat_info->status_code); + + pdev = wlan_objmgr_get_pdev_by_id(psoc, phy_id, dbg_id); + if (!pdev) { + reg_err("pdev is NULL"); + return QDF_STATUS_E_FAILURE; + } + wlan_objmgr_pdev_release_ref(pdev, dbg_id); + + if (tx_ops->set_country_failed) + tx_ops->set_country_failed(pdev); + + return QDF_STATUS_E_FAILURE; + } + + mas_chan_list = soc_reg->mas_chan_params[phy_id].mas_chan_list; + + reg_init_channel_map(regulat_info->dfs_region); + + for (chan_enum = 0; chan_enum < NUM_CHANNELS; + chan_enum++) { + mas_chan_list[chan_enum].chan_num = + channel_map[chan_enum].chan_num; + mas_chan_list[chan_enum].center_freq = + channel_map[chan_enum].center_freq; + mas_chan_list[chan_enum].chan_flags = + REGULATORY_CHAN_DISABLED; + mas_chan_list[chan_enum].state = + CHANNEL_STATE_DISABLE; + mas_chan_list[chan_enum].nol_chan = false; + } + + soc_reg->num_phy = regulat_info->num_phy; + soc_reg->mas_chan_params[phy_id].phybitmap = + regulat_info->phybitmap; + soc_reg->mas_chan_params[phy_id].dfs_region = + regulat_info->dfs_region; + soc_reg->mas_chan_params[phy_id].ctry_code = + regulat_info->ctry_code; + soc_reg->mas_chan_params[phy_id].reg_dmn_pair = + regulat_info->reg_dmn_pair; + qdf_mem_copy(soc_reg->mas_chan_params[phy_id].current_country, + regulat_info->alpha2, + REG_ALPHA2_LEN + 1); + qdf_mem_copy(soc_reg->cur_country, + regulat_info->alpha2, + REG_ALPHA2_LEN + 1); + reg_debug("set cur_country %.2s", soc_reg->cur_country); + + min_bw_2g = regulat_info->min_bw_2g; + max_bw_2g = regulat_info->max_bw_2g; + reg_rule_2g = regulat_info->reg_rules_2g_ptr; + num_2g_reg_rules = regulat_info->num_2g_reg_rules; + reg_update_max_bw_per_rule(num_2g_reg_rules, + reg_rule_2g, max_bw_2g); + + min_bw_5g = regulat_info->min_bw_5g; + max_bw_5g = regulat_info->max_bw_5g; + reg_rule_5g = regulat_info->reg_rules_5g_ptr; + num_5g_reg_rules = regulat_info->num_5g_reg_rules; + reg_update_max_bw_per_rule(num_5g_reg_rules, + reg_rule_5g, max_bw_5g); + + reg_rules = &soc_reg->mas_chan_params[phy_id].reg_rules; + reg_reset_reg_rules(reg_rules); + + reg_rules->num_of_reg_rules = num_5g_reg_rules + num_2g_reg_rules; + if (reg_rules->num_of_reg_rules > MAX_REG_RULES) { + reg_err("number of reg rules exceeds limit"); + return QDF_STATUS_E_FAILURE; + } + + if (reg_rules->num_of_reg_rules) { + if (num_2g_reg_rules) + qdf_mem_copy(reg_rules->reg_rules, + reg_rule_2g, num_2g_reg_rules * + sizeof(struct cur_reg_rule)); + if (num_5g_reg_rules) + qdf_mem_copy(reg_rules->reg_rules + + num_2g_reg_rules, reg_rule_5g, + num_5g_reg_rules * + sizeof(struct cur_reg_rule)); + } + + if (num_5g_reg_rules != 0) + reg_do_auto_bw_correction(num_5g_reg_rules, + reg_rule_5g, max_bw_5g); + + if (num_2g_reg_rules != 0) + reg_populate_band_channels(MIN_24GHZ_CHANNEL, MAX_24GHZ_CHANNEL, + reg_rule_2g, num_2g_reg_rules, + min_bw_2g, mas_chan_list); + + if (num_5g_reg_rules != 0) + reg_populate_band_channels(MIN_5GHZ_CHANNEL, MAX_5GHZ_CHANNEL, + reg_rule_5g, num_5g_reg_rules, + min_bw_5g, mas_chan_list); + + if (num_5g_reg_rules != 0) + reg_populate_band_channels(MIN_49GHZ_CHANNEL, + MAX_49GHZ_CHANNEL, + reg_rule_5g, num_5g_reg_rules, + min_bw_5g, mas_chan_list); + + if (soc_reg->new_user_ctry_pending[phy_id]) { + soc_reg->new_user_ctry_pending[phy_id] = false; + soc_reg->cc_src = SOURCE_USERSPACE; + soc_reg->user_ctry_set = true; + reg_debug("new user country is set"); + reg_run_11d_state_machine(psoc); + } else if (soc_reg->new_init_ctry_pending[phy_id]) { + soc_reg->new_init_ctry_pending[phy_id] = false; + soc_reg->cc_src = SOURCE_USERSPACE; + reg_debug("new init country is set"); + } else if (soc_reg->new_11d_ctry_pending[phy_id]) { + soc_reg->new_11d_ctry_pending[phy_id] = false; + soc_reg->cc_src = SOURCE_11D; + soc_reg->user_ctry_set = false; + reg_run_11d_state_machine(psoc); + } else if (soc_reg->world_country_pending[phy_id]) { + soc_reg->world_country_pending[phy_id] = false; + soc_reg->cc_src = SOURCE_CORE; + soc_reg->user_ctry_set = false; + reg_run_11d_state_machine(psoc); + } else { + if (soc_reg->cc_src == SOURCE_UNKNOWN && + soc_reg->num_phy == phy_id + 1) + soc_reg->cc_src = SOURCE_DRIVER; + + qdf_mem_copy(soc_reg->mas_chan_params[phy_id].default_country, + regulat_info->alpha2, + REG_ALPHA2_LEN + 1); + + soc_reg->mas_chan_params[phy_id].def_country_code = + regulat_info->ctry_code; + soc_reg->mas_chan_params[phy_id].def_region_domain = + regulat_info->reg_dmn_pair; + + if (soc_reg->cc_src == SOURCE_DRIVER) { + qdf_mem_copy(soc_reg->def_country, + regulat_info->alpha2, + REG_ALPHA2_LEN + 1); + + soc_reg->def_country_code = regulat_info->ctry_code; + soc_reg->def_region_domain = + regulat_info->reg_dmn_pair; + + if (reg_is_world_alpha2(regulat_info->alpha2)) { + soc_reg->cc_src = SOURCE_CORE; + reg_run_11d_state_machine(psoc); + } + } + } + + pdev = wlan_objmgr_get_pdev_by_id(psoc, phy_id, dbg_id); + if (pdev) { + reg_propagate_mas_chan_list_to_pdev(psoc, pdev, &dir); + wlan_objmgr_pdev_release_ref(pdev, dbg_id); + reg_reset_reg_rules(reg_rules); + } + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS reg_get_current_chan_list(struct wlan_objmgr_pdev *pdev, + struct regulatory_channel *chan_list) +{ + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev private obj is NULL"); + return QDF_STATUS_E_FAILURE; + } + + qdf_mem_copy(chan_list, pdev_priv_obj->cur_chan_list, + NUM_CHANNELS * sizeof(struct regulatory_channel)); + + return QDF_STATUS_SUCCESS; +} diff --git a/umac/regulatory/core/src/reg_build_chan_list.h b/umac/regulatory/core/src/reg_build_chan_list.h new file mode 100644 index 000000000000..9c5b511df426 --- /dev/null +++ b/umac/regulatory/core/src/reg_build_chan_list.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2017-2019 The Linux Foundation. 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: reg_build_chan_list.h + * This file provides prototypes of the regulatory component to build master + * and current channel list. + */ + +#ifndef __REG_BUILD_CHAN_LIST_H__ +#define __REG_BUILD_CHAN_LIST_H__ + +/** + * reg_reset_reg_rules() - provides the reg domain rules info + * @reg_rules: reg rules pointer + * + * Return: None + */ +void reg_reset_reg_rules(struct reg_rule_info *reg_rules); + +/** + * reg_init_pdev_mas_chan_list() - Initialize pdev master channel list + * @pdev_priv_obj: Pointer to regdb pdev private object. + * @mas_chan_params: Master channel params. + */ +void reg_init_pdev_mas_chan_list( + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj, + struct mas_chan_params *mas_chan_params); + +/** + * reg_save_reg_rules_to_pdev() - Save psoc reg-rules to pdev. + * @pdev_priv_obj: Pointer to regdb pdev private object. + */ +void reg_save_reg_rules_to_pdev( + struct reg_rule_info *psoc_reg_rules, + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj); + +/** + * reg_compute_pdev_current_chan_list() - Compute pdev current channel list. + * @pdev_priv_obj: Pointer to regdb pdev private object. + */ +void reg_compute_pdev_current_chan_list( + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj); + +/** + * reg_propagate_mas_chan_list_to_pdev() - Propagate master channel list to pdev + * @psoc: Pointer to psoc object. + * @object: Void pointer to pdev object. + * @arg: Pointer to direction. + */ +void reg_propagate_mas_chan_list_to_pdev(struct wlan_objmgr_psoc *psoc, + void *object, void *arg); + +/** + * reg_process_master_chan_list() - Compute master channel list based on the + * regulatory rules. + * @reg_info: Pointer to regulatory info + * + * Return: QDF_STATUS + */ +QDF_STATUS reg_process_master_chan_list(struct cur_regulatory_info *reg_info); + +QDF_STATUS reg_get_current_chan_list(struct wlan_objmgr_pdev *pdev, + struct regulatory_channel *chan_list); + +/** + * reg_update_nol_history_ch() - Set nol-history flag for the channels in the + * list. + * + * @pdev: Pdev ptr. + * @ch_list: Input channel list. + * @num_ch: Number of channels. + * @nol_history_ch: NOL-History flag. + * + * Return: void + */ +void reg_update_nol_history_ch(struct wlan_objmgr_pdev *pdev, + uint8_t *chan_list, + uint8_t num_chan, + bool nol_history_chan); + +#endif diff --git a/umac/regulatory/core/src/reg_db.c b/umac/regulatory/core/src/reg_db.c index 972599eb6a15..c0cd7644990e 100644 --- a/umac/regulatory/core/src/reg_db.c +++ b/umac/regulatory/core/src/reg_db.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -25,6 +25,8 @@ #include #include +#include +#include #include "reg_db.h" enum country_code { diff --git a/umac/regulatory/core/src/reg_db.h b/umac/regulatory/core/src/reg_db.h index 1f0d7dcd0210..fbbc6335c6b3 100644 --- a/umac/regulatory/core/src/reg_db.h +++ b/umac/regulatory/core/src/reg_db.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -25,48 +25,6 @@ #ifndef __REG_DB_H #define __REG_DB_H -#define REGULATORY_CHAN_DISABLED (1<<0) -#define REGULATORY_CHAN_NO_IR (1<<1) -#define REGULATORY_CHAN_RADAR (1<<3) -#define REGULATORY_CHAN_NO_OFDM (1<<6) -#define REGULATORY_CHAN_INDOOR_ONLY (1<<9) - -#define REGULATORY_CHAN_NO_HT40 (1<<4) -#define REGULATORY_CHAN_NO_80MHZ (1<<7) -#define REGULATORY_CHAN_NO_160MHZ (1<<8) -#define REGULATORY_CHAN_NO_20MHZ (1<<11) -#define REGULATORY_CHAN_NO_10MHZ (1<<12) - -#define REGULATORY_PHYMODE_NO11A (1<<0) -#define REGULATORY_PHYMODE_NO11B (1<<1) -#define REGULATORY_PHYMODE_NO11G (1<<2) -#define REGULATORY_CHAN_NO11N (1<<3) -#define REGULATORY_PHYMODE_NO11AC (1<<4) -#define REGULATORY_PHYMODE_NO11AX (1<<5) - -#define MAX_REG_RULES 10 -#define REG_ALPHA2_LEN 2 - -/** - * enum dfs_reg - DFS region - * @DFS_UNINIT_REGION: un-initialized region - * @DFS_FCC_REGION: FCC region - * @DFS_ETSI_REGION: ETSI region - * @DFS_MKK_REGION: MKK region - * @DFS_CN_REGION: China region - * @DFS_KR_REGION: Korea region - * @DFS_UNDEF_REGION: Undefined region - */ -enum dfs_reg { - DFS_UNINIT_REGION = 0, - DFS_FCC_REGION = 1, - DFS_ETSI_REGION = 2, - DFS_MKK_REGION = 3, - DFS_CN_REGION = 4, - DFS_KR_REGION = 5, - DFS_UNDEF_REGION = 0xFFFF, -}; - /** * struct regulatory_rule * @start_freq: start frequency diff --git a/umac/regulatory/core/src/reg_db_parser.c b/umac/regulatory/core/src/reg_db_parser.c index c31da8fd0b83..31037fbb43ad 100644 --- a/umac/regulatory/core/src/reg_db_parser.c +++ b/umac/regulatory/core/src/reg_db_parser.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -23,10 +23,14 @@ */ #include +#include +#include +#include "reg_db.h" #include "reg_db_parser.h" #include -#include "reg_priv.h" -#include "reg_services.h" +#include +#include "reg_priv_objs.h" +#include "reg_getset.h" QDF_STATUS reg_is_country_code_valid(uint8_t *alpha2) { @@ -37,7 +41,7 @@ QDF_STATUS reg_is_country_code_valid(uint8_t *alpha2) for (i = 0; i < num_countries; i++) { if ((g_all_countries[i].alpha2[0] == alpha2[0]) && - (g_all_countries[i].alpha2[1] == alpha2[1])) + (g_all_countries[i].alpha2[1] == alpha2[1])) return QDF_STATUS_SUCCESS; else continue; @@ -46,11 +50,9 @@ QDF_STATUS reg_is_country_code_valid(uint8_t *alpha2) return QDF_STATUS_E_FAILURE; } -QDF_STATUS reg_regrules_assign(uint8_t dmn_id_2g, - uint8_t dmn_id_5g, - uint8_t ant_gain_2g, - uint8_t ant_gain_5g, - struct cur_regulatory_info *reg_info) +QDF_STATUS reg_regrules_assign(uint8_t dmn_id_2g, uint8_t dmn_id_5g, + uint8_t ant_gain_2g, uint8_t ant_gain_5g, + struct cur_regulatory_info *reg_info) { uint8_t k; @@ -88,8 +90,8 @@ QDF_STATUS reg_regrules_assign(uint8_t dmn_id_2g, } QDF_STATUS reg_get_rdpair_from_country_iso(uint8_t *alpha2, - uint16_t *country_index, - uint16_t *regdmn_pair) + uint16_t *country_index, + uint16_t *regdmn_pair) { uint16_t i, j; int num_countries; @@ -100,7 +102,7 @@ QDF_STATUS reg_get_rdpair_from_country_iso(uint8_t *alpha2, for (i = 0; i < num_countries; i++) { if ((g_all_countries[i].alpha2[0] == alpha2[0]) && - (g_all_countries[i].alpha2[1] == alpha2[1])) + (g_all_countries[i].alpha2[1] == alpha2[1])) break; } @@ -127,7 +129,7 @@ QDF_STATUS reg_get_rdpair_from_country_iso(uint8_t *alpha2, } QDF_STATUS reg_get_rdpair_from_regdmn_id(uint16_t regdmn_id, - uint16_t *regdmn_pair) + uint16_t *regdmn_pair) { uint16_t j; int num_reg_dmn; @@ -150,8 +152,8 @@ QDF_STATUS reg_get_rdpair_from_regdmn_id(uint16_t regdmn_id, } QDF_STATUS reg_get_rdpair_from_country_code(uint16_t cc, - uint16_t *country_index, - uint16_t *regdmn_pair) + uint16_t *country_index, + uint16_t *regdmn_pair) { uint16_t i, j; int num_countries; @@ -244,8 +246,8 @@ static inline QDF_STATUS reg_get_reginfo_form_country_code_and_regdmn_pair( ant_gain_2g, ant_gain_5g, reg_info); if (err == QDF_STATUS_E_FAILURE) { - reg_err("%s : No rule found for country index = %d regdmn_pair = %d\n", - __func__, country_index, regdmn_pair); + reg_err("%s : No rule found for country index = %d regdmn_pair = %d", + __func__, country_index, regdmn_pair); return QDF_STATUS_E_FAILURE; } @@ -323,21 +325,16 @@ static inline QDF_STATUS reg_get_reginfo_form_regdmn_pair( return QDF_STATUS_SUCCESS; } -/* Given a country code the function finds current regulatory information */ QDF_STATUS reg_get_cur_reginfo(struct cur_regulatory_info *reg_info, - uint16_t country_index, - uint16_t regdmn_pair) + uint16_t country_index, + uint16_t regdmn_pair) { if ((country_index != (uint16_t)(-1)) && - (regdmn_pair != (uint16_t)(-1))) + (regdmn_pair != (uint16_t)(-1))) return reg_get_reginfo_form_country_code_and_regdmn_pair( - reg_info, - country_index, - regdmn_pair); + reg_info, country_index, regdmn_pair); else if (regdmn_pair != (uint16_t)(-1)) - return reg_get_reginfo_form_regdmn_pair( - reg_info, - regdmn_pair); + return reg_get_reginfo_form_regdmn_pair(reg_info, regdmn_pair); else return QDF_STATUS_E_FAILURE; diff --git a/umac/regulatory/core/src/reg_db_parser.h b/umac/regulatory/core/src/reg_db_parser.h index ef4731441f3b..4d945e17fe55 100644 --- a/umac/regulatory/core/src/reg_db_parser.h +++ b/umac/regulatory/core/src/reg_db_parser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -22,7 +22,8 @@ * This file contains regulatory data base parser function declarations */ -#include +#ifndef __REG_DB_PARSER_H +#define __REG_DB_PARSER_H extern const struct country_code_to_reg_domain g_all_countries[]; extern const struct reg_domain_pair g_reg_dmn_pairs[]; @@ -31,25 +32,71 @@ extern const struct regdomain regdomains_2g[]; extern const struct regulatory_rule reg_rules_5g[]; extern const struct regdomain regdomains_5g[]; +/** + * reg_is_country_code_valid() - Check if the given country code is valid + * @alpha2: Country string + * + * Return: QDF_STATUS + */ QDF_STATUS reg_is_country_code_valid(uint8_t *alpha2); -QDF_STATUS reg_regrules_assign(uint8_t dmn_id_2g, - uint8_t dmn_id_5g, - uint8_t ant_gain_2g, - uint8_t ant_gain_5g, - struct cur_regulatory_info *reg_info); +/** + * reg_regrules_assign() - Get 2GHz and 5GHz regulatory rules from regdomain + * structure. + * @dmn_id_2g: 2GHz regdomain ID + * @dmn_id_5g: 5GHz regdomain ID + * @ant_gain_2g: 2GHz antenna gain + * @ant_gain_5g: 5GHz antenna gain + * @reg_info: Pointer to current regulatory info structure + * + * Return: QDF_STATUS + */ +QDF_STATUS reg_regrules_assign(uint8_t dmn_id_2g, uint8_t dmn_id_5g, + uint8_t ant_gain_2g, uint8_t ant_gain_5g, + struct cur_regulatory_info *reg_info); +/** + * reg_get_cur_reginfo() - Get current regulatory info for a given country code + * @reg_info: Pointer to current regulatory info structure + * @country_index: Country code index in the country code table + * @regdmn_pair: Regdomain pair ID + * + * Return: QDF_STATUS + */ QDF_STATUS reg_get_cur_reginfo(struct cur_regulatory_info *reg_info, - uint16_t country_index, - uint16_t regdmn_pair); + uint16_t country_index, uint16_t regdmn_pair); +/** + * reg_get_rdpair_from_country_iso() - Get regdomain pair ID from country string + * @alpha: Pointer to country code string + * @country_index: Pointer to save country code index + * @regdmn_pair: Pointer to save regdomain pair ID index + * + * Return: QDF_STATUS + */ QDF_STATUS reg_get_rdpair_from_country_iso(uint8_t *alpha, - uint16_t *country_index, - uint16_t *regdmn_pair); + uint16_t *country_index, + uint16_t *regdmn_pair); +/** + * reg_get_rdpair_from_country_code() - Get regdomain pair ID from country code + * @cc: Country code + * @country_index: Pointer to save country code index + * @regdmn_pair: Pointer to save regdomain pair ID index + * + * Return: QDF_STATUS + */ QDF_STATUS reg_get_rdpair_from_country_code(uint16_t cc, - uint16_t *country_index, - uint16_t *regdmn_pair); + uint16_t *country_index, + uint16_t *regdmn_pair); +/** + * reg_get_rdpair_from_regdmn_id() - Get regdomain pair ID from regdomain ID + * @regdmn_id: Regdomain ID + * @regdmn_pair: Pointer to save regdomain pair ID index + * + * Return: QDF_STATUS + */ QDF_STATUS reg_get_rdpair_from_regdmn_id(uint16_t regdmn_id, - uint16_t *regdmn_pair); + uint16_t *regdmn_pair); +#endif diff --git a/umac/regulatory/core/src/reg_priv_objs.c b/umac/regulatory/core/src/reg_priv_objs.c new file mode 100644 index 000000000000..5c8e67453f64 --- /dev/null +++ b/umac/regulatory/core/src/reg_priv_objs.c @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2014-2019 The Linux Foundation. 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: reg_priv_objs.c + * This file defines the APIs to create regulatory private PSOC and PDEV + * objects. + */ + +#include +#include +#include +#include +#include +#include "reg_priv_objs.h" +#include "reg_getset.h" +#include "reg_services_common.h" +#include "reg_build_chan_list.h" +#include "reg_host_11d.h" + +struct wlan_regulatory_psoc_priv_obj *reg_get_psoc_obj( + struct wlan_objmgr_psoc *psoc) +{ + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + + if (!psoc) { + reg_alert("psoc is NULL"); + return NULL; + } + psoc_priv_obj = wlan_objmgr_psoc_get_comp_private_obj( + psoc, WLAN_UMAC_COMP_REGULATORY); + + return psoc_priv_obj; +} + +struct wlan_regulatory_pdev_priv_obj *reg_get_pdev_obj( + struct wlan_objmgr_pdev *pdev) +{ + struct wlan_regulatory_pdev_priv_obj *pdev_reg; + + if (!pdev) { + reg_alert("pdev is NULL"); + return NULL; + } + + pdev_reg = wlan_objmgr_pdev_get_comp_private_obj( + pdev, WLAN_UMAC_COMP_REGULATORY); + + return pdev_reg; +} + +QDF_STATUS wlan_regulatory_psoc_obj_created_notification( + struct wlan_objmgr_psoc *psoc, void *arg_list) +{ + struct wlan_regulatory_psoc_priv_obj *soc_reg_obj; + struct regulatory_channel *mas_chan_list; + enum channel_enum chan_enum; + QDF_STATUS status; + uint8_t i; + uint8_t pdev_cnt; + + soc_reg_obj = qdf_mem_malloc(sizeof(*soc_reg_obj)); + if (!soc_reg_obj) { + reg_alert("Mem alloc failed for reg psoc priv obj"); + return QDF_STATUS_E_NOMEM; + } + + soc_reg_obj->offload_enabled = false; + soc_reg_obj->psoc_ptr = psoc; + soc_reg_obj->dfs_enabled = true; + soc_reg_obj->band_capability = BAND_ALL; + soc_reg_obj->enable_11d_supp = false; + soc_reg_obj->indoor_chan_enabled = true; + soc_reg_obj->force_ssc_disable_indoor_channel = false; + soc_reg_obj->master_vdev_cnt = 0; + soc_reg_obj->vdev_cnt_11d = 0; + soc_reg_obj->restart_beaconing = CH_AVOID_RULE_RESTART; + soc_reg_obj->enable_srd_chan_in_master_mode = false; + soc_reg_obj->enable_11d_in_world_mode = false; + soc_reg_obj->def_pdev_id = -1; + + for (i = 0; i < MAX_STA_VDEV_CNT; i++) + soc_reg_obj->vdev_ids_11d[i] = INVALID_VDEV_ID; + + qdf_spinlock_create(&soc_reg_obj->cbk_list_lock); + + for (pdev_cnt = 0; pdev_cnt < PSOC_MAX_PHY_REG_CAP; pdev_cnt++) { + mas_chan_list = + soc_reg_obj->mas_chan_params[pdev_cnt].mas_chan_list; + + for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { + mas_chan_list[chan_enum].chan_flags |= + REGULATORY_CHAN_DISABLED; + mas_chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; + mas_chan_list[chan_enum].nol_chan = false; + } + } + + status = wlan_objmgr_psoc_component_obj_attach( + psoc, WLAN_UMAC_COMP_REGULATORY, soc_reg_obj, + QDF_STATUS_SUCCESS); + if (QDF_IS_STATUS_ERROR(status)) { + qdf_spinlock_destroy(&soc_reg_obj->cbk_list_lock); + qdf_mem_free(soc_reg_obj); + reg_err("Obj attach failed"); + return status; + } + + reg_debug("reg psoc obj created with status %d", status); + + return status; +} + +QDF_STATUS wlan_regulatory_psoc_obj_destroyed_notification( + struct wlan_objmgr_psoc *psoc, void *arg_list) +{ + QDF_STATUS status; + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + + psoc_priv_obj = reg_get_psoc_obj(psoc); + if (!psoc_priv_obj) { + reg_err("reg psoc private obj is NULL"); + return QDF_STATUS_E_FAULT; + } + + psoc_priv_obj->psoc_ptr = NULL; + qdf_spinlock_destroy(&psoc_priv_obj->cbk_list_lock); + + status = wlan_objmgr_psoc_component_obj_detach( + psoc, WLAN_UMAC_COMP_REGULATORY, psoc_priv_obj); + + if (status != QDF_STATUS_SUCCESS) + reg_err("psoc_priv_obj private obj detach failed"); + + reg_debug("reg psoc obj detached with status %d", status); + + qdf_mem_free(psoc_priv_obj); + + return status; +} + +QDF_STATUS wlan_regulatory_pdev_obj_created_notification( + struct wlan_objmgr_pdev *pdev, void *arg_list) +{ + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap_ptr; + struct wlan_objmgr_psoc *parent_psoc; + uint32_t pdev_id; + uint32_t cnt; + uint32_t range_2g_low, range_2g_high; + uint32_t range_5g_low, range_5g_high; + QDF_STATUS status; + struct reg_rule_info *psoc_reg_rules; + + pdev_priv_obj = qdf_mem_malloc(sizeof(*pdev_priv_obj)); + if (!pdev_priv_obj) { + reg_alert("Mem alloc failed for pdev priv obj"); + return QDF_STATUS_E_NOMEM; + } + + parent_psoc = wlan_pdev_get_psoc(pdev); + pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + + psoc_priv_obj = reg_get_psoc_obj(parent_psoc); + if (!psoc_priv_obj) { + reg_err("reg psoc private obj is NULL"); + qdf_mem_free(pdev_priv_obj); + return QDF_STATUS_E_FAULT; + } + + if (psoc_priv_obj->def_pdev_id == -1) + psoc_priv_obj->def_pdev_id = pdev_id; + else + reg_err("reg cannot handle more than one pdev"); + + pdev_priv_obj->pdev_ptr = pdev; + pdev_priv_obj->dfs_enabled = psoc_priv_obj->dfs_enabled; + pdev_priv_obj->set_fcc_channel = false; + pdev_priv_obj->band_capability = psoc_priv_obj->band_capability; + pdev_priv_obj->indoor_chan_enabled = + psoc_priv_obj->indoor_chan_enabled; + pdev_priv_obj->en_chan_144 = true; + + qdf_spinlock_create(&pdev_priv_obj->reg_rules_lock); + + reg_cap_ptr = psoc_priv_obj->reg_cap; + pdev_priv_obj->force_ssc_disable_indoor_channel = + psoc_priv_obj->force_ssc_disable_indoor_channel; + + for (cnt = 0; cnt < PSOC_MAX_PHY_REG_CAP; cnt++) { + if (!reg_cap_ptr) { + qdf_mem_free(pdev_priv_obj); + reg_err("reg cap ptr is NULL"); + return QDF_STATUS_E_FAULT; + } + + if (reg_cap_ptr->phy_id == pdev_id) + break; + reg_cap_ptr++; + } + + if (cnt == PSOC_MAX_PHY_REG_CAP) { + qdf_mem_free(pdev_priv_obj); + reg_err("extended capabilities not found for pdev"); + return QDF_STATUS_E_FAULT; + } + + range_2g_low = reg_cap_ptr->low_2ghz_chan; + range_2g_high = reg_cap_ptr->high_2ghz_chan; + range_5g_low = reg_cap_ptr->low_5ghz_chan; + range_5g_high = reg_cap_ptr->high_5ghz_chan; + + pdev_priv_obj->range_2g_low = range_2g_low; + pdev_priv_obj->range_2g_high = range_2g_high; + pdev_priv_obj->range_5g_low = range_5g_low; + pdev_priv_obj->range_5g_high = range_5g_high; + pdev_priv_obj->wireless_modes = reg_cap_ptr->wireless_modes; + + reg_init_pdev_mas_chan_list(pdev_priv_obj, + &psoc_priv_obj->mas_chan_params[pdev_id]); + + reg_compute_pdev_current_chan_list(pdev_priv_obj); + + psoc_reg_rules = &psoc_priv_obj->mas_chan_params[pdev_id].reg_rules; + reg_save_reg_rules_to_pdev(psoc_reg_rules, pdev_priv_obj); + + reg_reset_reg_rules(psoc_reg_rules); + + status = wlan_objmgr_pdev_component_obj_attach( + pdev, WLAN_UMAC_COMP_REGULATORY, pdev_priv_obj, + QDF_STATUS_SUCCESS); + if (QDF_IS_STATUS_ERROR(status)) { + reg_err("Obj attach failed"); + qdf_mem_free(pdev_priv_obj); + return status; + } + if (!psoc_priv_obj->is_11d_offloaded) + reg_11d_host_scan_init(parent_psoc); + + reg_debug("reg pdev obj created with status %d", status); + + return status; +} + +QDF_STATUS wlan_regulatory_pdev_obj_destroyed_notification( + struct wlan_objmgr_pdev *pdev, void *arg_list) +{ + QDF_STATUS status; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev private obj is NULL"); + return QDF_STATUS_E_FAILURE; + } + + psoc_priv_obj = reg_get_psoc_obj(wlan_pdev_get_psoc(pdev)); + if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { + reg_err("reg psoc private obj is NULL"); + return QDF_STATUS_E_FAILURE; + } + + if (!psoc_priv_obj->is_11d_offloaded) + reg_11d_host_scan_deinit(wlan_pdev_get_psoc(pdev)); + + pdev_priv_obj->pdev_ptr = NULL; + + status = wlan_objmgr_pdev_component_obj_detach( + pdev, WLAN_UMAC_COMP_REGULATORY, pdev_priv_obj); + + if (status != QDF_STATUS_SUCCESS) + reg_err("reg pdev private obj detach failed"); + + reg_debug("reg pdev obj deleted with status %d", status); + + qdf_spin_lock_bh(&pdev_priv_obj->reg_rules_lock); + reg_reset_reg_rules(&pdev_priv_obj->reg_rules); + qdf_spin_unlock_bh(&pdev_priv_obj->reg_rules_lock); + + qdf_spinlock_destroy(&pdev_priv_obj->reg_rules_lock); + + qdf_mem_free(pdev_priv_obj); + + return status; +} diff --git a/umac/regulatory/core/src/reg_priv.h b/umac/regulatory/core/src/reg_priv_objs.h similarity index 63% rename from umac/regulatory/core/src/reg_priv.h rename to umac/regulatory/core/src/reg_priv_objs.h index 16bbfa4525e0..031a8b6b2d6c 100644 --- a/umac/regulatory/core/src/reg_priv.h +++ b/umac/regulatory/core/src/reg_priv_objs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -18,18 +18,12 @@ */ /** - * DOC: reg_priv.h + * DOC: reg_priv_objs.h * This file contains regulatory component private data structures. */ -#ifndef __REG_PRIV_H -#define __REG_PRIV_H - -#include "reg_db.h" -#include "reg_services.h" -#ifdef HOST_11D_SCAN -#include -#endif +#ifndef __REG_PRIV_OBJS_H +#define __REG_PRIV_OBJS_H #define reg_alert(params...) \ QDF_TRACE_FATAL(QDF_MODULE_ID_REGULATORY, params) @@ -57,6 +51,31 @@ #define reg_nofl_debug(params...) \ QDF_TRACE_DEBUG_NO_FL(QDF_MODULE_ID_REGULATORY, params) +/** + * typedef reg_chan_change_callback() - Regulatory channel change callback + * @psoc: Pointer to psoc + * @pdev: Pointer to pdev + * @chan_list: Pointer to regulatory channel list + * @avoid_freq_ind: Pointer to avoid frequencies + * @arg: list of arguments + */ +typedef void (*reg_chan_change_callback)( + struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev, + struct regulatory_channel *chan_list, + struct avoid_freq_ind_data *avoid_freq_ind, + void *arg); + +/** + * struct chan_change_cbk_entry - Channel change callback entry + * @cbk: Callback + * @arg: Arguments + */ +struct chan_change_cbk_entry { + reg_chan_change_callback cbk; + void *arg; +}; + /** * struct wlan_regulatory_psoc_priv_obj - wlan regulatory psoc private object * @new_user_ctry_pending: In this array, element[phy_id] is true if any user @@ -151,4 +170,73 @@ struct wlan_regulatory_pdev_priv_obj { qdf_spinlock_t reg_rules_lock; }; +/** + * reg_get_psoc_obj() - Provides the reg component object pointer + * @psoc: pointer to psoc object. + * + * Return: reg component object pointer + */ +struct wlan_regulatory_psoc_priv_obj *reg_get_psoc_obj( + struct wlan_objmgr_psoc *psoc); + +/** + * reg_get_pdev_obj() - Provides the reg component object pointer + * @psoc: pointer to psoc object. + * + * Return: reg component object pointer + */ +struct wlan_regulatory_pdev_priv_obj *reg_get_pdev_obj( + struct wlan_objmgr_pdev *pdev); + +/** + * wlan_regulatory_psoc_obj_created_notification() - PSOC obj create callback + * @psoc: PSOC object + * @arg_list: Variable argument list + * + * This callback is registered with object manager during initialization to + * get notified when the object is created. + * + * Return: Success or Failure + */ +QDF_STATUS wlan_regulatory_psoc_obj_created_notification( + struct wlan_objmgr_psoc *psoc, void *arg_list); + +/** + * wlan_regulatory_psoc_obj_destroyed_notification() - PSOC obj delete callback + * @psoc: PSOC object + * @arg_list: Variable argument list + * + * This callback is registered with object manager during initialization to + * get notified when the object is deleted. + * + * Return: Success or Failure + */ +QDF_STATUS wlan_regulatory_psoc_obj_destroyed_notification( + struct wlan_objmgr_psoc *psoc, void *arg_list); + +/** + * wlan_regulatory_pdev_obj_created_notification() - PDEV obj create callback + * @pdev: pdev object + * @arg_list: Variable argument list + * + * This callback is registered with object manager during initialization to + * get notified when the pdev object is created. + * + * Return: Success or Failure + */ +QDF_STATUS wlan_regulatory_pdev_obj_created_notification( + struct wlan_objmgr_pdev *pdev, void *arg_list); + +/** + * wlan_regulatory_pdev_obj_destroyed_notification() - PDEV obj destroy callback + * @pdev: pdev object + * @arg_list: Variable argument list + * + * This callback is registered with object manager during initialization to + * get notified when the pdev object is destroyed. + * + * Return: Success or Failure + */ +QDF_STATUS wlan_regulatory_pdev_obj_destroyed_notification( + struct wlan_objmgr_pdev *pdev, void *arg_list); #endif diff --git a/umac/regulatory/core/src/reg_services_common.c b/umac/regulatory/core/src/reg_services_common.c new file mode 100644 index 000000000000..780d30ad32ac --- /dev/null +++ b/umac/regulatory/core/src/reg_services_common.c @@ -0,0 +1,1958 @@ +/* + * Copyright (c) 2014-2019 The Linux Foundation. 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: reg_services_common.c + * This file defines regulatory component service functions + */ + +#include +#include +#include +#include +#include "reg_priv_objs.h" +#include "reg_getset.h" +#include "reg_callbacks.h" +#include "reg_services_common.h" +#include +#include "reg_db.h" +#include "reg_db_parser.h" +#include "reg_build_chan_list.h" +#include + +const struct chan_map *channel_map; + +static const struct bonded_channel bonded_chan_40mhz_list[] = { + {36, 40}, + {44, 48}, + {52, 56}, + {60, 64}, + {100, 104}, + {108, 112}, + {116, 120}, + {124, 128}, + {132, 136}, + {140, 144}, + {149, 153}, + {157, 161} +}; + +static const struct bonded_channel bonded_chan_80mhz_list[] = { + {36, 48}, + {52, 64}, + {100, 112}, + {116, 128}, + {132, 144}, + {149, 161} +}; + +static const struct bonded_channel bonded_chan_160mhz_list[] = { + {36, 64}, + {100, 128} +}; + +static const enum phy_ch_width get_next_lower_bw[] = { + [CH_WIDTH_80P80MHZ] = CH_WIDTH_160MHZ, + [CH_WIDTH_160MHZ] = CH_WIDTH_80MHZ, + [CH_WIDTH_80MHZ] = CH_WIDTH_40MHZ, + [CH_WIDTH_40MHZ] = CH_WIDTH_20MHZ, + [CH_WIDTH_20MHZ] = CH_WIDTH_10MHZ, + [CH_WIDTH_10MHZ] = CH_WIDTH_5MHZ, + [CH_WIDTH_5MHZ] = CH_WIDTH_INVALID +}; + +#ifdef CONFIG_LEGACY_CHAN_ENUM +static const struct chan_map channel_map_old[NUM_CHANNELS] = { + [CHAN_ENUM_1] = {2412, 1, 2, 40}, + [CHAN_ENUM_2] = {2417, 2, 2, 40}, + [CHAN_ENUM_3] = {2422, 3, 2, 40}, + [CHAN_ENUM_4] = {2427, 4, 2, 40}, + [CHAN_ENUM_5] = {2432, 5, 2, 40}, + [CHAN_ENUM_6] = {2437, 6, 2, 40}, + [CHAN_ENUM_7] = {2442, 7, 2, 40}, + [CHAN_ENUM_8] = {2447, 8, 2, 40}, + [CHAN_ENUM_9] = {2452, 9, 2, 40}, + [CHAN_ENUM_10] = {2457, 10, 2, 40}, + [CHAN_ENUM_11] = {2462, 11, 2, 40}, + [CHAN_ENUM_12] = {2467, 12, 2, 40}, + [CHAN_ENUM_13] = {2472, 13, 2, 40}, + [CHAN_ENUM_14] = {2484, 14, 2, 40}, + + [CHAN_ENUM_36] = {5180, 36, 2, 160}, + [CHAN_ENUM_40] = {5200, 40, 2, 160}, + [CHAN_ENUM_44] = {5220, 44, 2, 160}, + [CHAN_ENUM_48] = {5240, 48, 2, 160}, + [CHAN_ENUM_52] = {5260, 52, 2, 160}, + [CHAN_ENUM_56] = {5280, 56, 2, 160}, + [CHAN_ENUM_60] = {5300, 60, 2, 160}, + [CHAN_ENUM_64] = {5320, 64, 2, 160}, + + [CHAN_ENUM_100] = {5500, 100, 2, 160}, + [CHAN_ENUM_104] = {5520, 104, 2, 160}, + [CHAN_ENUM_108] = {5540, 108, 2, 160}, + [CHAN_ENUM_112] = {5560, 112, 2, 160}, + [CHAN_ENUM_116] = {5580, 116, 2, 160}, + [CHAN_ENUM_120] = {5600, 120, 2, 160}, + [CHAN_ENUM_124] = {5620, 124, 2, 160}, + [CHAN_ENUM_128] = {5640, 128, 2, 160}, + [CHAN_ENUM_132] = {5660, 132, 2, 160}, + [CHAN_ENUM_136] = {5680, 136, 2, 160}, + [CHAN_ENUM_140] = {5700, 140, 2, 160}, + [CHAN_ENUM_144] = {5720, 144, 2, 160}, + + [CHAN_ENUM_149] = {5745, 149, 2, 160}, + [CHAN_ENUM_153] = {5765, 153, 2, 160}, + [CHAN_ENUM_157] = {5785, 157, 2, 160}, + [CHAN_ENUM_161] = {5805, 161, 2, 160}, + [CHAN_ENUM_165] = {5825, 165, 2, 160}, +#ifndef WLAN_FEATURE_DSRC + [CHAN_ENUM_169] = {5845, 169, 2, 20}, + [CHAN_ENUM_173] = {5865, 173, 2, 20}, +#else + [CHAN_ENUM_170] = {5852, 170, 2, 20}, + [CHAN_ENUM_171] = {5855, 171, 2, 20}, + [CHAN_ENUM_172] = {5860, 172, 2, 20}, + [CHAN_ENUM_173] = {5865, 173, 2, 20}, + [CHAN_ENUM_174] = {5870, 174, 2, 20}, + [CHAN_ENUM_175] = {5875, 175, 2, 20}, + [CHAN_ENUM_176] = {5880, 176, 2, 20}, + [CHAN_ENUM_177] = {5885, 177, 2, 20}, + [CHAN_ENUM_178] = {5890, 178, 2, 20}, + [CHAN_ENUM_179] = {5895, 179, 2, 20}, + [CHAN_ENUM_180] = {5900, 180, 2, 20}, + [CHAN_ENUM_181] = {5905, 181, 2, 20}, + [CHAN_ENUM_182] = {5910, 182, 2, 20}, + [CHAN_ENUM_183] = {5915, 183, 2, 20}, + [CHAN_ENUM_184] = {5920, 184, 2, 20}, +#endif +}; + +#else +static const struct chan_map channel_map_us[NUM_CHANNELS] = { + [CHAN_ENUM_2412] = {2412, 1, 20, 40}, + [CHAN_ENUM_2417] = {2417, 2, 20, 40}, + [CHAN_ENUM_2422] = {2422, 3, 20, 40}, + [CHAN_ENUM_2427] = {2427, 4, 20, 40}, + [CHAN_ENUM_2432] = {2432, 5, 20, 40}, + [CHAN_ENUM_2437] = {2437, 6, 20, 40}, + [CHAN_ENUM_2442] = {2442, 7, 20, 40}, + [CHAN_ENUM_2447] = {2447, 8, 20, 40}, + [CHAN_ENUM_2452] = {2452, 9, 20, 40}, + [CHAN_ENUM_2457] = {2457, 10, 20, 40}, + [CHAN_ENUM_2462] = {2462, 11, 20, 40}, + [CHAN_ENUM_2467] = {2467, 12, 20, 40}, + [CHAN_ENUM_2472] = {2472, 13, 20, 40}, + [CHAN_ENUM_2484] = {2484, 14, 20, 20}, + + [CHAN_ENUM_4912] = {4912, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4915] = {4915, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4917] = {4917, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4920] = {4920, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4922] = {4922, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4925] = {4925, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4927] = {4927, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4932] = {4932, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4935] = {4935, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4937] = {4937, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4940] = {4940, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4942] = {4942, 1, 5, 5}, + [CHAN_ENUM_4945] = {4945, 11, 10, 10}, + [CHAN_ENUM_4947] = {4947, 2, 5, 5}, + [CHAN_ENUM_4950] = {4950, 20, 10, 20}, + [CHAN_ENUM_4952] = {4952, 3, 5, 5}, + [CHAN_ENUM_4955] = {4955, 21, 10, 20}, + [CHAN_ENUM_4957] = {4957, 4, 5, 5}, + [CHAN_ENUM_4960] = {4960, 22, 10, 20}, + [CHAN_ENUM_4962] = {4962, 5, 5, 5}, + [CHAN_ENUM_4965] = {4965, 23, 10, 20}, + [CHAN_ENUM_4967] = {4967, 6, 5, 5}, + [CHAN_ENUM_4970] = {4970, 24, 10, 20}, + [CHAN_ENUM_4972] = {4972, 7, 5, 5}, + [CHAN_ENUM_4975] = {4975, 25, 10, 20}, + [CHAN_ENUM_4977] = {4977, 8, 5, 5}, + [CHAN_ENUM_4980] = {4980, 26, 10, 20}, + [CHAN_ENUM_4982] = {4982, 9, 5, 5}, + [CHAN_ENUM_4985] = {4985, 19, 10, 10}, + [CHAN_ENUM_4987] = {4987, 10, 5, 5}, + [CHAN_ENUM_5032] = {5032, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5035] = {5035, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5037] = {5037, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5040] = {5040, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5042] = {5042, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5045] = {5045, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5047] = {5047, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5052] = {5052, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5055] = {5055, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5057] = {5057, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5060] = {5060, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5080] = {5080, INVALID_CHANNEL_NUM, 2, 20}, + + [CHAN_ENUM_5180] = {5180, 36, 2, 160}, + [CHAN_ENUM_5200] = {5200, 40, 2, 160}, + [CHAN_ENUM_5220] = {5220, 44, 2, 160}, + [CHAN_ENUM_5240] = {5240, 48, 2, 160}, + [CHAN_ENUM_5260] = {5260, 52, 2, 160}, + [CHAN_ENUM_5280] = {5280, 56, 2, 160}, + [CHAN_ENUM_5300] = {5300, 60, 2, 160}, + [CHAN_ENUM_5320] = {5320, 64, 2, 160}, + [CHAN_ENUM_5500] = {5500, 100, 2, 160}, + [CHAN_ENUM_5520] = {5520, 104, 2, 160}, + [CHAN_ENUM_5540] = {5540, 108, 2, 160}, + [CHAN_ENUM_5560] = {5560, 112, 2, 160}, + [CHAN_ENUM_5580] = {5580, 116, 2, 160}, + [CHAN_ENUM_5600] = {5600, 120, 2, 160}, + [CHAN_ENUM_5620] = {5620, 124, 2, 160}, + [CHAN_ENUM_5640] = {5640, 128, 2, 160}, + [CHAN_ENUM_5660] = {5660, 132, 2, 160}, + [CHAN_ENUM_5680] = {5680, 136, 2, 160}, + [CHAN_ENUM_5700] = {5700, 140, 2, 160}, + [CHAN_ENUM_5720] = {5720, 144, 2, 160}, + [CHAN_ENUM_5745] = {5745, 149, 2, 160}, + [CHAN_ENUM_5765] = {5765, 153, 2, 160}, + [CHAN_ENUM_5785] = {5785, 157, 2, 160}, + [CHAN_ENUM_5805] = {5805, 161, 2, 160}, + [CHAN_ENUM_5825] = {5825, 165, 2, 160}, + [CHAN_ENUM_5845] = {5845, 169, 2, 160}, + [CHAN_ENUM_5850] = {5850, 170, 2, 160}, + [CHAN_ENUM_5855] = {5855, 171, 2, 160}, + [CHAN_ENUM_5860] = {5860, 172, 2, 160}, + [CHAN_ENUM_5865] = {5865, 173, 2, 160}, + [CHAN_ENUM_5870] = {5870, 174, 2, 160}, + [CHAN_ENUM_5875] = {5875, 175, 2, 160}, + [CHAN_ENUM_5880] = {5880, 176, 2, 160}, + [CHAN_ENUM_5885] = {5885, 177, 2, 160}, + [CHAN_ENUM_5890] = {5890, 178, 2, 160}, + [CHAN_ENUM_5895] = {5895, 179, 2, 160}, + [CHAN_ENUM_5900] = {5900, 180, 2, 160}, + [CHAN_ENUM_5905] = {5905, 181, 2, 160}, + [CHAN_ENUM_5910] = {5910, 182, 2, 160}, + [CHAN_ENUM_5915] = {5915, 183, 2, 160}, + [CHAN_ENUM_5920] = {5920, 184, 2, 160}, +}; + +static const struct chan_map channel_map_eu[NUM_CHANNELS] = { + [CHAN_ENUM_2412] = {2412, 1, 20, 40}, + [CHAN_ENUM_2417] = {2417, 2, 20, 40}, + [CHAN_ENUM_2422] = {2422, 3, 20, 40}, + [CHAN_ENUM_2427] = {2427, 4, 20, 40}, + [CHAN_ENUM_2432] = {2432, 5, 20, 40}, + [CHAN_ENUM_2437] = {2437, 6, 20, 40}, + [CHAN_ENUM_2442] = {2442, 7, 20, 40}, + [CHAN_ENUM_2447] = {2447, 8, 20, 40}, + [CHAN_ENUM_2452] = {2452, 9, 20, 40}, + [CHAN_ENUM_2457] = {2457, 10, 20, 40}, + [CHAN_ENUM_2462] = {2462, 11, 20, 40}, + [CHAN_ENUM_2467] = {2467, 12, 20, 40}, + [CHAN_ENUM_2472] = {2472, 13, 20, 40}, + [CHAN_ENUM_2484] = {2484, 14, 20, 20}, + + [CHAN_ENUM_4912] = {4912, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4915] = {4915, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4917] = {4917, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4920] = {4920, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4922] = {4922, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4925] = {4925, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4927] = {4927, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4932] = {4932, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4935] = {4935, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4937] = {4937, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4940] = {4940, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4942] = {4942, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4945] = {4945, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4947] = {4947, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4950] = {4950, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4952] = {4952, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4955] = {4955, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4957] = {4957, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4960] = {4960, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4962] = {4962, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4965] = {4965, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4967] = {4967, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4970] = {4970, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4972] = {4972, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4975] = {4975, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4977] = {4977, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4980] = {4980, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4982] = {4982, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4985] = {4985, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4987] = {4987, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5032] = {5032, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5035] = {5035, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5037] = {5037, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5040] = {5040, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5042] = {5042, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5045] = {5045, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5047] = {5047, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5052] = {5052, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5055] = {5055, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5057] = {5057, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5060] = {5060, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5080] = {5080, INVALID_CHANNEL_NUM, 2, 20}, + + [CHAN_ENUM_5180] = {5180, 36, 2, 160}, + [CHAN_ENUM_5200] = {5200, 40, 2, 160}, + [CHAN_ENUM_5220] = {5220, 44, 2, 160}, + [CHAN_ENUM_5240] = {5240, 48, 2, 160}, + [CHAN_ENUM_5260] = {5260, 52, 2, 160}, + [CHAN_ENUM_5280] = {5280, 56, 2, 160}, + [CHAN_ENUM_5300] = {5300, 60, 2, 160}, + [CHAN_ENUM_5320] = {5320, 64, 2, 160}, + [CHAN_ENUM_5500] = {5500, 100, 2, 160}, + [CHAN_ENUM_5520] = {5520, 104, 2, 160}, + [CHAN_ENUM_5540] = {5540, 108, 2, 160}, + [CHAN_ENUM_5560] = {5560, 112, 2, 160}, + [CHAN_ENUM_5580] = {5580, 116, 2, 160}, + [CHAN_ENUM_5600] = {5600, 120, 2, 160}, + [CHAN_ENUM_5620] = {5620, 124, 2, 160}, + [CHAN_ENUM_5640] = {5640, 128, 2, 160}, + [CHAN_ENUM_5660] = {5660, 132, 2, 160}, + [CHAN_ENUM_5680] = {5680, 136, 2, 160}, + [CHAN_ENUM_5700] = {5700, 140, 2, 160}, + [CHAN_ENUM_5720] = {5720, 144, 2, 160}, + [CHAN_ENUM_5745] = {5745, 149, 2, 160}, + [CHAN_ENUM_5765] = {5765, 153, 2, 160}, + [CHAN_ENUM_5785] = {5785, 157, 2, 160}, + [CHAN_ENUM_5805] = {5805, 161, 2, 160}, + [CHAN_ENUM_5825] = {5825, 165, 2, 160}, + [CHAN_ENUM_5845] = {5845, 169, 2, 160}, + [CHAN_ENUM_5850] = {5850, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5855] = {5855, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5860] = {5860, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5865] = {5865, 173, 2, 160}, + [CHAN_ENUM_5870] = {5870, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5875] = {5875, 175, 2, 160}, + [CHAN_ENUM_5880] = {5880, 176, 2, 160}, + [CHAN_ENUM_5885] = {5885, 177, 2, 160}, + [CHAN_ENUM_5890] = {5890, 178, 2, 160}, + [CHAN_ENUM_5895] = {5895, 179, 2, 160}, + [CHAN_ENUM_5900] = {5900, 180, 2, 160}, + [CHAN_ENUM_5905] = {5905, 181, 2, 160}, + [CHAN_ENUM_5910] = {5910, 182, 2, 160}, + [CHAN_ENUM_5915] = {5915, 183, 2, 160}, + [CHAN_ENUM_5920] = {5920, 184, 2, 160}, +}; + +static const struct chan_map channel_map_jp[NUM_CHANNELS] = { + [CHAN_ENUM_2412] = {2412, 1, 20, 40}, + [CHAN_ENUM_2417] = {2417, 2, 20, 40}, + [CHAN_ENUM_2422] = {2422, 3, 20, 40}, + [CHAN_ENUM_2427] = {2427, 4, 20, 40}, + [CHAN_ENUM_2432] = {2432, 5, 20, 40}, + [CHAN_ENUM_2437] = {2437, 6, 20, 40}, + [CHAN_ENUM_2442] = {2442, 7, 20, 40}, + [CHAN_ENUM_2447] = {2447, 8, 20, 40}, + [CHAN_ENUM_2452] = {2452, 9, 20, 40}, + [CHAN_ENUM_2457] = {2457, 10, 20, 40}, + [CHAN_ENUM_2462] = {2462, 11, 20, 40}, + [CHAN_ENUM_2467] = {2467, 12, 20, 40}, + [CHAN_ENUM_2472] = {2472, 13, 20, 40}, + [CHAN_ENUM_2484] = {2484, 14, 20, 20}, + + [CHAN_ENUM_4912] = {4912, 182, 5, 5}, + [CHAN_ENUM_4915] = {4915, 183, 10, 10}, + [CHAN_ENUM_4917] = {4917, 183, 5, 5}, + [CHAN_ENUM_4920] = {4920, 184, 10, 20}, + [CHAN_ENUM_4922] = {4922, 184, 5, 5}, + [CHAN_ENUM_4925] = {4925, 185, 10, 10}, + [CHAN_ENUM_4927] = {4927, 185, 5, 5}, + [CHAN_ENUM_4932] = {4932, 186, 5, 5}, + [CHAN_ENUM_4935] = {4935, 187, 10, 10}, + [CHAN_ENUM_4937] = {4937, 187, 5, 5}, + [CHAN_ENUM_4940] = {4940, 188, 10, 20}, + [CHAN_ENUM_4942] = {4942, 188, 5, 5}, + [CHAN_ENUM_4945] = {4945, 189, 10, 10}, + [CHAN_ENUM_4947] = {4947, 189, 5, 5}, + [CHAN_ENUM_4950] = {4950, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4952] = {4952, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4955] = {4955, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4957] = {4957, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4960] = {4960, 192, 20, 20}, + [CHAN_ENUM_4962] = {4962, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4965] = {4965, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4967] = {4967, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4970] = {4970, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4972] = {4972, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4975] = {4975, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4977] = {4977, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4980] = {4980, 196, 20, 20}, + [CHAN_ENUM_4982] = {4982, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4985] = {4985, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4987] = {4987, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5032] = {5032, 6, 5, 5}, + [CHAN_ENUM_5035] = {5035, 7, 10, 10}, + [CHAN_ENUM_5037] = {5037, 7, 5, 5}, + [CHAN_ENUM_5040] = {5040, 8, 10, 20}, + [CHAN_ENUM_5042] = {5042, 8, 5, 5}, + [CHAN_ENUM_5045] = {5045, 9, 10, 10}, + [CHAN_ENUM_5047] = {5047, 9, 5, 5}, + [CHAN_ENUM_5052] = {5052, 10, 5, 5}, + [CHAN_ENUM_5055] = {5055, 11, 10, 10}, + [CHAN_ENUM_5057] = {5057, 11, 5, 5}, + [CHAN_ENUM_5060] = {5060, 12, 20, 20}, + [CHAN_ENUM_5080] = {5080, 16, 20, 20}, + + [CHAN_ENUM_5180] = {5180, 36, 2, 160}, + [CHAN_ENUM_5200] = {5200, 40, 2, 160}, + [CHAN_ENUM_5220] = {5220, 44, 2, 160}, + [CHAN_ENUM_5240] = {5240, 48, 2, 160}, + [CHAN_ENUM_5260] = {5260, 52, 2, 160}, + [CHAN_ENUM_5280] = {5280, 56, 2, 160}, + [CHAN_ENUM_5300] = {5300, 60, 2, 160}, + [CHAN_ENUM_5320] = {5320, 64, 2, 160}, + [CHAN_ENUM_5500] = {5500, 100, 2, 160}, + [CHAN_ENUM_5520] = {5520, 104, 2, 160}, + [CHAN_ENUM_5540] = {5540, 108, 2, 160}, + [CHAN_ENUM_5560] = {5560, 112, 2, 160}, + [CHAN_ENUM_5580] = {5580, 116, 2, 160}, + [CHAN_ENUM_5600] = {5600, 120, 2, 160}, + [CHAN_ENUM_5620] = {5620, 124, 2, 160}, + [CHAN_ENUM_5640] = {5640, 128, 2, 160}, + [CHAN_ENUM_5660] = {5660, 132, 2, 160}, + [CHAN_ENUM_5680] = {5680, 136, 2, 160}, + [CHAN_ENUM_5700] = {5700, 140, 2, 160}, + [CHAN_ENUM_5720] = {5720, 144, 2, 160}, + [CHAN_ENUM_5745] = {5745, 149, 2, 160}, + [CHAN_ENUM_5765] = {5765, 153, 2, 160}, + [CHAN_ENUM_5785] = {5785, 157, 2, 160}, + [CHAN_ENUM_5805] = {5805, 161, 2, 160}, + [CHAN_ENUM_5825] = {5825, 165, 2, 160}, + [CHAN_ENUM_5845] = {5845, 169, 2, 160}, + [CHAN_ENUM_5850] = {5850, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5855] = {5855, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5860] = {5860, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5865] = {5865, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5870] = {5870, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5875] = {5875, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5880] = {5880, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5885] = {5885, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5890] = {5890, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5895] = {5895, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5900] = {5900, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5905] = {5905, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5910] = {5910, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5915] = {5915, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5920] = {5920, INVALID_CHANNEL_NUM, 2, 160}, +}; + +static const struct chan_map channel_map_global[NUM_CHANNELS] = { + [CHAN_ENUM_2412] = {2412, 1, 20, 40}, + [CHAN_ENUM_2417] = {2417, 2, 20, 40}, + [CHAN_ENUM_2422] = {2422, 3, 20, 40}, + [CHAN_ENUM_2427] = {2427, 4, 20, 40}, + [CHAN_ENUM_2432] = {2432, 5, 20, 40}, + [CHAN_ENUM_2437] = {2437, 6, 20, 40}, + [CHAN_ENUM_2442] = {2442, 7, 20, 40}, + [CHAN_ENUM_2447] = {2447, 8, 20, 40}, + [CHAN_ENUM_2452] = {2452, 9, 20, 40}, + [CHAN_ENUM_2457] = {2457, 10, 20, 40}, + [CHAN_ENUM_2462] = {2462, 11, 20, 40}, + [CHAN_ENUM_2467] = {2467, 12, 20, 40}, + [CHAN_ENUM_2472] = {2472, 13, 20, 40}, + [CHAN_ENUM_2484] = {2484, 14, 20, 20}, + + [CHAN_ENUM_4912] = {4912, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4915] = {4915, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4917] = {4917, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4920] = {4920, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4922] = {4922, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4925] = {4925, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4927] = {4927, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4932] = {4932, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4935] = {4935, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4937] = {4937, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4940] = {4940, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4942] = {4942, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4945] = {4945, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4947] = {4947, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4950] = {4950, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4952] = {4952, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4955] = {4955, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4957] = {4957, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4960] = {4960, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4962] = {4962, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4965] = {4965, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4967] = {4967, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4970] = {4970, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4972] = {4972, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4975] = {4975, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4977] = {4977, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4980] = {4980, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4982] = {4982, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4985] = {4985, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4987] = {4987, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5032] = {5032, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5035] = {5035, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5037] = {5037, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5040] = {5040, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5042] = {5042, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5045] = {5045, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5047] = {5047, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5052] = {5052, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5055] = {5055, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5057] = {5057, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5060] = {5060, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5080] = {5080, INVALID_CHANNEL_NUM, 2, 20}, + + [CHAN_ENUM_5180] = {5180, 36, 2, 160}, + [CHAN_ENUM_5200] = {5200, 40, 2, 160}, + [CHAN_ENUM_5220] = {5220, 44, 2, 160}, + [CHAN_ENUM_5240] = {5240, 48, 2, 160}, + [CHAN_ENUM_5260] = {5260, 52, 2, 160}, + [CHAN_ENUM_5280] = {5280, 56, 2, 160}, + [CHAN_ENUM_5300] = {5300, 60, 2, 160}, + [CHAN_ENUM_5320] = {5320, 64, 2, 160}, + [CHAN_ENUM_5500] = {5500, 100, 2, 160}, + [CHAN_ENUM_5520] = {5520, 104, 2, 160}, + [CHAN_ENUM_5540] = {5540, 108, 2, 160}, + [CHAN_ENUM_5560] = {5560, 112, 2, 160}, + [CHAN_ENUM_5580] = {5580, 116, 2, 160}, + [CHAN_ENUM_5600] = {5600, 120, 2, 160}, + [CHAN_ENUM_5620] = {5620, 124, 2, 160}, + [CHAN_ENUM_5640] = {5640, 128, 2, 160}, + [CHAN_ENUM_5660] = {5660, 132, 2, 160}, + [CHAN_ENUM_5680] = {5680, 136, 2, 160}, + [CHAN_ENUM_5700] = {5700, 140, 2, 160}, + [CHAN_ENUM_5720] = {5720, 144, 2, 160}, + [CHAN_ENUM_5745] = {5745, 149, 2, 160}, + [CHAN_ENUM_5765] = {5765, 153, 2, 160}, + [CHAN_ENUM_5785] = {5785, 157, 2, 160}, + [CHAN_ENUM_5805] = {5805, 161, 2, 160}, + [CHAN_ENUM_5825] = {5825, 165, 2, 160}, + [CHAN_ENUM_5845] = {5845, 169, 2, 160}, + [CHAN_ENUM_5850] = {5850, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5855] = {5855, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5860] = {5860, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5865] = {5865, 173, 2, 160}, + [CHAN_ENUM_5870] = {5870, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5875] = {5875, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5880] = {5880, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5885] = {5885, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5890] = {5890, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5895] = {5895, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5900] = {5900, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5905] = {5905, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5910] = {5910, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5915] = {5915, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5920] = {5920, INVALID_CHANNEL_NUM, 2, 160}, +}; + +static const struct chan_map channel_map_china[NUM_CHANNELS] = { + [CHAN_ENUM_2412] = {2412, 1, 20, 40}, + [CHAN_ENUM_2417] = {2417, 2, 20, 40}, + [CHAN_ENUM_2422] = {2422, 3, 20, 40}, + [CHAN_ENUM_2427] = {2427, 4, 20, 40}, + [CHAN_ENUM_2432] = {2432, 5, 20, 40}, + [CHAN_ENUM_2437] = {2437, 6, 20, 40}, + [CHAN_ENUM_2442] = {2442, 7, 20, 40}, + [CHAN_ENUM_2447] = {2447, 8, 20, 40}, + [CHAN_ENUM_2452] = {2452, 9, 20, 40}, + [CHAN_ENUM_2457] = {2457, 10, 20, 40}, + [CHAN_ENUM_2462] = {2462, 11, 20, 40}, + [CHAN_ENUM_2467] = {2467, 12, 20, 40}, + [CHAN_ENUM_2472] = {2472, 13, 20, 40}, + [CHAN_ENUM_2484] = {2484, 14, 20, 20}, + + [CHAN_ENUM_4912] = {4912, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4915] = {4915, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4917] = {4917, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4920] = {4920, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4922] = {4922, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4925] = {4925, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4927] = {4927, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4932] = {4932, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4935] = {4935, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4937] = {4937, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4940] = {4940, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4942] = {4942, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4945] = {4945, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4947] = {4947, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4950] = {4950, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4952] = {4952, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4955] = {4955, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4957] = {4957, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4960] = {4960, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4962] = {4962, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4965] = {4965, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4967] = {4967, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4970] = {4970, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4972] = {4972, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4975] = {4975, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4977] = {4977, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4980] = {4980, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4982] = {4982, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4985] = {4985, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_4987] = {4987, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5032] = {5032, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5035] = {5035, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5037] = {5037, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5040] = {5040, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5042] = {5042, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5045] = {5045, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5047] = {5047, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5052] = {5052, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5055] = {5055, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5057] = {5057, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5060] = {5060, INVALID_CHANNEL_NUM, 2, 20}, + [CHAN_ENUM_5080] = {5080, INVALID_CHANNEL_NUM, 2, 20}, + + [CHAN_ENUM_5180] = {5180, 36, 2, 160}, + [CHAN_ENUM_5200] = {5200, 40, 2, 160}, + [CHAN_ENUM_5220] = {5220, 44, 2, 160}, + [CHAN_ENUM_5240] = {5240, 48, 2, 160}, + [CHAN_ENUM_5260] = {5260, 52, 2, 160}, + [CHAN_ENUM_5280] = {5280, 56, 2, 160}, + [CHAN_ENUM_5300] = {5300, 60, 2, 160}, + [CHAN_ENUM_5320] = {5320, 64, 2, 160}, + [CHAN_ENUM_5500] = {5500, 100, 2, 160}, + [CHAN_ENUM_5520] = {5520, 104, 2, 160}, + [CHAN_ENUM_5540] = {5540, 108, 2, 160}, + [CHAN_ENUM_5560] = {5560, 112, 2, 160}, + [CHAN_ENUM_5580] = {5580, 116, 2, 160}, + [CHAN_ENUM_5600] = {5600, 120, 2, 160}, + [CHAN_ENUM_5620] = {5620, 124, 2, 160}, + [CHAN_ENUM_5640] = {5640, 128, 2, 160}, + [CHAN_ENUM_5660] = {5660, 132, 2, 160}, + [CHAN_ENUM_5680] = {5680, 136, 2, 160}, + [CHAN_ENUM_5700] = {5700, 140, 2, 160}, + [CHAN_ENUM_5720] = {5720, 144, 2, 160}, + [CHAN_ENUM_5745] = {5745, 149, 2, 160}, + [CHAN_ENUM_5765] = {5765, 153, 2, 160}, + [CHAN_ENUM_5785] = {5785, 157, 2, 160}, + [CHAN_ENUM_5805] = {5805, 161, 2, 160}, + [CHAN_ENUM_5825] = {5825, 165, 2, 160}, + [CHAN_ENUM_5845] = {5845, 169, 2, 160}, + [CHAN_ENUM_5850] = {5850, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5855] = {5855, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5860] = {5860, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5865] = {5865, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5870] = {5870, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5875] = {5875, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5880] = {5880, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5885] = {5885, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5890] = {5890, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5895] = {5895, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5900] = {5900, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5905] = {5905, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5910] = {5910, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5915] = {5915, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5920] = {5920, INVALID_CHANNEL_NUM, 2, 160}, +}; +#endif + +#ifdef CONFIG_LEGACY_CHAN_ENUM +void reg_init_channel_map(enum dfs_reg dfs_region) +{ + channel_map = channel_map_old; +} +#else +void reg_init_channel_map(enum dfs_reg dfs_region) +{ + switch (dfs_region) { + case DFS_UNINIT_REGION: + case DFS_UNDEF_REGION: + channel_map = channel_map_global; + break; + case DFS_FCC_REGION: + channel_map = channel_map_us; + break; + case DFS_ETSI_REGION: + channel_map = channel_map_eu; + break; + case DFS_MKK_REGION: + channel_map = channel_map_jp; + break; + case DFS_CN_REGION: + channel_map = channel_map_china; + break; + case DFS_KR_REGION: + channel_map = channel_map_eu; + break; + } +} +#endif + +uint16_t reg_get_bw_value(enum phy_ch_width bw) +{ + switch (bw) { + case CH_WIDTH_20MHZ: + return 20; + case CH_WIDTH_40MHZ: + return 40; + case CH_WIDTH_80MHZ: + return 80; + case CH_WIDTH_160MHZ: + return 160; + case CH_WIDTH_80P80MHZ: + return 160; + case CH_WIDTH_INVALID: + return 0; + case CH_WIDTH_5MHZ: + return 5; + case CH_WIDTH_10MHZ: + return 10; + case CH_WIDTH_MAX: + return 160; + default: + return 0; + } +} + +struct wlan_lmac_if_reg_tx_ops *reg_get_psoc_tx_ops( + struct wlan_objmgr_psoc *psoc) +{ + return &((psoc->soc_cb.tx_ops.reg_ops)); +} + +QDF_STATUS reg_get_channel_list_with_power(struct wlan_objmgr_pdev *pdev, + struct channel_power *ch_list, + uint8_t *num_chan) +{ + int i, count; + struct regulatory_channel *reg_channels; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + + if (!num_chan || !ch_list) { + reg_err("chan_list or num_ch is NULL"); + return QDF_STATUS_E_FAILURE; + } + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev priv obj is NULL"); + return QDF_STATUS_E_FAILURE; + } + + /* set the current channel list */ + reg_channels = pdev_priv_obj->cur_chan_list; + + for (i = 0, count = 0; i < NUM_CHANNELS; i++) { + if (reg_channels[i].state && + reg_channels[i].state != REGULATORY_CHAN_DISABLED) { + ch_list[count].chan_num = + reg_channels[i].chan_num; + ch_list[count++].tx_power = + reg_channels[i].tx_power; + } + } + + *num_chan = count; + + return QDF_STATUS_SUCCESS; +} + +enum channel_enum reg_get_chan_enum(uint32_t chan_num) +{ + uint32_t count; + + for (count = 0; count < NUM_CHANNELS; count++) + if (channel_map[count].chan_num == chan_num) + return count; + + reg_err("invalid channel number %d", chan_num); + + return INVALID_CHANNEL; +} + +enum channel_state reg_get_channel_state(struct wlan_objmgr_pdev *pdev, + uint32_t ch) +{ + enum channel_enum ch_idx; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + + ch_idx = reg_get_chan_enum(ch); + + if (ch_idx == INVALID_CHANNEL) + return CHANNEL_STATE_INVALID; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("pdev reg obj is NULL"); + return CHANNEL_STATE_INVALID; + } + + return pdev_priv_obj->cur_chan_list[ch_idx].state; +} + +/** + * reg_get_5g_bonded_chan_array() - get ptr to bonded channel + * @pdev: Pointer to pdev structure + * @oper_ch: operating channel number + * @bonded_chan_ar: bonded channel array + * @array_size; Array size + * @bonded_chan_ptr_ptr: bonded channel ptr ptr + * + * Return: bonded channel state + */ +static enum channel_state reg_get_5g_bonded_chan_array( + struct wlan_objmgr_pdev *pdev, + uint32_t oper_chan, + const struct bonded_channel bonded_chan_ar[], + uint16_t array_size, + const struct bonded_channel **bonded_chan_ptr_ptr) +{ + int i; + uint8_t chan_num; + const struct bonded_channel *bonded_chan_ptr = NULL; + enum channel_state chan_state = CHANNEL_STATE_INVALID; + enum channel_state temp_chan_state; + + for (i = 0; i < array_size; i++) { + if ((oper_chan >= bonded_chan_ar[i].start_ch) && + (oper_chan <= bonded_chan_ar[i].end_ch)) { + bonded_chan_ptr = &bonded_chan_ar[i]; + break; + } + } + + if (!bonded_chan_ptr) + return chan_state; + + *bonded_chan_ptr_ptr = bonded_chan_ptr; + chan_num = bonded_chan_ptr->start_ch; + while (chan_num <= bonded_chan_ptr->end_ch) { + temp_chan_state = reg_get_channel_state(pdev, chan_num); + if (temp_chan_state < chan_state) + chan_state = temp_chan_state; + chan_num = chan_num + 4; + } + + return chan_state; +} + +/** + * reg_get_5g_bonded_channel() - get the 5G bonded channel state + * @pdev: Pointer to pdev structure + * @chan_num: channel number + * @ch_width: channel width + * @bonded_chan_ptr_ptr: bonded channel ptr ptr + * + * Return: channel state + */ +static enum channel_state reg_get_5g_bonded_channel( + struct wlan_objmgr_pdev *pdev, uint32_t chan_num, + enum phy_ch_width ch_width, + const struct bonded_channel **bonded_chan_ptr_ptr) +{ + if (ch_width == CH_WIDTH_80P80MHZ) + return reg_get_5g_bonded_chan_array(pdev, chan_num, + bonded_chan_80mhz_list, + QDF_ARRAY_SIZE(bonded_chan_80mhz_list), + bonded_chan_ptr_ptr); + else if (ch_width == CH_WIDTH_160MHZ) + return reg_get_5g_bonded_chan_array(pdev, chan_num, + bonded_chan_160mhz_list, + QDF_ARRAY_SIZE(bonded_chan_160mhz_list), + bonded_chan_ptr_ptr); + else if (ch_width == CH_WIDTH_80MHZ) + return reg_get_5g_bonded_chan_array(pdev, chan_num, + bonded_chan_80mhz_list, + QDF_ARRAY_SIZE(bonded_chan_80mhz_list), + bonded_chan_ptr_ptr); + else if (ch_width == CH_WIDTH_40MHZ) + return reg_get_5g_bonded_chan_array(pdev, chan_num, + bonded_chan_40mhz_list, + QDF_ARRAY_SIZE(bonded_chan_40mhz_list), + bonded_chan_ptr_ptr); + else + return reg_get_channel_state(pdev, chan_num); +} + +enum channel_state reg_get_5g_bonded_channel_state( + struct wlan_objmgr_pdev *pdev, + uint8_t ch, enum phy_ch_width bw) +{ + enum channel_enum ch_indx; + enum channel_state chan_state; + struct regulatory_channel *reg_channels; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + bool bw_enabled = false; + const struct bonded_channel *bonded_chan_ptr = NULL; + + if (bw > CH_WIDTH_80P80MHZ) { + reg_err("bw passed is not good"); + return CHANNEL_STATE_INVALID; + } + + chan_state = reg_get_5g_bonded_channel(pdev, ch, bw, &bonded_chan_ptr); + + if ((chan_state == CHANNEL_STATE_INVALID) || + (chan_state == CHANNEL_STATE_DISABLE)) + return chan_state; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("pdev reg obj is NULL"); + return CHANNEL_STATE_INVALID; + } + reg_channels = pdev_priv_obj->cur_chan_list; + + ch_indx = reg_get_chan_enum(ch); + if (ch_indx == INVALID_CHANNEL) + return CHANNEL_STATE_INVALID; + if (bw == CH_WIDTH_5MHZ) + bw_enabled = true; + else if (bw == CH_WIDTH_10MHZ) + bw_enabled = (reg_channels[ch_indx].min_bw <= 10) && + (reg_channels[ch_indx].max_bw >= 10); + else if (bw == CH_WIDTH_20MHZ) + bw_enabled = (reg_channels[ch_indx].min_bw <= 20) && + (reg_channels[ch_indx].max_bw >= 20); + else if (bw == CH_WIDTH_40MHZ) + bw_enabled = (reg_channels[ch_indx].min_bw <= 40) && + (reg_channels[ch_indx].max_bw >= 40); + else if (bw == CH_WIDTH_80MHZ) + bw_enabled = (reg_channels[ch_indx].min_bw <= 80) && + (reg_channels[ch_indx].max_bw >= 80); + else if (bw == CH_WIDTH_160MHZ) + bw_enabled = (reg_channels[ch_indx].min_bw <= 160) && + (reg_channels[ch_indx].max_bw >= 160); + else if (bw == CH_WIDTH_80P80MHZ) + bw_enabled = (reg_channels[ch_indx].min_bw <= 80) && + (reg_channels[ch_indx].max_bw >= 80); + + if (bw_enabled) + return chan_state; + else + return CHANNEL_STATE_DISABLE; +} + +enum channel_state reg_get_2g_bonded_channel_state( + struct wlan_objmgr_pdev *pdev, + uint8_t oper_ch, uint8_t sec_ch, + enum phy_ch_width bw) +{ + enum channel_enum chan_idx; + enum channel_state chan_state; + struct regulatory_channel *reg_channels; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + bool bw_enabled = false; + enum channel_state chan_state2 = CHANNEL_STATE_INVALID; + + if (bw > CH_WIDTH_40MHZ) + return CHANNEL_STATE_INVALID; + + if (bw == CH_WIDTH_40MHZ) { + if ((sec_ch + 4 != oper_ch) && + (oper_ch + 4 != sec_ch)) + return CHANNEL_STATE_INVALID; + chan_state2 = reg_get_channel_state(pdev, sec_ch); + if (chan_state2 == CHANNEL_STATE_INVALID) + return chan_state2; + } + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev priv obj is NULL"); + return CHANNEL_STATE_INVALID; + } + + reg_channels = pdev_priv_obj->cur_chan_list; + + chan_state = reg_get_channel_state(pdev, oper_ch); + if (chan_state2 < chan_state) + chan_state = chan_state2; + + if ((chan_state == CHANNEL_STATE_INVALID) || + (chan_state == CHANNEL_STATE_DISABLE)) + return chan_state; + + chan_idx = reg_get_chan_enum(oper_ch); + if (chan_idx == INVALID_CHANNEL) + return CHANNEL_STATE_INVALID; + if (bw == CH_WIDTH_5MHZ) + bw_enabled = true; + else if (bw == CH_WIDTH_10MHZ) + bw_enabled = (reg_channels[chan_idx].min_bw <= 10) && + (reg_channels[chan_idx].max_bw >= 10); + else if (bw == CH_WIDTH_20MHZ) + bw_enabled = (reg_channels[chan_idx].min_bw <= 20) && + (reg_channels[chan_idx].max_bw >= 20); + else if (bw == CH_WIDTH_40MHZ) + bw_enabled = (reg_channels[chan_idx].min_bw <= 40) && + (reg_channels[chan_idx].max_bw >= 40); + + if (bw_enabled) + return chan_state; + else + return CHANNEL_STATE_DISABLE; + + return CHANNEL_STATE_ENABLE; +} + +/** + * reg_combine_channel_states() - Get minimum of channel state1 and state2 + * @chan_state1: Channel state1 + * @chan_state2: Channel state2 + * + * Return: Channel state + */ +static enum channel_state reg_combine_channel_states( + enum channel_state chan_state1, + enum channel_state chan_state2) +{ + if ((chan_state1 == CHANNEL_STATE_INVALID) || + (chan_state2 == CHANNEL_STATE_INVALID)) + return CHANNEL_STATE_INVALID; + else + return min(chan_state1, chan_state2); +} + +/** + * reg_set_5g_channel_params () - Sets channel parameteres for given bandwidth + * @ch: channel number. + * @ch_params: pointer to the channel parameters. + * + * Return: None + */ +static void reg_set_5g_channel_params(struct wlan_objmgr_pdev *pdev, + uint8_t ch, + struct ch_params *ch_params) +{ + /* + * Set channel parameters like center frequency for a bonded channel + * state. Also return the maximum bandwidth supported by the channel. + */ + + enum phy_ch_width next_lower_bw; + enum channel_state chan_state = CHANNEL_STATE_ENABLE; + enum channel_state chan_state2 = CHANNEL_STATE_ENABLE; + const struct bonded_channel *bonded_chan_ptr = NULL; + const struct bonded_channel *bonded_chan_ptr2 = NULL; + + if (!ch_params) { + reg_err("ch_params is NULL"); + return; + } + + if (ch_params->ch_width >= CH_WIDTH_MAX) { + if (ch_params->center_freq_seg1 != 0) + ch_params->ch_width = CH_WIDTH_80P80MHZ; + else + ch_params->ch_width = CH_WIDTH_160MHZ; + } + next_lower_bw = ch_params->ch_width; + + while (ch_params->ch_width != CH_WIDTH_INVALID) { + ch_params->ch_width = next_lower_bw; + next_lower_bw = get_next_lower_bw[ch_params->ch_width]; + bonded_chan_ptr = NULL; + bonded_chan_ptr2 = NULL; + chan_state = reg_get_5g_bonded_channel( + pdev, ch, ch_params->ch_width, + &bonded_chan_ptr); + + chan_state = reg_get_5g_bonded_channel_state( + pdev, ch, ch_params->ch_width); + + if (ch_params->ch_width == CH_WIDTH_80P80MHZ) { + chan_state2 = reg_get_5g_bonded_channel_state( + pdev, ch_params->center_freq_seg1 - 2, + CH_WIDTH_80MHZ); + + chan_state = reg_combine_channel_states( + chan_state, chan_state2); + } + + if ((chan_state != CHANNEL_STATE_ENABLE) && + (chan_state != CHANNEL_STATE_DFS)) + continue; + if (ch_params->ch_width <= CH_WIDTH_20MHZ) { + ch_params->sec_ch_offset = NO_SEC_CH; + ch_params->center_freq_seg0 = ch; + break; + } else if (ch_params->ch_width >= CH_WIDTH_40MHZ) { + reg_get_5g_bonded_chan_array( + pdev, ch, bonded_chan_40mhz_list, + QDF_ARRAY_SIZE(bonded_chan_40mhz_list), + &bonded_chan_ptr2); + if (!bonded_chan_ptr || !bonded_chan_ptr2) + continue; + if (ch == bonded_chan_ptr2->start_ch) + ch_params->sec_ch_offset = LOW_PRIMARY_CH; + else + ch_params->sec_ch_offset = HIGH_PRIMARY_CH; + + ch_params->center_freq_seg0 = + (bonded_chan_ptr->start_ch + + bonded_chan_ptr->end_ch) / 2; + break; + } + } + + if (ch_params->ch_width == CH_WIDTH_160MHZ) { + ch_params->center_freq_seg1 = ch_params->center_freq_seg0; + chan_state = reg_get_5g_bonded_channel( + pdev, ch, CH_WIDTH_80MHZ, &bonded_chan_ptr); + if (bonded_chan_ptr) + ch_params->center_freq_seg0 = + (bonded_chan_ptr->start_ch + + bonded_chan_ptr->end_ch) / 2; + } + + /* Overwrite center_freq_seg1 to 0 for non 160 and 80+80 width */ + if (!(ch_params->ch_width == CH_WIDTH_160MHZ || + ch_params->ch_width == CH_WIDTH_80P80MHZ)) + ch_params->center_freq_seg1 = 0; + + reg_debug("ch %d ch_wd %d freq0 %d freq1 %d", ch, + ch_params->ch_width, ch_params->center_freq_seg0, + ch_params->center_freq_seg1); +} + +/** + * reg_set_2g_channel_params() - set the 2.4G bonded channel parameters + * @oper_ch: operating channel + * @ch_params: channel parameters + * @sec_ch_2g: 2.4G secondary channel + * + * Return: void + */ +static void reg_set_2g_channel_params(struct wlan_objmgr_pdev *pdev, + uint16_t oper_ch, + struct ch_params *ch_params, + uint16_t sec_ch_2g) +{ + enum channel_state chan_state = CHANNEL_STATE_ENABLE; + + if (ch_params->ch_width >= CH_WIDTH_MAX) + ch_params->ch_width = CH_WIDTH_40MHZ; + if ((reg_get_bw_value(ch_params->ch_width) > 20) && !sec_ch_2g) { + if (oper_ch >= 1 && oper_ch <= 5) + sec_ch_2g = oper_ch + 4; + else if (oper_ch >= 6 && oper_ch <= 13) + sec_ch_2g = oper_ch - 4; + } + + while (ch_params->ch_width != CH_WIDTH_INVALID) { + chan_state = reg_get_2g_bonded_channel_state( + pdev, oper_ch, sec_ch_2g, ch_params->ch_width); + if (chan_state == CHANNEL_STATE_ENABLE) { + if (ch_params->ch_width == CH_WIDTH_40MHZ) { + if (oper_ch < sec_ch_2g) + ch_params->sec_ch_offset = + LOW_PRIMARY_CH; + else + ch_params->sec_ch_offset = + HIGH_PRIMARY_CH; + ch_params->center_freq_seg0 = + (oper_ch + sec_ch_2g) / 2; + } else { + ch_params->sec_ch_offset = NO_SEC_CH; + ch_params->center_freq_seg0 = oper_ch; + } + break; + } + + ch_params->ch_width = get_next_lower_bw[ch_params->ch_width]; + } + /* Overwrite center_freq_seg1 to 0 for 2.4 Ghz */ + ch_params->center_freq_seg1 = 0; +} + +void reg_set_channel_params(struct wlan_objmgr_pdev *pdev, + uint8_t ch, uint8_t sec_ch_2g, + struct ch_params *ch_params) +{ + if (REG_IS_5GHZ_CH(ch)) + reg_set_5g_channel_params(pdev, ch, ch_params); + else if (REG_IS_24GHZ_CH(ch)) + reg_set_2g_channel_params(pdev, ch, ch_params, sec_ch_2g); +} + +QDF_STATUS reg_get_curr_band(struct wlan_objmgr_pdev *pdev, + enum band_info *band) +{ + struct wlan_regulatory_pdev_priv_obj *pdev_reg; + + pdev_reg = reg_get_pdev_obj(pdev); + if (!IS_VALID_PDEV_REG_OBJ(pdev_reg)) { + reg_err("pdev reg component is NULL"); + return QDF_STATUS_E_INVAL; + } + + *band = pdev_reg->band_capability; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS reg_read_default_country(struct wlan_objmgr_psoc *psoc, + uint8_t *country_code) +{ + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + + if (!country_code) { + reg_err("country_code is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc_priv_obj = reg_get_psoc_obj(psoc); + if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { + reg_err("psoc reg component is NULL"); + return QDF_STATUS_E_INVAL; + } + + qdf_mem_copy(country_code, psoc_priv_obj->def_country, + REG_ALPHA2_LEN + 1); + + return QDF_STATUS_SUCCESS; +} + +void reg_get_current_dfs_region(struct wlan_objmgr_pdev *pdev, + enum dfs_reg *dfs_reg) +{ + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg component pdev priv is NULL"); + return; + } + + *dfs_reg = pdev_priv_obj->dfs_region; +} + +void reg_set_dfs_region(struct wlan_objmgr_pdev *pdev, + enum dfs_reg dfs_reg) +{ + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("psoc reg component is NULL"); + return; + } + + pdev_priv_obj->dfs_region = dfs_reg; + + reg_init_channel_map(dfs_reg); +} + +uint32_t reg_get_channel_reg_power(struct wlan_objmgr_pdev *pdev, + uint32_t chan_num) +{ + enum channel_enum chan_enum; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + struct regulatory_channel *reg_channels; + + chan_enum = reg_get_chan_enum(chan_num); + + if (chan_enum == INVALID_CHANNEL) { + reg_err("channel is invalid"); + return QDF_STATUS_E_FAILURE; + } + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev priv obj is NULL"); + return QDF_STATUS_E_FAILURE; + } + + reg_channels = pdev_priv_obj->cur_chan_list; + + return reg_channels[chan_enum].tx_power; +} + +uint32_t reg_get_channel_freq(struct wlan_objmgr_pdev *pdev, + uint32_t chan_num) +{ + enum channel_enum chan_enum; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + struct regulatory_channel *reg_channels; + + chan_enum = reg_get_chan_enum(chan_num); + + if (chan_enum == INVALID_CHANNEL) + return CHANNEL_STATE_INVALID; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev priv obj is NULL"); + return QDF_STATUS_E_FAILURE; + } + + reg_channels = pdev_priv_obj->cur_chan_list; + + return reg_channels[chan_enum].center_freq; +} + +bool reg_is_dfs_ch(struct wlan_objmgr_pdev *pdev, + uint32_t chan) +{ + enum channel_state ch_state; + + ch_state = reg_get_channel_state(pdev, chan); + + return ch_state == CHANNEL_STATE_DFS; +} + +uint32_t reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, + uint32_t freq) +{ + uint32_t count; + struct regulatory_channel *chan_list; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev priv obj is NULL"); + return QDF_STATUS_E_FAILURE; + } + + chan_list = pdev_priv_obj->cur_chan_list; + + for (count = 0; count < NUM_CHANNELS; count++) + if (chan_list[count].center_freq == freq) + return chan_list[count].chan_num; + + reg_err("invalid frequency %d", freq); + + return 0; +} + +uint32_t reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, + uint32_t chan_num) +{ + uint32_t count; + struct regulatory_channel *chan_list; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev priv obj is NULL"); + return QDF_STATUS_E_FAILURE; + } + + chan_list = pdev_priv_obj->cur_chan_list; + + for (count = 0; count < NUM_CHANNELS; count++) + if (chan_list[count].chan_num == chan_num) { + if (reg_chan_in_range(chan_list, + pdev_priv_obj->range_2g_low, + pdev_priv_obj->range_2g_high, + pdev_priv_obj->range_5g_low, + pdev_priv_obj->range_5g_high, + count)) { + return chan_list[count].center_freq; + } + } + + reg_debug_rl("invalid channel %d", chan_num); + + return 0; +} + +#ifndef CONFIG_LEGACY_CHAN_ENUM +bool reg_chan_is_49ghz(struct wlan_objmgr_pdev *pdev, uint8_t chan_num) +{ + uint32_t freq = 0; + + freq = reg_chan_to_freq(pdev, chan_num); + + return REG_IS_49GHZ_FREQ(freq) ? true : false; +} +#else +bool reg_chan_is_49ghz(struct wlan_objmgr_pdev *pdev, uint8_t chan_num) +{ + return false; +} +#endif + +enum band_info reg_chan_to_band(uint32_t chan_num) +{ + if (chan_num <= 14) + return BAND_2G; + + return BAND_5G; +} + +void reg_update_nol_ch(struct wlan_objmgr_pdev *pdev, + uint8_t *chan_list, + uint8_t num_chan, + bool nol_chan) +{ + enum channel_enum chan_enum; + struct regulatory_channel *mas_chan_list; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + uint16_t i; + + if (!num_chan || !chan_list) { + reg_err("chan_list or num_ch is NULL"); + return; + } + + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!pdev_priv_obj) { + reg_err("reg psoc private obj is NULL"); + return; + } + + mas_chan_list = pdev_priv_obj->mas_chan_list; + for (i = 0; i < num_chan; i++) { + chan_enum = reg_get_chan_enum(chan_list[i]); + if (chan_enum == INVALID_CHANNEL) { + reg_err("Invalid ch in nol list, chan %d", + chan_list[i]); + continue; + } + mas_chan_list[chan_enum].nol_chan = nol_chan; + } + + reg_compute_pdev_current_chan_list(pdev_priv_obj); +} + +QDF_STATUS reg_program_default_cc(struct wlan_objmgr_pdev *pdev, + uint16_t regdmn) +{ + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + struct cur_regulatory_info *reg_info; + uint16_t cc = -1; + uint16_t country_index = -1, regdmn_pair = -1; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS err; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!pdev_priv_obj) { + reg_err("reg soc is NULL"); + return QDF_STATUS_E_FAILURE; + } + + reg_info = (struct cur_regulatory_info *)qdf_mem_malloc + (sizeof(struct cur_regulatory_info)); + if (!reg_info) { + reg_err("reg info is NULL"); + return QDF_STATUS_E_NOMEM; + } + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + reg_err("psoc is NULL"); + return QDF_STATUS_E_INVAL; + } + + reg_info->psoc = psoc; + reg_info->phy_id = wlan_objmgr_pdev_get_pdev_id(pdev); + + if (regdmn == 0) { + reg_get_default_country(®dmn); + regdmn |= COUNTRY_ERD_FLAG; + } + + if (regdmn & COUNTRY_ERD_FLAG) { + cc = regdmn & ~COUNTRY_ERD_FLAG; + + reg_get_rdpair_from_country_code(cc, + &country_index, + ®dmn_pair); + + err = reg_get_cur_reginfo(reg_info, country_index, regdmn_pair); + if (err == QDF_STATUS_E_FAILURE) { + reg_err("%s : Unable to set country code\n", __func__); + qdf_mem_free(reg_info->reg_rules_2g_ptr); + qdf_mem_free(reg_info->reg_rules_5g_ptr); + qdf_mem_free(reg_info); + return QDF_STATUS_E_FAILURE; + } + + pdev_priv_obj->ctry_code = cc; + + } else { + reg_get_rdpair_from_regdmn_id(regdmn, ®dmn_pair); + + err = reg_get_cur_reginfo(reg_info, country_index, regdmn_pair); + if (err == QDF_STATUS_E_FAILURE) { + reg_err("%s : Unable to set country code\n", __func__); + qdf_mem_free(reg_info->reg_rules_2g_ptr); + qdf_mem_free(reg_info->reg_rules_5g_ptr); + qdf_mem_free(reg_info); + return QDF_STATUS_E_FAILURE; + } + + pdev_priv_obj->reg_dmn_pair = regdmn; + } + + reg_info->offload_enabled = false; + reg_process_master_chan_list(reg_info); + + qdf_mem_free(reg_info->reg_rules_2g_ptr); + qdf_mem_free(reg_info->reg_rules_5g_ptr); + qdf_mem_free(reg_info); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS reg_program_chan_list(struct wlan_objmgr_pdev *pdev, + struct cc_regdmn_s *rd) +{ + struct cur_regulatory_info *reg_info; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + uint16_t country_index = -1, regdmn_pair = -1; + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_reg_tx_ops *tx_ops; + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + uint8_t pdev_id; + QDF_STATUS err; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!pdev_priv_obj) { + reg_err(" pdev priv obj is NULL"); + return QDF_STATUS_E_FAILURE; + } + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + reg_err("psoc is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc_priv_obj = reg_get_psoc_obj(psoc); + if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { + reg_err("psoc reg component is NULL"); + return QDF_STATUS_E_FAILURE; + } + + if (psoc_priv_obj->offload_enabled) { + if ((rd->flags == ALPHA_IS_SET) && (rd->cc.alpha[2] == 'O')) + pdev_priv_obj->indoor_chan_enabled = false; + else + pdev_priv_obj->indoor_chan_enabled = true; + + pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + tx_ops = reg_get_psoc_tx_ops(psoc); + if (tx_ops->set_user_country_code) { + psoc_priv_obj->new_init_ctry_pending[pdev_id] = true; + return tx_ops->set_user_country_code(psoc, pdev_id, rd); + } + + return QDF_STATUS_E_FAILURE; + } + + reg_info = (struct cur_regulatory_info *)qdf_mem_malloc + (sizeof(struct cur_regulatory_info)); + if (!reg_info) { + reg_err("reg info is NULL"); + return QDF_STATUS_E_NOMEM; + } + + reg_info->psoc = psoc; + reg_info->phy_id = wlan_objmgr_pdev_get_pdev_id(pdev); + + if (rd->flags == CC_IS_SET) { + reg_get_rdpair_from_country_code(rd->cc.country_code, + &country_index, + ®dmn_pair); + } else if (rd->flags == ALPHA_IS_SET) { + reg_get_rdpair_from_country_iso(rd->cc.alpha, + &country_index, + ®dmn_pair); + } else if (rd->flags == REGDMN_IS_SET) { + reg_get_rdpair_from_regdmn_id(rd->cc.regdmn_id, + ®dmn_pair); + } + + err = reg_get_cur_reginfo(reg_info, country_index, regdmn_pair); + if (err == QDF_STATUS_E_FAILURE) { + reg_err("%s : Unable to set country code\n", __func__); + qdf_mem_free(reg_info->reg_rules_2g_ptr); + qdf_mem_free(reg_info->reg_rules_5g_ptr); + qdf_mem_free(reg_info); + return QDF_STATUS_E_FAILURE; + } + + reg_info->offload_enabled = false; + reg_process_master_chan_list(reg_info); + + qdf_mem_free(reg_info->reg_rules_2g_ptr); + qdf_mem_free(reg_info->reg_rules_5g_ptr); + qdf_mem_free(reg_info); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS reg_get_current_cc(struct wlan_objmgr_pdev *pdev, + struct cc_regdmn_s *rd) +{ + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!pdev_priv_obj) { + reg_err("reg pdev priv is NULL"); + return QDF_STATUS_E_FAILURE; + } + + if (rd->flags == CC_IS_SET) { + rd->cc.country_code = pdev_priv_obj->ctry_code; + } else if (rd->flags == ALPHA_IS_SET) { + qdf_mem_copy(rd->cc.alpha, pdev_priv_obj->current_country, + sizeof(rd->cc.alpha)); + } else if (rd->flags == REGDMN_IS_SET) { + rd->cc.regdmn_id = pdev_priv_obj->reg_dmn_pair; + } + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS reg_set_regdb_offloaded(struct wlan_objmgr_psoc *psoc, bool val) +{ + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + + psoc_priv_obj = reg_get_psoc_obj(psoc); + + if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { + reg_err("psoc reg component is NULL"); + return QDF_STATUS_E_FAILURE; + } + + psoc_priv_obj->offload_enabled = val; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS reg_get_curr_regdomain(struct wlan_objmgr_pdev *pdev, + struct cur_regdmn_info *cur_regdmn) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + uint16_t index; + int num_reg_dmn; + uint8_t phy_id; + + psoc = wlan_pdev_get_psoc(pdev); + psoc_priv_obj = reg_get_psoc_obj(psoc); + if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { + reg_err("soc reg component is NULL"); + return QDF_STATUS_E_INVAL; + } + + phy_id = wlan_objmgr_pdev_get_pdev_id(pdev); + cur_regdmn->regdmn_pair_id = + psoc_priv_obj->mas_chan_params[phy_id].reg_dmn_pair; + + reg_get_num_reg_dmn_pairs(&num_reg_dmn); + for (index = 0; index < num_reg_dmn; index++) { + if (g_reg_dmn_pairs[index].reg_dmn_pair_id == + cur_regdmn->regdmn_pair_id) + break; + } + + if (index == num_reg_dmn) { + reg_err("invalid regdomain"); + return QDF_STATUS_E_FAILURE; + } + + cur_regdmn->dmn_id_2g = g_reg_dmn_pairs[index].dmn_id_2g; + cur_regdmn->dmn_id_5g = g_reg_dmn_pairs[index].dmn_id_5g; + cur_regdmn->ctl_2g = regdomains_2g[cur_regdmn->dmn_id_2g].ctl_val; + cur_regdmn->ctl_5g = regdomains_5g[cur_regdmn->dmn_id_5g].ctl_val; + cur_regdmn->dfs_region = + regdomains_5g[cur_regdmn->dmn_id_5g].dfs_region; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS reg_modify_chan_144(struct wlan_objmgr_pdev *pdev, + bool enable_ch_144) +{ + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_reg_tx_ops *reg_tx_ops; + QDF_STATUS status; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("pdev reg component is NULL"); + return QDF_STATUS_E_INVAL; + } + + if (pdev_priv_obj->en_chan_144 == enable_ch_144) { + reg_info("chan 144 is already %d", enable_ch_144); + return QDF_STATUS_SUCCESS; + } + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + reg_err("psoc is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc_priv_obj = reg_get_psoc_obj(psoc); + if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { + reg_err("psoc reg component is NULL"); + return QDF_STATUS_E_INVAL; + } + + reg_debug("setting chan 144: %d", enable_ch_144); + pdev_priv_obj->en_chan_144 = enable_ch_144; + + reg_compute_pdev_current_chan_list(pdev_priv_obj); + + reg_tx_ops = reg_get_psoc_tx_ops(psoc); + if (reg_tx_ops->fill_umac_legacy_chanlist) + reg_tx_ops->fill_umac_legacy_chanlist(pdev, + pdev_priv_obj->cur_chan_list); + + status = reg_send_scheduler_msg_sb(psoc, pdev); + + return status; +} + +bool reg_get_en_chan_144(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("pdev reg component is NULL"); + return false; + } + + return pdev_priv_obj->en_chan_144; +} + +struct wlan_psoc_host_hal_reg_capabilities_ext *reg_get_hal_reg_cap( + struct wlan_objmgr_psoc *psoc) +{ + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + + psoc_priv_obj = reg_get_psoc_obj(psoc); + + if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { + reg_err("psoc reg component is NULL"); + return NULL; + } + + return psoc_priv_obj->reg_cap; +} + +QDF_STATUS reg_set_hal_reg_cap( + struct wlan_objmgr_psoc *psoc, + struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap, + uint16_t phy_cnt) +{ + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + + psoc_priv_obj = reg_get_psoc_obj(psoc); + + if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { + reg_err("psoc reg component is NULL"); + return QDF_STATUS_E_FAILURE; + } + + if (phy_cnt > PSOC_MAX_PHY_REG_CAP) { + reg_err("phy cnt:%d is more than %d", phy_cnt, + PSOC_MAX_PHY_REG_CAP); + return QDF_STATUS_E_FAILURE; + } + + qdf_mem_copy(psoc_priv_obj->reg_cap, reg_cap, + phy_cnt * + sizeof(struct wlan_psoc_host_hal_reg_capabilities_ext)); + + return QDF_STATUS_SUCCESS; +} + +bool reg_chan_in_range(struct regulatory_channel *chan_list, + uint32_t low_freq_2g, uint32_t high_freq_2g, + uint32_t low_freq_5g, uint32_t high_freq_5g, + enum channel_enum ch_enum) +{ + uint32_t low_limit_2g = NUM_CHANNELS; + uint32_t high_limit_2g = NUM_CHANNELS; + uint32_t low_limit_5g = NUM_CHANNELS; + uint32_t high_limit_5g = NUM_CHANNELS; + bool chan_in_range; + enum channel_enum chan_enum; + uint16_t min_bw; + uint32_t center_freq; + + for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { + min_bw = chan_list[chan_enum].min_bw; + center_freq = chan_list[chan_enum].center_freq; + + if ((center_freq - min_bw / 2) >= low_freq_2g) { + low_limit_2g = chan_enum; + break; + } + } + + for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { + min_bw = chan_list[chan_enum].min_bw; + center_freq = chan_list[chan_enum].center_freq; + + if ((center_freq - min_bw / 2) >= low_freq_5g) { + low_limit_5g = chan_enum; + break; + } + } + + for (chan_enum = NUM_CHANNELS - 1; chan_enum >= 0; chan_enum--) { + min_bw = chan_list[chan_enum].min_bw; + center_freq = chan_list[chan_enum].center_freq; + + if (center_freq + min_bw / 2 <= high_freq_2g) { + high_limit_2g = chan_enum; + break; + } + if (chan_enum == 0) + break; + } + + for (chan_enum = NUM_CHANNELS - 1; chan_enum >= 0; chan_enum--) { + min_bw = chan_list[chan_enum].min_bw; + center_freq = chan_list[chan_enum].center_freq; + + if (center_freq + min_bw / 2 <= high_freq_5g) { + high_limit_5g = chan_enum; + break; + } + if (chan_enum == 0) + break; + } + + chan_in_range = false; + if ((low_limit_2g <= ch_enum) && + (high_limit_2g >= ch_enum) && + (low_limit_2g != NUM_CHANNELS) && + (high_limit_2g != NUM_CHANNELS)) + chan_in_range = true; + if ((low_limit_5g <= ch_enum) && + (high_limit_5g >= ch_enum) && + (low_limit_5g != NUM_CHANNELS) && + (high_limit_5g != NUM_CHANNELS)) + chan_in_range = true; + + if (chan_in_range) + return true; + else + return false; +} + +void reg_update_nol_history_ch(struct wlan_objmgr_pdev *pdev, + uint8_t *chan_list, uint8_t num_chan, + bool nol_history_chan) +{ + enum channel_enum chan_enum; + struct regulatory_channel *mas_chan_list; + struct regulatory_channel *cur_chan_list; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + uint16_t i; + + if (!num_chan || !chan_list) { + reg_err("chan_list or num_ch is NULL"); + return; + } + + pdev_priv_obj = wlan_objmgr_pdev_get_comp_private_obj( + pdev, WLAN_UMAC_COMP_REGULATORY); + + if (!pdev_priv_obj) { + reg_err("reg psoc private obj is NULL"); + return; + } + + mas_chan_list = pdev_priv_obj->mas_chan_list; + cur_chan_list = pdev_priv_obj->cur_chan_list; + + for (i = 0; i < num_chan; i++) { + chan_enum = reg_get_chan_enum(chan_list[i]); + if (chan_enum == INVALID_CHANNEL) { + reg_err("Invalid ch in nol list, chan %d", + chan_list[i]); + continue; + } + mas_chan_list[chan_enum].nol_history = nol_history_chan; + cur_chan_list[chan_enum].nol_history = nol_history_chan; + } +} + +bool reg_is_24ghz_ch(uint32_t chan) +{ + return REG_IS_24GHZ_CH(chan); +} + +bool reg_is_5ghz_ch(uint32_t chan) +{ + return REG_IS_5GHZ_CH(chan); +} + +bool reg_is_24ghz_ch_freq(uint32_t freq) +{ + return REG_IS_24GHZ_CH_FREQ(freq); +} + +bool reg_is_5ghz_ch_freq(uint32_t freq) +{ + return REG_IS_5GHZ_FREQ(freq); +} + +#ifndef CONFIG_LEGACY_CHAN_ENUM +bool reg_is_49ghz_freq(uint32_t freq) +{ + return REG_IS_49GHZ_FREQ(freq); +} +#endif + +uint32_t reg_ch_num(uint32_t ch_enum) +{ + return REG_CH_NUM(ch_enum); +} + +uint32_t reg_ch_to_freq(uint32_t ch_enum) +{ + return REG_CH_TO_FREQ(ch_enum); +} + +bool reg_is_same_band_channels(uint32_t chan_num1, uint32_t chan_num2) +{ + return (chan_num1 && chan_num2 && + (REG_IS_5GHZ_CH(chan_num1) == REG_IS_5GHZ_CH(chan_num2))); +} + +bool reg_is_channel_valid_5g_sbs(uint32_t curchan, uint32_t newchan) +{ + return REG_IS_CHANNEL_VALID_5G_SBS(curchan, newchan); +} + +uint32_t reg_min_24ghz_ch_num(void) +{ + return REG_MIN_24GHZ_CH_NUM; +} + +uint32_t reg_max_24ghz_ch_num(void) +{ + return REG_MAX_24GHZ_CH_NUM; +} + +uint32_t reg_min_5ghz_ch_num(void) +{ + return REG_MIN_5GHZ_CH_NUM; +} + +uint32_t reg_max_5ghz_ch_num(void) +{ + return REG_MAX_5GHZ_CH_NUM; +} diff --git a/umac/regulatory/core/src/reg_services_common.h b/umac/regulatory/core/src/reg_services_common.h new file mode 100644 index 000000000000..1d95309e140b --- /dev/null +++ b/umac/regulatory/core/src/reg_services_common.h @@ -0,0 +1,500 @@ +/* + * Copyright (c) 2017-2019 The Linux Foundation. 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: reg_services.h + * This file provides prototypes of the regulatory component + * service functions + */ + +#ifndef __REG_SERVICES_COMMON_H_ +#define __REG_SERVICES_COMMON_H_ + +#define IS_VALID_PSOC_REG_OBJ(psoc_priv_obj) (psoc_priv_obj) +#define IS_VALID_PDEV_REG_OBJ(pdev_priv_obj) (pdev_priv_obj) + +#define REG_MIN_24GHZ_CH_NUM channel_map[MIN_24GHZ_CHANNEL].chan_num +#define REG_MAX_24GHZ_CH_NUM channel_map[MAX_24GHZ_CHANNEL].chan_num +#define REG_MIN_5GHZ_CH_NUM channel_map[MIN_5GHZ_CHANNEL].chan_num +#define REG_MAX_5GHZ_CH_NUM channel_map[MAX_5GHZ_CHANNEL].chan_num + +#define REG_IS_24GHZ_CH(chan_num) \ + (((chan_num) >= REG_MIN_24GHZ_CH_NUM) && \ + ((chan_num) <= REG_MAX_24GHZ_CH_NUM)) + +#define REG_MIN_24GHZ_CH_FREQ channel_map[MIN_24GHZ_CHANNEL].center_freq +#define REG_MAX_24GHZ_CH_FREQ channel_map[MAX_24GHZ_CHANNEL].center_freq + +#define REG_IS_24GHZ_CH_FREQ(freq) \ + (((freq) >= REG_MIN_24GHZ_CH_FREQ) && \ + ((freq) <= REG_MAX_24GHZ_CH_FREQ)) + +#ifndef CONFIG_LEGACY_CHAN_ENUM +#define REG_MIN_49GHZ_CH_FREQ channel_map[MIN_49GHZ_CHANNEL].center_freq +#define REG_MAX_49GHZ_CH_FREQ channel_map[MAX_49GHZ_CHANNEL].center_freq + +#define REG_IS_49GHZ_FREQ(freq) \ + (((freq) >= REG_MIN_49GHZ_CH_FREQ) && \ + ((freq) <= REG_MAX_49GHZ_CH_FREQ)) +#endif + +#define REG_IS_5GHZ_CH(chan_num) \ + (((chan_num) >= REG_MIN_5GHZ_CH_NUM) && \ + ((chan_num) <= REG_MAX_5GHZ_CH_NUM)) + +#define REG_IS_5GHZ_FREQ(freq) \ + (((freq) >= channel_map[MIN_5GHZ_CHANNEL].center_freq) && \ + ((freq) <= channel_map[MAX_5GHZ_CHANNEL].center_freq)) + +#define REG_CH_NUM(ch_enum) channel_map[ch_enum].chan_num +#define REG_CH_TO_FREQ(ch_enum) channel_map[ch_enum].center_freq + +/* EEPROM setting is a country code */ +#define COUNTRY_ERD_FLAG 0x8000 + +extern const struct chan_map *channel_map; + +/** + * reg_get_chan_enum() - Get channel enum for given channel number + * @chan_num: Channel number + * + * Return: Channel enum + */ +enum channel_enum reg_get_chan_enum(uint32_t chan_num); + +/** + * reg_get_channel_list_with_power() - Provides the channel list with power + * @pdev: Pointer to pdev + * @ch_list: Pointer to the channel list. + * @num_chan: Pointer to save number of channels + * + * Return: QDF_STATUS + */ +QDF_STATUS reg_get_channel_list_with_power(struct wlan_objmgr_pdev *pdev, + struct channel_power *ch_list, + uint8_t *num_chan); + +/** + * reg_get_channel_state() - Get channel state from regulatory + * @pdev: Pointer to pdev + * @ch: channel number. + * + * Return: channel state + */ +enum channel_state reg_get_channel_state(struct wlan_objmgr_pdev *pdev, + uint32_t ch); + +/** + * reg_get_5g_bonded_channel_state() - Get channel state for 5G bonded channel + * @pdev: Pointer to pdev + * @ch: channel number. + * @bw: channel band width + * + * Return: channel state + */ +enum channel_state reg_get_5g_bonded_channel_state( + struct wlan_objmgr_pdev *pdev, uint8_t ch, + enum phy_ch_width bw); + +/** + * reg_get_2g_bonded_channel_state() - Get channel state for 2G bonded channel + * @ch: channel number. + * @pdev: Pointer to pdev + * @oper_ch: Primary channel number + * @sec_ch: Secondary channel number + * @bw: channel band width + * + * Return: channel state + */ +enum channel_state reg_get_2g_bonded_channel_state( + struct wlan_objmgr_pdev *pdev, uint8_t oper_ch, uint8_t sec_ch, + enum phy_ch_width bw); + +/** + * reg_set_channel_params () - Sets channel parameteres for given bandwidth + * @pdev: Pointer to pdev + * @ch: channel number. + * @sec_ch_2g: Secondary 2G channel + * @ch_params: pointer to the channel parameters. + * + * Return: None + */ +void reg_set_channel_params(struct wlan_objmgr_pdev *pdev, + uint8_t ch, uint8_t sec_ch_2g, + struct ch_params *ch_params); + +/** + * reg_read_default_country() - Get the default regulatory country + * @psoc: The physical SoC to get default country from + * @country_code: the buffer to populate the country code into + * + * Return: QDF_STATUS + */ +QDF_STATUS reg_read_default_country(struct wlan_objmgr_psoc *psoc, + uint8_t *country_code); + +/** + * reg_get_current_dfs_region () - Get the current dfs region + * @pdev: Pointer to pdev + * @dfs_reg: pointer to dfs region + * + * Return: None + */ +void reg_get_current_dfs_region(struct wlan_objmgr_pdev *pdev, + enum dfs_reg *dfs_reg); + +/** + * reg_get_channel_reg_power() - Get the txpower for the given channel + * @pdev: Pointer to pdev + * @chan_num: Channel number + * + * Return: txpower + */ +uint32_t reg_get_channel_reg_power(struct wlan_objmgr_pdev *pdev, + uint32_t chan_num); + +/** + * reg_get_channel_freq() - Get the channel frequency + * @pdev: Pointer to pdev + * @chan_num: Channel number + * + * Return: frequency + */ +uint32_t reg_get_channel_freq(struct wlan_objmgr_pdev *pdev, + uint32_t chan_num); + +/** + * reg_get_bw_value() - give bandwidth value + * bw: bandwidth enum + * + * Return: uint16_t + */ +uint16_t reg_get_bw_value(enum phy_ch_width bw); + +/** + * reg_set_dfs_region () - Set the current dfs region + * @pdev: Pointer to pdev + * @dfs_reg: pointer to dfs region + * + * Return: None + */ +void reg_set_dfs_region(struct wlan_objmgr_pdev *pdev, + enum dfs_reg dfs_reg); + +/** + * reg_chan_to_band() - Get band from channel number + * @chan_num: channel number + * + * Return: band info + */ +enum band_info reg_chan_to_band(uint32_t chan_num); + +/** + * reg_program_chan_list() - Set user country code and populate the channel list + * @pdev: Pointer to pdev + * @rd: Pointer to cc_regdmn_s structure + * + * Return: QDF_STATUS + */ +QDF_STATUS reg_program_chan_list(struct wlan_objmgr_pdev *pdev, + struct cc_regdmn_s *rd); + +/** + * reg_update_nol_ch () - Updates NOL channels in current channel list + * @pdev: pointer to pdev object + * @ch_list: pointer to NOL channel list + * @num_ch: No.of channels in list + * @update_nol: set/reset the NOL status + * + * Return: None + */ +void reg_update_nol_ch(struct wlan_objmgr_pdev *pdev, uint8_t *chan_list, + uint8_t num_chan, bool nol_chan); + +/** + * reg_is_dfs_ch () - Checks the channel state for DFS + * @pdev: pdev ptr + * @chan: channel + * + * Return: true or false + */ +bool reg_is_dfs_ch(struct wlan_objmgr_pdev *pdev, uint32_t chan); + +/** + * reg_freq_to_chan() - Get channel number from frequency. + * @pdev: Pointer to pdev + * @freq: Channel frequency + * + * Return: Channel number + */ +uint32_t reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, uint32_t freq); + +/** + * reg_chan_to_freq() - Get frequency from channel number + * @pdev: Pointer to pdev + * @chan_num: Channel number + * + * Return: Channel frequency + */ +uint32_t reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, uint32_t chan_num); + +/** + * reg_chan_is_49ghz() - Check if the input channel number is 4.9GHz + * @pdev: Pdev pointer + * @chan_num: Input channel number + * + * Return: true if the channel is 4.9GHz else false. + */ +bool reg_chan_is_49ghz(struct wlan_objmgr_pdev *pdev, uint8_t chan_num); + +/** + * reg_program_default_cc() - Program default country code + * @pdev: Pdev pointer + * @regdmn: Regdomain value + * + * Return: QDF_STATUS + */ +QDF_STATUS reg_program_default_cc(struct wlan_objmgr_pdev *pdev, + uint16_t regdmn); + +/** + * reg_get_current_cc() - Get current country code + * @pdev: Pdev pointer + * @regdmn: Pointer to get current country values + * + * Return: QDF_STATUS + */ +QDF_STATUS reg_get_current_cc(struct wlan_objmgr_pdev *pdev, + struct cc_regdmn_s *rd); + +/** + * reg_get_curr_band() - Get current band + * @pdev: Pdev pointer + * @band: Pointer to save the current band + * + * Return: QDF_STATUS + */ +QDF_STATUS reg_get_curr_band(struct wlan_objmgr_pdev *pdev, + enum band_info *band); + +/** + * reg_set_regdb_offloaded() - set/clear regulatory offloaded flag + * + * @psoc: psoc pointer + * Return: Success or Failure + */ +QDF_STATUS reg_set_regdb_offloaded(struct wlan_objmgr_psoc *psoc, bool val); + +/** + * reg_get_curr_regdomain() - Get current regdomain in use + * @pdev: pdev pointer + * @cur_regdmn: Current regdomain info + * + * Return: QDF status + */ +QDF_STATUS reg_get_curr_regdomain(struct wlan_objmgr_pdev *pdev, + struct cur_regdmn_info *cur_regdmn); + +/** + * reg_modify_chan_144() - Enable/Disable channel 144 + * @pdev: pdev pointer + * @en_chan_144: flag to disable/enable channel 144 + * + * Return: Success or Failure + */ +QDF_STATUS reg_modify_chan_144(struct wlan_objmgr_pdev *pdev, bool en_chan_144); + +/** + * reg_get_en_chan_144() - get en_chan_144 flag value + * @pdev: pdev pointer + * + * Return: en_chan_144 flag value + */ +bool reg_get_en_chan_144(struct wlan_objmgr_pdev *pdev); + +/** + * reg_get_hal_reg_cap() - Get HAL REG capabilities + * @psoc: psoc for country information + * + * Return: hal reg cap pointer + */ +struct wlan_psoc_host_hal_reg_capabilities_ext *reg_get_hal_reg_cap( + struct wlan_objmgr_psoc *psoc); + +/** + * reg_set_hal_reg_cap() - Set HAL REG capabilities + * @psoc: psoc for country information + * @reg_cap: Regulatory caps pointer + * @phy_cnt: number of phy + * + * Return: hal reg cap pointer + */ +QDF_STATUS reg_set_hal_reg_cap( + struct wlan_objmgr_psoc *psoc, + struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap, + uint16_t phy_cnt); + +/** + * reg_chan_in_range() - Check if the given channel is in pdev's channel range + * @chan_list: Pointer to regulatory channel list. + * @low_freq_2g: Low frequency 2G. + * @high_freq_2g: High frequency 2G. + * @low_freq_5g: Low frequency 5G. + * @high_freq_5g: High frequency 5G. + * @ch_enum: Channel enum. + * + * Return: true if ch_enum is with in pdev's channel range, else false. + */ +bool reg_chan_in_range(struct regulatory_channel *chan_list, + uint32_t low_freq_2g, uint32_t high_freq_2g, + uint32_t low_freq_5g, uint32_t high_freq_5g, + enum channel_enum ch_enum); + +/** + * reg_init_channel_map() - Initialize the channel list based on the dfs region. + * @dfs_region: Dfs region + */ +void reg_init_channel_map(enum dfs_reg dfs_region); + +/** + * reg_get_psoc_tx_ops() - Get regdb tx ops + * @psoc: Pointer to psoc structure + */ +struct wlan_lmac_if_reg_tx_ops *reg_get_psoc_tx_ops( + struct wlan_objmgr_psoc *psoc); + +/** + * reg_update_nol_history_ch() - Set nol-history flag for the channels in the + * list. + * @pdev: Pdev ptr. + * @ch_list: Input channel list. + * @num_ch: Number of channels. + * @nol_history_ch: NOL-History flag. + * + * Return: void + */ +void reg_update_nol_history_ch(struct wlan_objmgr_pdev *pdev, + uint8_t *chan_list, + uint8_t num_chan, + bool nol_history_chan); + +/** + * reg_is_24ghz_ch() - Check if the given channel number is 2.4GHz + * @chan: Channel number + * + * Return: true if channel number is 2.4GHz, else false + */ +bool reg_is_24ghz_ch(uint32_t chan); + +/** + * reg_is_5ghz_ch() - Check if the given channel number is 5GHz + * @chan: Channel number + * + * Return: true if channel number is 5GHz, else false + */ +bool reg_is_5ghz_ch(uint32_t chan); + +/** + * reg_is_24ghz_ch_freq() - Check if the given channel frequency is 2.4GHz + * @freq: Channel frequency + * + * Return: true if channel frequency is 2.4GHz, else false + */ +bool reg_is_24ghz_ch_freq(uint32_t freq); + +/** + * reg_is_5ghz_ch_freq() - Check if the given channel frequency is 5GHz + * @freq: Channel frequency + * + * Return: true if channel frequency is 5GHz, else false + */ +bool reg_is_5ghz_ch_freq(uint32_t chan); + +#ifndef CONFIG_LEGACY_CHAN_ENUM +/** + * reg_is_49ghz_freq() - Check if the given channel frequency is 4.9GHz + * @freq: Channel frequency + * + * Return: true if channel frequency is 4.9GHz, else false + */ +bool reg_is_49ghz_freq(uint32_t freq); +#endif + +/** + * reg_ch_num() - Get channel number from channel enum + * @ch_enum: Channel enum + * + * Return: channel number + */ +uint32_t reg_ch_num(uint32_t ch_enum); + +/** + * reg_ch_to_freq() - Get channel frequency from channel enum + * @ch_enum: Channel enum + * + * Return: channel frequency + */ +uint32_t reg_ch_to_freq(uint32_t ch_enum); + +/** + * reg_is_same_band_channels() - Check if given channel numbers have same band + * @chan_num1: Channel number1 + * @chan_num2: Channel number2 + * + * Return: true if both the channels has the same band. + */ +bool reg_is_same_band_channels(uint32_t chan_num1, uint32_t chan_num2); + +/** + * reg_is_channel_valid_5g_sbs() Check if the given channel is 5G SBS. + * @curchan: current channel + * @newchan:new channel + * + * Return: true if the given channel is a valid 5G SBS + */ +bool reg_is_channel_valid_5g_sbs(uint32_t curchan, uint32_t newchan); + +/** + * reg_min_24ghz_ch_num() - Get minimum 2.4GHz channel number + * + * Return: Minimum 2.4GHz channel number + */ +uint32_t reg_min_24ghz_ch_num(void); + +/** + * reg_max_24ghz_ch_num() - Get maximum 2.4GHz channel number + * + * Return: Maximum 2.4GHz channel number + */ +uint32_t reg_max_24ghz_ch_num(void); + +/** + * reg_min_5ghz_ch_num() - Get minimum 5GHz channel number + * + * Return: Minimum 5GHz channel number + */ +uint32_t reg_min_5ghz_ch_num(void); + +/** + * reg_max_5ghz_ch_num() - Get maximum 5GHz channel number + * + * Return: Maximum 5GHz channel number + */ +uint32_t reg_max_5ghz_ch_num(void); +#endif diff --git a/umac/regulatory/dispatcher/inc/reg_services_public_struct.h b/umac/regulatory/dispatcher/inc/reg_services_public_struct.h index cf4829abe8cc..76a79dea3f72 100644 --- a/umac/regulatory/dispatcher/inc/reg_services_public_struct.h +++ b/umac/regulatory/dispatcher/inc/reg_services_public_struct.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. 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 @@ -24,9 +24,6 @@ #ifndef __REG_SERVICES_PUBLIC_STRUCT_H_ #define __REG_SERVICES_PUBLIC_STRUCT_H_ -#include "../../core/src/reg_db.h" -#include "wlan_cmn.h" - #define REG_SBS_SEPARATION_THRESHOLD 100 #define REG_MAX_CHANNELS_PER_OPERATING_CLASS 25 #define REG_MAX_SUPP_OPER_CLASSES 32 @@ -35,6 +32,47 @@ #define INVALID_VDEV_ID 0xFF #define INVALID_CHANNEL_NUM 0xBAD #define CH_AVOID_MAX_RANGE 4 +#define REG_ALPHA2_LEN 2 +#define MAX_REG_RULES 10 + +#define REGULATORY_CHAN_DISABLED BIT(0) +#define REGULATORY_CHAN_NO_IR BIT(1) +#define REGULATORY_CHAN_RADAR BIT(3) +#define REGULATORY_CHAN_NO_OFDM BIT(6) +#define REGULATORY_CHAN_INDOOR_ONLY BIT(9) + +#define REGULATORY_CHAN_NO_HT40 BIT(4) +#define REGULATORY_CHAN_NO_80MHZ BIT(7) +#define REGULATORY_CHAN_NO_160MHZ BIT(8) +#define REGULATORY_CHAN_NO_20MHZ BIT(11) +#define REGULATORY_CHAN_NO_10MHZ BIT(12) + +#define REGULATORY_PHYMODE_NO11A BIT(0) +#define REGULATORY_PHYMODE_NO11B BIT(1) +#define REGULATORY_PHYMODE_NO11G BIT(2) +#define REGULATORY_CHAN_NO11N BIT(3) +#define REGULATORY_PHYMODE_NO11AC BIT(4) +#define REGULATORY_PHYMODE_NO11AX BIT(5) + +/** + * enum dfs_reg - DFS region + * @DFS_UNINIT_REGION: un-initialized region + * @DFS_FCC_REGION: FCC region + * @DFS_ETSI_REGION: ETSI region + * @DFS_MKK_REGION: MKK region + * @DFS_CN_REGION: China region + * @DFS_KR_REGION: Korea region + * @DFS_UNDEF_REGION: Undefined region + */ +enum dfs_reg { + DFS_UNINIT_REGION = 0, + DFS_FCC_REGION = 1, + DFS_ETSI_REGION = 2, + DFS_MKK_REGION = 3, + DFS_CN_REGION = 4, + DFS_KR_REGION = 5, + DFS_UNDEF_REGION = 0xFFFF, +}; #ifdef CONFIG_LEGACY_CHAN_ENUM diff --git a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h index a81a4d86da34..bf4f632683ff 100644 --- a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h +++ b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. 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 @@ -26,46 +26,137 @@ #ifndef __WLAN_REG_SERVICES_API_H #define __WLAN_REG_SERVICES_API_H -#include "../../core/src/reg_services.h" -#include +/** + * wlan_reg_min_24ghz_ch_num() - Get minimum 2.4GHz channel number + * + * Return: Minimum 2.4GHz channel number + */ +#define WLAN_REG_MIN_24GHZ_CH_NUM wlan_reg_min_24ghz_ch_num() +uint32_t wlan_reg_min_24ghz_ch_num(void); +/** + * wlan_reg_max_24ghz_ch_num() - Get maximum 2.4GHz channel number + * + * Return: Maximum 2.4GHz channel number + */ +#define WLAN_REG_MAX_24GHZ_CH_NUM wlan_reg_max_24ghz_ch_num() +uint32_t wlan_reg_max_24ghz_ch_num(void); -#define WLAN_REG_MIN_24GHZ_CH_NUM REG_MIN_24GHZ_CH_NUM -#define WLAN_REG_MAX_24GHZ_CH_NUM REG_MAX_24GHZ_CH_NUM -#define WLAN_REG_MIN_5GHZ_CH_NUM REG_MIN_5GHZ_CH_NUM -#define WLAN_REG_MAX_5GHZ_CH_NUM REG_MAX_5GHZ_CH_NUM +/** + * wlan_reg_min_5ghz_ch_num() - Get minimum 5GHz channel number + * + * Return: Minimum 5GHz channel number + */ +#define WLAN_REG_MIN_5GHZ_CH_NUM wlan_reg_min_5ghz_ch_num() +uint32_t wlan_reg_min_5ghz_ch_num(void); -#define WLAN_REG_IS_24GHZ_CH(chan) REG_IS_24GHZ_CH(chan) -#define WLAN_REG_IS_5GHZ_CH(chan) REG_IS_5GHZ_CH(chan) +/** + * wlan_reg_max_5ghz_ch_num() - Get maximum 5GHz channel number + * + * Return: Maximum 5GHz channel number + */ +#define WLAN_REG_MAX_5GHZ_CH_NUM wlan_reg_max_5ghz_ch_num() +uint32_t wlan_reg_max_5ghz_ch_num(void); -#define WLAN_REG_IS_24GHZ_CH_FREQ(freq) REG_IS_24GHZ_CH_FREQ(freq) -#define WLAN_REG_IS_5GHZ_CH_FREQ(freq) REG_IS_5GHZ_FREQ(freq) +/** + * wlan_reg_is_24ghz_ch() - Check if the given channel number is 2.4GHz + * @chan: Channel number + * + * Return: true if channel number is 2.4GHz, else false + */ +#define WLAN_REG_IS_24GHZ_CH(chan) wlan_reg_is_24ghz_ch(chan) +bool wlan_reg_is_24ghz_ch(uint32_t chan); + +/** + * wlan_reg_is_5ghz_ch() - Check if the given channel number is 5GHz + * @chan: Channel number + * + * Return: true if channel number is 5GHz, else false + */ +#define WLAN_REG_IS_5GHZ_CH(chan) wlan_reg_is_5ghz_ch(chan) +bool wlan_reg_is_5ghz_ch(uint32_t chan); + +/** + * wlan_reg_is_24ghz_ch_freq() - Check if the given channel frequency is 2.4GHz + * @freq: Channel frequency + * + * Return: true if channel frequency is 2.4GHz, else false + */ +#define WLAN_REG_IS_24GHZ_CH_FREQ(freq) wlan_reg_is_24ghz_ch_freq(freq) +bool wlan_reg_is_24ghz_ch_freq(uint32_t freq); + +/** + * wlan_reg_is_5ghz_ch_freq() - Check if the given channel frequency is 5GHz + * @freq: Channel frequency + * + * Return: true if channel frequency is 5GHz, else false + */ +#define WLAN_REG_IS_5GHZ_CH_FREQ(freq) wlan_reg_is_5ghz_ch_freq(freq) +bool wlan_reg_is_5ghz_ch_freq(uint32_t freq); #ifndef CONFIG_LEGACY_CHAN_ENUM -#define WLAN_REG_IS_49GHZ_FREQ(freq) REG_IS_49GHZ_FREQ(freq) +/** + * wlan_reg_is_49ghz_freq() - Check if the given channel frequency is 4.9GHz + * @freq: Channel frequency + * + * Return: true if channel frequency is 4.9GHz, else false + */ +#define WLAN_REG_IS_49GHZ_FREQ(freq) wlan_reg_is_49ghz_freq(freq) +bool wlan_reg_is_49ghz_freq(uint32_t freq); #endif -#define WLAN_REG_CH_NUM(ch_enum) REG_CH_NUM(ch_enum) -#define WLAN_REG_CH_TO_FREQ(ch_enum) REG_CH_TO_FREQ(ch_enum) +/** + * wlan_reg_ch_num() - Get channel number from channel enum + * @ch_enum: Channel enum + * + * Return: channel number + */ +#define WLAN_REG_CH_NUM(ch_enum) wlan_reg_ch_num(ch_enum) +uint32_t wlan_reg_ch_num(uint32_t ch_enum); +/** + * wlan_reg_ch_to_freq() - Get channel frequency from channel enum + * @ch_enum: Channel enum + * + * Return: channel frequency + */ +#define WLAN_REG_CH_TO_FREQ(ch_enum) wlan_reg_ch_to_freq(ch_enum) +uint32_t wlan_reg_ch_to_freq(uint32_t ch_enum); + +/** + * wlan_reg_is_same_band_channels() - Check if given channel numbers have same + * band + * @chan_num1: Channel number1 + * @chan_num2: Channel number2 + * + * Return: true if both the channels has the same band. + */ #define WLAN_REG_IS_SAME_BAND_CHANNELS(chan_num1, chan_num2) \ - (chan_num1 && chan_num2 && \ - (WLAN_REG_IS_5GHZ_CH(chan_num1) == WLAN_REG_IS_5GHZ_CH(chan_num2))) - + wlan_reg_is_same_band_channels(chan_num1, chan_num2) +bool wlan_reg_is_same_band_channels(uint32_t chan_num1, uint32_t chan_num2); +/** + * wlan_reg_is_channel_valid_5g_sbs() Check if the given channel is 5G SBS. + * @curchan: current channel + * @newchan:new channel + * + * Return: true if the given channel is a valid 5G SBS + */ #define WLAN_REG_IS_CHANNEL_VALID_5G_SBS(curchan, newchan) \ - (curchan > newchan ? \ - REG_CH_TO_FREQ(reg_get_chan_enum(curchan)) \ - - REG_CH_TO_FREQ(reg_get_chan_enum(newchan)) \ - > REG_SBS_SEPARATION_THRESHOLD : \ - REG_CH_TO_FREQ(reg_get_chan_enum(newchan)) \ - - REG_CH_TO_FREQ(reg_get_chan_enum(curchan)) \ - > REG_SBS_SEPARATION_THRESHOLD) + wlan_reg_is_channel_valid_5g_sbs(curchan, newchan) +bool wlan_reg_is_channel_valid_5g_sbs(uint32_t curchan, uint32_t newchan); #define WLAN_REG_INVALID_CHANNEL_ID #define WLAN_REG_GET_24_END_CHAN_NUM 14 -#define WLAN_REG_CHAN_TO_BAND(chan_num) reg_chan_to_band(chan_num) +/** + * wlan_reg_chan_to_band() - Get band from channel number + * @chan_num: channel number + * + * Return: band info + */ +#define WLAN_REG_CHAN_TO_BAND(chan_num) wlan_reg_chan_to_band(chan_num) +enum band_info wlan_reg_chan_to_band(uint32_t chan_num); /** * wlan_reg_get_channel_list_with_power() - Provide the channel list with power @@ -86,6 +177,7 @@ QDF_STATUS wlan_reg_get_channel_list_with_power(struct wlan_objmgr_pdev *pdev, QDF_STATUS wlan_reg_read_default_country(struct wlan_objmgr_psoc *psoc, uint8_t *country); +#ifdef CONFIG_MCL_REGDB /** * wlan_reg_read_current_country() - Read the current country for the regdomain * @country: pointer to the country code. @@ -95,15 +187,6 @@ QDF_STATUS wlan_reg_read_default_country(struct wlan_objmgr_psoc *psoc, QDF_STATUS wlan_reg_read_current_country(struct wlan_objmgr_psoc *psoc, uint8_t *country); -/** - * wlan_reg_get_channel_state() - Get channel state from regulatory - * @ch: channel number. - * - * Return: channel state - */ -enum channel_state wlan_reg_get_channel_state(struct wlan_objmgr_pdev *pdev, - uint32_t ch); - /** * wlan_reg_chan_has_dfs_attribute() - check channel has dfs attribute flag * @ch: channel number. @@ -115,6 +198,61 @@ enum channel_state wlan_reg_get_channel_state(struct wlan_objmgr_pdev *pdev, bool wlan_reg_chan_has_dfs_attribute(struct wlan_objmgr_pdev *pdev, uint32_t ch); +/** + * wlan_reg_is_etsi13_srd_chan () - Checks if the ch is ETSI13 srd ch or not + * @pdev: pdev ptr + * @chan_num: channel + * + * Return: true or false + */ +bool wlan_reg_is_etsi13_srd_chan(struct wlan_objmgr_pdev *pdev, + uint8_t chan_num); + +/** + * wlan_reg_is_etsi13_regdmn() - Checks if current reg domain is ETSI13 or not + * @pdev: pdev ptr + * + * Return: true or false + */ +bool wlan_reg_is_etsi13_regdmn(struct wlan_objmgr_pdev *pdev); + +/** + * wlan_reg_is_etsi13_srd_chan_allowed_master_mode() - Checks if regdmn is + * ETSI13 and SRD channels are allowed in master mode or not. + * + * @pdev: pdev ptr + * + * Return: true or false + */ +bool wlan_reg_is_etsi13_srd_chan_allowed_master_mode(struct wlan_objmgr_pdev + *pdev); +#endif + +/** + * wlan_reg_is_world() - reg is world mode + * @country: The country information + * + * Return: true or false + */ +bool wlan_reg_is_world(uint8_t *country); + +/** + * wlan_reg_get_chan_enum() - Get channel enum for given channel number + * @chan_num: Channel number + * + * Return: Channel enum + */ +enum channel_enum wlan_reg_get_chan_enum(uint32_t chan_num); + +/** + * wlan_reg_get_channel_state() - Get channel state from regulatory + * @ch: channel number. + * + * Return: channel state + */ +enum channel_state wlan_reg_get_channel_state(struct wlan_objmgr_pdev *pdev, + uint32_t ch); + /** * wlan_reg_get_5g_bonded_channel_state() - Get 5G bonded channel state * @pdev: The physical dev to program country code or regdomain @@ -354,35 +492,6 @@ bool wlan_reg_is_dfs_ch(struct wlan_objmgr_pdev *pdev, uint32_t chan); */ bool wlan_reg_is_dsrc_chan(struct wlan_objmgr_pdev *pdev, uint8_t chan_num); -/** - * wlan_reg_is_etsi13_srd_chan () - Checks if the ch is ETSI13 srd ch or not - * @pdev: pdev ptr - * @chan_num: channel - * - * Return: true or false - */ -bool wlan_reg_is_etsi13_srd_chan(struct wlan_objmgr_pdev *pdev, - uint8_t chan_num); - -/** - * wlan_reg_is_etsi13_regdmn() - Checks if current reg domain is ETSI13 or not - * @pdev: pdev ptr - * - * Return: true or false - */ -bool wlan_reg_is_etsi13_regdmn(struct wlan_objmgr_pdev *pdev); - -/** - * wlan_reg_is_etsi13_srd_chan_allowed_master_mode() - Checks if regdmn is - * ETSI13 and SRD channels are allowed in master mode or not. - * - * @pdev: pdev ptr - * - * Return: true or false - */ -bool wlan_reg_is_etsi13_srd_chan_allowed_master_mode(struct wlan_objmgr_pdev - *pdev); - /** * wlan_reg_is_passive_or_disable_ch () - Checks chan state for passive * and disabled @@ -421,13 +530,6 @@ uint32_t wlan_reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, */ uint32_t wlan_reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, uint32_t chan); -/** - * wlan_reg_is_world() - reg is world mode - * @country: The country information - * - * Return: true or false - */ -bool wlan_reg_is_world(uint8_t *country); /** * wlan_reg_is_us() - reg is us country @@ -477,8 +579,7 @@ QDF_STATUS wlan_reg_set_11d_country(struct wlan_objmgr_pdev *pdev, * Return: true or false */ void wlan_reg_register_chan_change_callback(struct wlan_objmgr_psoc *psoc, - reg_chan_change_callback cbk, - void *arg); + void *cbk, void *arg); /** * wlan_reg_unregister_chan_change_callback () - remove chan change cbk @@ -488,7 +589,7 @@ void wlan_reg_register_chan_change_callback(struct wlan_objmgr_psoc *psoc, * Return: true or false */ void wlan_reg_unregister_chan_change_callback(struct wlan_objmgr_psoc *psoc, - reg_chan_change_callback cbk); + void *cbk); /** * wlan_reg_is_11d_offloaded() - 11d offloaded supported diff --git a/umac/regulatory/dispatcher/inc/wlan_reg_tgt_api.h b/umac/regulatory/dispatcher/inc/wlan_reg_tgt_api.h index 6338430d2caf..f4ab54c935b6 100644 --- a/umac/regulatory/dispatcher/inc/wlan_reg_tgt_api.h +++ b/umac/regulatory/dispatcher/inc/wlan_reg_tgt_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -26,10 +26,6 @@ #ifndef __WLAN_REG_TGT_API_H #define __WLAN_REG_TGT_API_H -#include -#include -#include - QDF_STATUS tgt_reg_process_master_chan_list(struct cur_regulatory_info *reg_info); diff --git a/umac/regulatory/dispatcher/inc/wlan_reg_ucfg_api.h b/umac/regulatory/dispatcher/inc/wlan_reg_ucfg_api.h index fa097dfbb66f..18129167ca64 100644 --- a/umac/regulatory/dispatcher/inc/wlan_reg_ucfg_api.h +++ b/umac/regulatory/dispatcher/inc/wlan_reg_ucfg_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -26,11 +26,6 @@ #ifndef __WLAN_REG_UCFG_API_H #define __WLAN_REG_UCFG_API_H -#include -#include -#include "../../core/src/reg_services.h" -#include - typedef QDF_STATUS (*reg_event_cb)(void *status_struct); /** @@ -274,8 +269,7 @@ QDF_STATUS ucfg_reg_get_regd_rules(struct wlan_objmgr_pdev *pdev, * Return: void */ void ucfg_reg_register_chan_change_callback(struct wlan_objmgr_psoc *psoc, - reg_chan_change_callback cbk, - void *arg); + void *cbk, void *arg); /** * ucfg_reg_unregister_chan_change_callback () - remove chan change cbk @@ -285,7 +279,7 @@ void ucfg_reg_register_chan_change_callback(struct wlan_objmgr_psoc *psoc, * Return: void */ void ucfg_reg_unregister_chan_change_callback(struct wlan_objmgr_psoc *psoc, - reg_chan_change_callback cbk); + void *cbk); /** * ucfg_reg_get_cc_and_src () - get country code and src diff --git a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c index 2a23132837b0..c4e3b4d91803 100644 --- a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c +++ b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -25,10 +25,21 @@ #include #include +#include +#include #include -#include "../../core/src/reg_services.h" -#include "../../core/src/reg_priv.h" +#include +#include +#include "../../core/src/reg_priv_objs.h" +#include "../../core/src/reg_getset.h" +#include "../../core/src/reg_services_common.h" +#include "../../core/src/reg_db.h" #include "../../core/src/reg_db_parser.h" +#include <../../core/src/reg_build_chan_list.h> +#include <../../core/src/reg_opclass.h> +#include <../../core/src/reg_callbacks.h> +#include <../../core/src/reg_host_11d.h> +#include /** * wlan_reg_get_channel_list_with_power() - Provide the channel list with power @@ -510,17 +521,18 @@ bool wlan_reg_is_us(uint8_t *country) } void wlan_reg_register_chan_change_callback(struct wlan_objmgr_psoc *psoc, - reg_chan_change_callback cbk, - void *arg) + void *cbk, void *arg) { - reg_register_chan_change_callback(psoc, cbk, arg); + reg_register_chan_change_callback(psoc, (reg_chan_change_callback)cbk, + arg); } void wlan_reg_unregister_chan_change_callback(struct wlan_objmgr_psoc *psoc, - reg_chan_change_callback cbk) + void *cbk) { - reg_unregister_chan_change_callback(psoc, cbk); + reg_unregister_chan_change_callback(psoc, + (reg_chan_change_callback)cbk); } bool wlan_reg_is_11d_offloaded(struct wlan_objmgr_psoc *psoc) @@ -613,3 +625,86 @@ QDF_STATUS wlan_reg_get_curr_regdomain(struct wlan_objmgr_pdev *pdev, { return reg_get_curr_regdomain(pdev, cur_regdmn); } + +uint32_t wlan_reg_min_24ghz_ch_num(void) +{ + return reg_min_24ghz_ch_num(); +} + +uint32_t wlan_reg_max_24ghz_ch_num(void) +{ + return reg_max_24ghz_ch_num(); +} + +uint32_t wlan_reg_min_5ghz_ch_num(void) +{ + return reg_min_5ghz_ch_num(); +} + +uint32_t wlan_reg_max_5ghz_ch_num(void) +{ + return reg_max_5ghz_ch_num(); +} + +bool wlan_reg_is_24ghz_ch(uint32_t chan) +{ + return reg_is_24ghz_ch(chan); +} + +bool wlan_reg_is_5ghz_ch(uint32_t chan) +{ + return reg_is_5ghz_ch(chan); +} + +bool wlan_reg_is_24ghz_ch_freq(uint32_t freq) +{ + return reg_is_24ghz_ch_freq(freq); +} + +bool wlan_reg_is_5ghz_ch_freq(uint32_t freq) +{ + return reg_is_5ghz_ch_freq(freq); +} + +#ifndef CONFIG_LEGACY_CHAN_ENUM +bool wlan_reg_is_49ghz_freq(uint32_t freq) +{ + return reg_is_49ghz_freq(freq); +} +#endif + +uint32_t wlan_reg_ch_num(uint32_t ch_enum) +{ + return reg_ch_num(ch_enum); +} + +uint32_t wlan_reg_ch_to_freq(uint32_t ch_enum) +{ + return reg_ch_to_freq(ch_enum); +} + +bool wlan_reg_is_same_band_channels(uint32_t chan_num1, uint32_t chan_num2) +{ + return reg_is_same_band_channels(chan_num1, chan_num2); +} + +bool wlan_reg_is_channel_valid_5g_sbs(uint32_t curchan, uint32_t newchan) +{ + return reg_is_channel_valid_5g_sbs(curchan, newchan); +} + +enum band_info wlan_reg_chan_to_band(uint32_t chan_num) +{ + return reg_chan_to_band(chan_num); +} + +/** + * wlan_reg_get_chan_enum() - Get channel enum for given channel number + * @chan_num: Channel number + * + * Return: Channel enum + */ +enum channel_enum wlan_reg_get_chan_enum(uint32_t chan_num) +{ + return reg_get_chan_enum(chan_num); +} diff --git a/umac/regulatory/dispatcher/src/wlan_reg_tgt_api.c b/umac/regulatory/dispatcher/src/wlan_reg_tgt_api.c index 0c03d4af3b26..e84db49f344b 100644 --- a/umac/regulatory/dispatcher/src/wlan_reg_tgt_api.c +++ b/umac/regulatory/dispatcher/src/wlan_reg_tgt_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -24,8 +24,16 @@ #include #include +#include +#include #include -#include "../../core/src/reg_services.h" +#include +#include <../../core/src/reg_priv_objs.h> +#include <../../core/src/reg_getset.h> +#include <../../core/src/reg_services_common.h> +#include <../../core/src/reg_lte.h> +#include <../../core/src/reg_build_chan_list.h> +#include <../../core/src/reg_host_11d.h> /** * tgt_process_master_chan_list() - process master channel list diff --git a/umac/regulatory/dispatcher/src/wlan_reg_ucfg_api.c b/umac/regulatory/dispatcher/src/wlan_reg_ucfg_api.c index 2b78bf641da0..bfcd9eba2b9c 100644 --- a/umac/regulatory/dispatcher/src/wlan_reg_ucfg_api.c +++ b/umac/regulatory/dispatcher/src/wlan_reg_ucfg_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -22,8 +22,16 @@ * @brief contains regulatory user config interface definations */ +#include #include -#include "../../core/src/reg_services.h" +#include +#include <../../core/src/reg_priv_objs.h> +#include <../../core/src/reg_getset.h> +#include <../../core/src/reg_services_common.h> +#include <../../core/src/reg_lte.h> +#include <../../core/src/reg_host_11d.h> +#include <../../core/src/reg_build_chan_list.h> +#include <../../core/src/reg_callbacks.h> #include QDF_STATUS ucfg_reg_register_event_handler(uint8_t vdev_id, reg_event_cb cb, @@ -108,6 +116,7 @@ QDF_STATUS ucfg_reg_get_current_cc(struct wlan_objmgr_pdev *pdev, return reg_get_current_cc(pdev, rd); } +#ifdef CONFIG_MCL_REGDB /** * ucfg_reg_set_band() - Sets the band information for the PDEV * @pdev: The physical pdev to set the band for @@ -134,30 +143,6 @@ QDF_STATUS ucfg_reg_notify_sap_event(struct wlan_objmgr_pdev *pdev, return reg_notify_sap_event(pdev, sap_state); } -#ifdef DISABLE_CHANNEL_LIST -/** - * ucfg_reg_cache_channel_state() - Cache the current state of the channles - * @pdev: The physical dev to cache the channels for - * @channel_list: List of the channels for which states needs to be cached - * @num_channels: Number of channels in the list - * - */ -void ucfg_reg_cache_channel_state(struct wlan_objmgr_pdev *pdev, - uint32_t *channel_list, uint32_t num_channels) -{ - reg_cache_channel_state(pdev, channel_list, num_channels); -} - -/** - * ucfg_reg_restore_cached_channels() - Cache the current state of the channles - * @pdev: The physical dev to cache the channels for - */ -void ucfg_reg_restore_cached_channels(struct wlan_objmgr_pdev *pdev) -{ - reg_restore_cached_channels(pdev); -} -#endif - /** * ucfg_reg_set_fcc_constraint() - apply fcc constraints on channels 12/13 * @pdev: The physical pdev to reduce tx power for @@ -173,25 +158,12 @@ QDF_STATUS ucfg_reg_set_fcc_constraint(struct wlan_objmgr_pdev *pdev, return reg_set_fcc_constraint(pdev, fcc_constraint); } - -/** - * ucfg_reg_get_default_country() - Get the default regulatory country - * @psoc: The physical SoC to get default country from - * @country_code: the buffer to populate the country code into - * - * Return: QDF_STATUS - */ -QDF_STATUS ucfg_reg_get_default_country(struct wlan_objmgr_psoc *psoc, - uint8_t *country_code) -{ - return reg_read_default_country(psoc, country_code); -} - QDF_STATUS ucfg_reg_get_current_country(struct wlan_objmgr_psoc *psoc, uint8_t *country_code) { return reg_read_current_country(psoc, country_code); } + /** * ucfg_reg_set_default_country() - Set the default regulatory country * @psoc: The physical SoC to set default country for @@ -204,6 +176,20 @@ QDF_STATUS ucfg_reg_set_default_country(struct wlan_objmgr_psoc *psoc, { return reg_set_default_country(psoc, country); } +#endif + +/** + * ucfg_reg_get_default_country() - Get the default regulatory country + * @psoc: The physical SoC to get default country from + * @country_code: the buffer to populate the country code into + * + * Return: QDF_STATUS + */ +QDF_STATUS ucfg_reg_get_default_country(struct wlan_objmgr_psoc *psoc, + uint8_t *country_code) +{ + return reg_read_default_country(psoc, country_code); +} /** * ucfg_reg_set_country() - Set the current regulatory country @@ -249,16 +235,17 @@ QDF_STATUS ucfg_reg_get_curr_band(struct wlan_objmgr_pdev *pdev, } void ucfg_reg_register_chan_change_callback(struct wlan_objmgr_psoc *psoc, - reg_chan_change_callback cbk, - void *arg) + void *cbk, void *arg) { - reg_register_chan_change_callback(psoc, cbk, arg); + reg_register_chan_change_callback(psoc, (reg_chan_change_callback)cbk, + arg); } void ucfg_reg_unregister_chan_change_callback(struct wlan_objmgr_psoc *psoc, - reg_chan_change_callback cbk) + void *cbk) { - reg_unregister_chan_change_callback(psoc, cbk); + reg_unregister_chan_change_callback(psoc, + (reg_chan_change_callback)cbk); } enum country_src ucfg_reg_get_cc_and_src(struct wlan_objmgr_psoc *psoc, @@ -298,3 +285,27 @@ QDF_STATUS ucfg_reg_set_hal_reg_cap(struct wlan_objmgr_psoc *psoc, return reg_set_hal_reg_cap(psoc, hal_reg_cap, phy_cnt); } qdf_export_symbol(ucfg_reg_set_hal_reg_cap); + +#ifdef DISABLE_CHANNEL_LIST +/** + * ucfg_reg_cache_channel_state() - Cache the current state of the channles + * @pdev: The physical dev to cache the channels for + * @channel_list: List of the channels for which states needs to be cached + * @num_channels: Number of channels in the list + * + */ +void ucfg_reg_cache_channel_state(struct wlan_objmgr_pdev *pdev, + uint32_t *channel_list, uint32_t num_channels) +{ + reg_cache_channel_state(pdev, channel_list, num_channels); +} + +/** + * ucfg_reg_restore_cached_channels() - Cache the current state of the channles + * @pdev: The physical dev to cache the channels for + */ +void ucfg_reg_restore_cached_channels(struct wlan_objmgr_pdev *pdev) +{ + reg_restore_cached_channels(pdev); +} +#endif diff --git a/umac/wifi_pos/src/wifi_pos_main.c b/umac/wifi_pos/src/wifi_pos_main.c index 086321d7e117..4bdad7e1017d 100644 --- a/umac/wifi_pos/src/wifi_pos_main.c +++ b/umac/wifi_pos/src/wifi_pos_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2019 The Linux Foundation. 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 @@ -270,7 +270,7 @@ static uint32_t wifi_pos_get_valid_channels(uint8_t *channels, uint32_t num_ch, uint32_t i, num_valid_channels = 0; for (i = 0; i < num_ch; i++) { - if (INVALID_CHANNEL == reg_get_chan_enum(channels[i])) + if (wlan_reg_get_chan_enum(channels[i]) == INVALID_CHANNEL) continue; valid_channel_list[num_valid_channels++] = channels[i]; }