diff --git a/umac/regulatory/core/src/reg_priv.h b/umac/regulatory/core/src/reg_priv.h index ad522dd5d279..ae83a0206163 100644 --- a/umac/regulatory/core/src/reg_priv.h +++ b/umac/regulatory/core/src/reg_priv.h @@ -54,9 +54,12 @@ struct wlan_regulatory_psoc_priv_obj { bool nol_chan[NUM_CHANNELS]; char default_country[REG_ALPHA2_LEN + 1]; char current_country[REG_ALPHA2_LEN + 1]; + enum country_src cc_src; struct wlan_objmgr_psoc *psoc_ptr; uint32_t phybitmap; enum dfs_reg dfs_region; + bool new_user_ctry_pending; + bool new_11d_ctry_pending; char country_11d[REG_ALPHA2_LEN + 1]; bool dfs_enabled; bool set_fcc_channel; @@ -65,6 +68,9 @@ struct wlan_regulatory_psoc_priv_obj { bool enable_11d_supp_original; bool enable_11d_supp_current; bool userspace_country_priority; + struct chan_change_cbk_entry cbk_list[REG_MAX_CHAN_CHANGE_CBKS]; + uint8_t num_chan_change_cbks; + qdf_spinlock_t cbk_list_lock; }; struct wlan_regulatory_pdev_priv_obj { diff --git a/umac/regulatory/core/src/reg_services.c b/umac/regulatory/core/src/reg_services.c index 80390b857d63..ba23215db643 100644 --- a/umac/regulatory/core/src/reg_services.c +++ b/umac/regulatory/core/src/reg_services.c @@ -33,6 +33,7 @@ #include "reg_services.h" #include "reg_priv.h" #include "reg_db_parser.h" +#include #define MAX_PWR_FCC_CHAN_12 8 #define MAX_PWR_FCC_CHAN_13 2 @@ -773,7 +774,7 @@ void reg_set_channel_params(struct wlan_objmgr_pdev *pdev, } QDF_STATUS reg_get_curr_band(struct wlan_objmgr_pdev *pdev, - enum band_info *band) + enum band_info *band) { struct wlan_regulatory_pdev_priv_obj *pdev_reg; @@ -789,7 +790,7 @@ QDF_STATUS reg_get_curr_band(struct wlan_objmgr_pdev *pdev, } QDF_STATUS reg_read_default_country(struct wlan_objmgr_psoc *psoc, - uint8_t *country_code) + uint8_t *country_code) { struct wlan_regulatory_psoc_priv_obj *psoc_reg; @@ -818,7 +819,7 @@ QDF_STATUS reg_read_default_country(struct wlan_objmgr_psoc *psoc, * Return: QDF_STATUS */ QDF_STATUS reg_set_default_country(struct wlan_objmgr_psoc *psoc, - uint8_t *country) + uint8_t *country) { struct wlan_regulatory_psoc_priv_obj *psoc_reg; @@ -839,7 +840,8 @@ QDF_STATUS reg_set_default_country(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } -QDF_STATUS reg_set_country(struct wlan_objmgr_pdev *pdev, uint8_t *country) +QDF_STATUS reg_set_country(struct wlan_objmgr_pdev *pdev, + uint8_t *country) { struct wlan_regulatory_psoc_priv_obj *psoc_reg; struct wlan_lmac_if_reg_tx_ops *tx_ops; @@ -860,14 +862,28 @@ QDF_STATUS reg_set_country(struct wlan_objmgr_pdev *pdev, uint8_t *country) return QDF_STATUS_E_INVAL; } - reg_info("setting current_country:%s", country); - qdf_mem_copy(psoc_reg->current_country, - country, sizeof(psoc_reg->current_country)); + if (!qdf_mem_cmp(psoc_reg->current_country, + country, REG_ALPHA2_LEN)) { + reg_err("country is not different"); + return QDF_STATUS_E_INVAL; + } + + reg_debug("programming new country:%s to firmware", country); + qdf_mem_copy(country_code.country, - country, sizeof(psoc_reg->current_country)); + country, REG_ALPHA2_LEN + 1); country_code.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); - tx_ops = get_reg_psoc_tx_ops(psoc); - tx_ops->set_country_code(psoc, &country_code); + + psoc_reg->new_user_ctry_pending = true; + + tx_ops = reg_get_psoc_tx_ops(psoc); + + if (tx_ops->set_country_code) { + tx_ops->set_country_code(psoc, &country_code); + } else { + reg_err("country set fw handler not present"); + return QDF_STATUS_E_FAULT; + } return QDF_STATUS_SUCCESS; } @@ -917,7 +933,7 @@ void reg_get_dfs_region(struct wlan_objmgr_psoc *psoc, * Return: None */ void reg_set_dfs_region(struct wlan_objmgr_psoc *psoc, - enum dfs_reg dfs_reg) + enum dfs_reg dfs_reg) { struct wlan_regulatory_psoc_priv_obj *soc_reg; @@ -999,7 +1015,8 @@ uint32_t reg_get_channel_freq(struct wlan_objmgr_pdev *pdev, } -bool reg_is_dfs_ch(struct wlan_objmgr_pdev *pdev, uint32_t chan) +bool reg_is_dfs_ch(struct wlan_objmgr_pdev *pdev, + uint32_t chan) { enum channel_state ch_state; @@ -1008,7 +1025,8 @@ bool reg_is_dfs_ch(struct wlan_objmgr_pdev *pdev, uint32_t chan) return ch_state == CHANNEL_STATE_DFS; } -bool reg_is_passive_or_disable_ch(struct wlan_objmgr_pdev *pdev, uint32_t chan) +bool reg_is_passive_or_disable_ch(struct wlan_objmgr_pdev *pdev, + uint32_t chan) { enum channel_state ch_state; @@ -1019,7 +1037,8 @@ bool reg_is_passive_or_disable_ch(struct wlan_objmgr_pdev *pdev, uint32_t chan) } -uint32_t reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, uint32_t freq) +uint32_t reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, + uint32_t freq) { uint32_t count; struct regulatory_channel *chan_list; @@ -1043,7 +1062,8 @@ uint32_t reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, uint32_t freq) return 0; } -uint32_t reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, uint32_t chan_num) +uint32_t reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, + uint32_t chan_num) { uint32_t count; struct regulatory_channel *chan_list; @@ -1073,7 +1093,6 @@ enum band_info reg_chan_to_band(uint32_t chan_num) return BAND_2G; return BAND_5G; - } uint16_t reg_dmn_get_chanwidth_from_opclass(uint8_t *country, @@ -1109,7 +1128,8 @@ uint16_t reg_dmn_get_chanwidth_from_opclass(uint8_t *country, } -uint16_t reg_dmn_get_opclass_from_channel(uint8_t *country, uint8_t channel, +uint16_t reg_dmn_get_opclass_from_channel(uint8_t *country, + uint8_t channel, uint8_t offset) { const struct reg_dmn_op_class_map_t *class = NULL; @@ -1139,7 +1159,8 @@ uint16_t reg_dmn_get_opclass_from_channel(uint8_t *country, uint8_t channel, return 0; } -uint16_t reg_dmn_set_curr_opclasses(uint8_t num_classes, uint8_t *class) +uint16_t reg_dmn_set_curr_opclasses(uint8_t num_classes, + uint8_t *class) { uint8_t i; @@ -1156,7 +1177,8 @@ uint16_t reg_dmn_set_curr_opclasses(uint8_t num_classes, uint8_t *class) return 0; } -uint16_t reg_dmn_get_curr_opclasses(uint8_t *num_classes, uint8_t *class) +uint16_t reg_dmn_get_curr_opclasses(uint8_t *num_classes, + uint8_t *class) { uint8_t i; @@ -1215,7 +1237,6 @@ static void reg_fill_channel_info(enum channel_enum chan_enum, master_list[chan_enum].min_bw = min_bw; if (20 == master_list[chan_enum].max_bw) master_list[chan_enum].max_bw = reg_rule->max_bw; - } @@ -1259,7 +1280,6 @@ static void populate_band_channels(enum channel_enum start_chan, mas_chan_list, min_bw); } } - } static void update_max_bw_per_rule(uint32_t num_reg_rules, @@ -1293,9 +1313,9 @@ static void do_auto_bw_correction(uint32_t num_reg_rules, } } -static void -modify_chan_list_for_dfs_channels(struct regulatory_channel *chan_list, - bool dfs_enabled) +static void modify_chan_list_for_dfs_channels(struct regulatory_channel + *chan_list, + bool dfs_enabled) { enum channel_enum chan_enum; @@ -1303,8 +1323,7 @@ modify_chan_list_for_dfs_channels(struct regulatory_channel *chan_list, return; for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { - if (CHANNEL_STATE_DFS == - chan_list[chan_enum].state) { + if (CHANNEL_STATE_DFS == chan_list[chan_enum].state) { chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; chan_list[chan_enum].chan_flags |= @@ -1313,10 +1332,9 @@ modify_chan_list_for_dfs_channels(struct regulatory_channel *chan_list, } } -static void -modify_chan_list_for_indoor_channels(struct regulatory_channel - *chan_list, - bool indoor_chan_enabled) +static void modify_chan_list_for_indoor_channels(struct regulatory_channel + *chan_list, bool + indoor_chan_enabled) { enum channel_enum chan_enum; @@ -1334,10 +1352,8 @@ modify_chan_list_for_indoor_channels(struct regulatory_channel } } -static void -modify_chan_list_for_band(struct regulatory_channel - *chan_list, - enum band_info band_val) +static void modify_chan_list_for_band(struct regulatory_channel *chan_list, + enum band_info band_val) { enum channel_enum chan_enum; @@ -1347,8 +1363,7 @@ modify_chan_list_for_band(struct regulatory_channel chan_enum++) { chan_list[chan_enum].chan_flags |= REGULATORY_CHAN_DISABLED; - chan_list[chan_enum].state = - CHANNEL_STATE_DISABLE; + chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; } } @@ -1358,16 +1373,14 @@ modify_chan_list_for_band(struct regulatory_channel chan_enum++) { chan_list[chan_enum].chan_flags |= REGULATORY_CHAN_DISABLED; - chan_list[chan_enum].state = - CHANNEL_STATE_DISABLE; + chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; } } } -static void -modify_chan_list_for_fcc_channel(struct regulatory_channel - *chan_list, - bool set_fcc_channel) +static void modify_chan_list_for_fcc_channel(struct regulatory_channel + *chan_list, + bool set_fcc_channel) { if (set_fcc_channel) { chan_list[CHAN_ENUM_12].tx_power = MAX_PWR_FCC_CHAN_12; @@ -1376,8 +1389,7 @@ modify_chan_list_for_fcc_channel(struct regulatory_channel } static void -modify_chan_list_for_nol_list(struct regulatory_channel - *chan_list) +modify_chan_list_for_nol_list(struct regulatory_channel *chan_list) { enum channel_enum chan_enum; @@ -1393,8 +1405,7 @@ modify_chan_list_for_nol_list(struct regulatory_channel } static void -modify_chan_list_for_freq_range(struct regulatory_channel - *chan_list, +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, @@ -1460,13 +1471,244 @@ modify_chan_list_for_freq_range(struct regulatory_channel } } +static void init_pdev_chan_list(struct wlan_regulatory_psoc_priv_obj + *psoc_priv_obj, + struct wlan_regulatory_pdev_priv_obj + *pdev_priv_obj) +{ + qdf_mem_copy(pdev_priv_obj->cur_chan_list, + psoc_priv_obj->mas_chan_list, + NUM_CHANNELS * sizeof(struct regulatory_channel)); +} + + +static void compute_pdev_current_chan_list(struct wlan_regulatory_pdev_priv_obj + *pdev_priv_obj) +{ + 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); + + modify_chan_list_for_band(pdev_priv_obj->cur_chan_list, + pdev_priv_obj->band_capability); + + modify_chan_list_for_dfs_channels(pdev_priv_obj->cur_chan_list, + pdev_priv_obj->dfs_enabled); + + modify_chan_list_for_nol_list(pdev_priv_obj->cur_chan_list); + + modify_chan_list_for_indoor_channels(pdev_priv_obj->cur_chan_list, + pdev_priv_obj->indoor_chan_enabled); + + modify_chan_list_for_fcc_channel(pdev_priv_obj->cur_chan_list, + pdev_priv_obj->set_fcc_channel); +} + +static void call_chan_change_cbks(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + struct chan_change_cbk_entry *cbk_list; + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + struct regulatory_channel cur_chan_list[NUM_CHANNELS]; + uint32_t ctr; + reg_chan_change_callback callback; + + psoc_priv_obj = reg_get_psoc_obj(psoc); + if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { + reg_alert("psoc reg component is NULL"); + return; + } + + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_alert("pdev reg component is NULL"); + return; + } + + qdf_mem_copy(cur_chan_list, + pdev_priv_obj->cur_chan_list, + NUM_CHANNELS * + sizeof(struct regulatory_channel)); + + cbk_list = psoc_priv_obj->cbk_list; + + for (ctr = 0; ctr < REG_MAX_CHAN_CHANGE_CBKS; ctr++) { + callback = NULL; + qdf_spin_lock_bh(&psoc_priv_obj->cbk_list_lock); + if (cbk_list[ctr].cbk != NULL) + callback = cbk_list[ctr].cbk; + qdf_spin_unlock_bh(&psoc_priv_obj->cbk_list_lock); + if (callback != NULL) + callback(psoc, pdev, cur_chan_list, + cbk_list[ctr].arg); + } +} + +static struct reg_sched_payload +*reg_alloc_and_fill_payload(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + struct reg_sched_payload *payload; + + payload = qdf_mem_malloc(sizeof(*payload)); + if (payload != NULL) { + payload->psoc = psoc; + payload->pdev = pdev; + } + + return payload; +} + +static QDF_STATUS chan_change_flush_cbk_sb(struct scheduler_msg *msg) +{ + struct reg_sched_payload *load = msg->bodyptr; + struct wlan_objmgr_psoc *psoc = load->psoc; + struct wlan_objmgr_pdev *pdev = load->pdev; + + wlan_objmgr_pdev_release_ref(pdev, WLAN_REGULATORY_SB_ID); + wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID); + qdf_mem_free(load); + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS sched_chan_change_cbks_sb(struct scheduler_msg *msg) +{ + struct reg_sched_payload *load = msg->bodyptr; + struct wlan_objmgr_psoc *psoc = load->psoc; + struct wlan_objmgr_pdev *pdev = load->pdev; + + call_chan_change_cbks(psoc, pdev); + + wlan_objmgr_pdev_release_ref(pdev, WLAN_REGULATORY_SB_ID); + wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID); + qdf_mem_free(load); + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS chan_change_flush_cbk_nb(struct scheduler_msg *msg) +{ + struct reg_sched_payload *load = msg->bodyptr; + struct wlan_objmgr_psoc *psoc = load->psoc; + struct wlan_objmgr_pdev *pdev = load->pdev; + + wlan_objmgr_pdev_release_ref(pdev, WLAN_REGULATORY_NB_ID); + wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_NB_ID); + qdf_mem_free(load); + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS sched_chan_change_cbks_nb(struct scheduler_msg *msg) +{ + struct reg_sched_payload *load = msg->bodyptr; + struct wlan_objmgr_psoc *psoc = load->psoc; + struct wlan_objmgr_pdev *pdev = load->pdev; + + call_chan_change_cbks(psoc, pdev); + + wlan_objmgr_pdev_release_ref(pdev, WLAN_REGULATORY_NB_ID); + wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_NB_ID); + qdf_mem_free(load); + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS send_scheduler_msg_sb(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + struct scheduler_msg msg = {0}; + struct reg_sched_payload *payload; + QDF_STATUS status; + + status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID); + if (QDF_IS_STATUS_ERROR(status)) { + reg_err("error taking psoc ref cnt"); + return status; + } + + status = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_REGULATORY_SB_ID); + if (QDF_IS_STATUS_ERROR(status)) { + wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID); + reg_err("error taking pdev ref cnt"); + return status; + } + + payload = reg_alloc_and_fill_payload(psoc, pdev); + if (payload == NULL) { + reg_err("payload memory alloc failed"); + wlan_objmgr_pdev_release_ref(pdev, WLAN_REGULATORY_SB_ID); + wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID); + return QDF_STATUS_E_NOMEM; + } + msg.bodyptr = payload; + msg.callback = sched_chan_change_cbks_sb; + msg.flush_callback = chan_change_flush_cbk_sb; + + status = scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg); + if (QDF_IS_STATUS_ERROR(status)) { + wlan_objmgr_pdev_release_ref(pdev, WLAN_REGULATORY_SB_ID); + wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID); + reg_err("scheduler msg posting failed"); + qdf_mem_free(payload); + } + + return status; +} + +static QDF_STATUS send_scheduler_msg_nb(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + struct scheduler_msg msg = {0}; + struct reg_sched_payload *payload; + QDF_STATUS status; + + status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_NB_ID); + if (QDF_IS_STATUS_ERROR(status)) { + reg_err("error taking psoc ref cnt"); + return status; + } + + status = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_REGULATORY_NB_ID); + if (QDF_IS_STATUS_ERROR(status)) { + wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_NB_ID); + reg_err("error taking pdev ref cnt"); + return status; + } + + payload = reg_alloc_and_fill_payload(psoc, pdev); + if (payload == NULL) { + reg_err("payload memory alloc failed"); + wlan_objmgr_pdev_release_ref(pdev, WLAN_REGULATORY_NB_ID); + wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_NB_ID); + return QDF_STATUS_E_NOMEM; + } + msg.bodyptr = payload; + msg.callback = sched_chan_change_cbks_nb; + msg.flush_callback = chan_change_flush_cbk_nb; + + status = scheduler_post_msg(QDF_MODULE_ID_OS_IF, &msg); + if (QDF_IS_STATUS_ERROR(status)) { + wlan_objmgr_pdev_release_ref(pdev, WLAN_REGULATORY_NB_ID); + wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_NB_ID); + reg_err("scheduler msg posting failed"); + qdf_mem_free(payload); + } + + return status; +} + static void reg_propagate_mas_chan_list_to_pdev(struct wlan_objmgr_psoc *psoc, - void *object, void *arg) + 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 channel_enum chan_enum; + enum direction *dir = arg; wlan_psoc_obj_lock(psoc); psoc_priv_obj = (struct wlan_regulatory_psoc_priv_obj *) @@ -1486,37 +1728,17 @@ static void reg_propagate_mas_chan_list_to_pdev(struct wlan_objmgr_psoc *psoc, return; } - qdf_mem_copy(pdev_priv_obj->cur_chan_list, - psoc_priv_obj->mas_chan_list, - NUM_CHANNELS * sizeof(struct regulatory_channel)); + init_pdev_chan_list(psoc_priv_obj, + pdev_priv_obj); - for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) - pdev_priv_obj->cur_chan_list[chan_enum].nol_chan = - psoc_priv_obj->nol_chan[chan_enum]; - - 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); - - modify_chan_list_for_dfs_channels(pdev_priv_obj->cur_chan_list, - pdev_priv_obj->dfs_enabled); - - modify_chan_list_for_indoor_channels(pdev_priv_obj->cur_chan_list, - pdev_priv_obj->indoor_chan_enabled); - - modify_chan_list_for_band(pdev_priv_obj->cur_chan_list, - pdev_priv_obj->band_capability); - - modify_chan_list_for_nol_list(pdev_priv_obj->cur_chan_list); - - modify_chan_list_for_fcc_channel(pdev_priv_obj->cur_chan_list, - pdev_priv_obj->set_fcc_channel); + compute_pdev_current_chan_list(pdev_priv_obj); + if (*dir == NORTHBOUND) + send_scheduler_msg_nb(psoc, pdev); + else + send_scheduler_msg_sb(psoc, pdev); } - QDF_STATUS reg_process_master_chan_list(struct cur_regulatory_info *regulat_info) { @@ -1525,12 +1747,23 @@ QDF_STATUS reg_process_master_chan_list(struct cur_regulatory_info 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; - QDF_STATUS status; + struct wlan_objmgr_psoc *psoc; enum channel_enum chan_enum; + QDF_STATUS status; + wlan_objmgr_ref_dbgid dbg_id; + enum direction dir; reg_debug("process reg master chan list"); - soc_reg = reg_get_psoc_obj(regulat_info->psoc); + if (regulat_info->status_code == REG_CURRENT_ALPHA2_NOT_FOUND) { + reg_err("current country not present in regdb"); + soc_reg->new_user_ctry_pending = false; + return QDF_STATUS_SUCCESS; + } + + 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; @@ -1549,12 +1782,14 @@ QDF_STATUS reg_process_master_chan_list(struct cur_regulatory_info mas_chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; mas_chan_list[chan_enum].nol_chan = false; - soc_reg->nol_chan[chan_enum] = false; } soc_reg->offload_enabled = regulat_info->offload_enabled; soc_reg->phybitmap = regulat_info->phybitmap; soc_reg->dfs_region = regulat_info->dfs_region; + soc_reg->num_phy = regulat_info->num_phy; + soc_reg->ctry_code = regulat_info->ctry_code; + soc_reg->reg_dmn_pair = regulat_info->reg_dmn_pair; qdf_mem_copy(soc_reg->default_country, regulat_info->alpha2, REG_ALPHA2_LEN + 1); qdf_mem_copy(soc_reg->current_country, regulat_info->alpha2, @@ -1575,23 +1810,47 @@ QDF_STATUS reg_process_master_chan_list(struct cur_regulatory_info reg_rule_5g, max_bw_5g); if (num_5g_reg_rules != 0) - do_auto_bw_correction(num_5g_reg_rules, reg_rule_5g, - max_bw_5g); + do_auto_bw_correction(num_5g_reg_rules, + reg_rule_5g, max_bw_5g); if (num_2g_reg_rules != 0) - populate_band_channels(CHAN_ENUM_1, CHAN_ENUM_14, + 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) - populate_band_channels(CHAN_ENUM_36, CHAN_ENUM_165, + populate_band_channels(MIN_5GHZ_CHANNEL, MAX_5GHZ_CHANNEL, reg_rule_5g, num_5g_reg_rules, min_bw_5g, mas_chan_list); - status = wlan_objmgr_iterate_obj_list(regulat_info->psoc, WLAN_PDEV_OP, - reg_propagate_mas_chan_list_to_pdev, - NULL, 1, WLAN_REGULATORY_SB_ID); + soc_reg->cc_src = SOURCE_DRIVER; + if (soc_reg->new_user_ctry_pending == true) { + soc_reg->new_user_ctry_pending = false; + soc_reg->cc_src = SOURCE_USERSPACE; + + } else if (soc_reg->new_11d_ctry_pending == true) { + soc_reg->new_11d_ctry_pending = false; + soc_reg->cc_src = SOURCE_11D; + } + + if (soc_reg->offload_enabled) { + dbg_id = WLAN_REGULATORY_NB_ID; + dir = NORTHBOUND; + } else { + dbg_id = WLAN_REGULATORY_SB_ID; + dir = SOUTHBOUND; + } + + status = wlan_objmgr_psoc_try_get_ref(psoc, dbg_id); + if (QDF_IS_STATUS_ERROR(status)) { + reg_err("error taking psoc ref cnt"); + return status; + } + status = wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, + reg_propagate_mas_chan_list_to_pdev, + &dir, 1, dbg_id); + wlan_objmgr_psoc_release_ref(psoc, dbg_id); return status; } @@ -1615,7 +1874,6 @@ QDF_STATUS wlan_regulatory_psoc_obj_created_notification( QDF_STATUS status; soc_reg_obj = qdf_mem_malloc(sizeof(*soc_reg_obj)); - if (NULL == soc_reg_obj) { reg_alert("Mem alloc failed for reg psoc priv obj"); return QDF_STATUS_E_NOMEM; @@ -1627,6 +1885,7 @@ QDF_STATUS wlan_regulatory_psoc_obj_created_notification( soc_reg_obj->set_fcc_channel = false; soc_reg_obj->band_capability = BAND_ALL; soc_reg_obj->indoor_chan_enabled = true; + qdf_spinlock_create(&soc_reg_obj->cbk_list_lock); mas_chan_list = soc_reg_obj->mas_chan_list; @@ -1641,7 +1900,6 @@ QDF_STATUS wlan_regulatory_psoc_obj_created_notification( mas_chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; mas_chan_list[chan_enum].nol_chan = false; - soc_reg_obj->nol_chan[chan_enum] = false; } status = wlan_objmgr_psoc_component_obj_attach(psoc, @@ -1680,6 +1938,7 @@ QDF_STATUS wlan_regulatory_psoc_obj_destroyed_notification( } soc_reg->psoc_ptr = NULL; + qdf_spinlock_destroy(&soc_reg->cbk_list_lock); status = wlan_objmgr_psoc_component_obj_detach(psoc, WLAN_UMAC_COMP_REGULATORY, @@ -1694,53 +1953,13 @@ QDF_STATUS wlan_regulatory_psoc_obj_destroyed_notification( return status; } -static void init_pdev_chan_list( - struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj, - struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) -{ - enum channel_enum chan_enum; - - qdf_mem_copy(pdev_priv_obj->cur_chan_list, - psoc_priv_obj->mas_chan_list, - NUM_CHANNELS * sizeof(struct regulatory_channel)); - - for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) - pdev_priv_obj->cur_chan_list[chan_enum].nol_chan = - psoc_priv_obj->nol_chan[chan_enum]; -} - - -static void compute_pdev_current_chan_list(struct wlan_regulatory_pdev_priv_obj - *pdev_priv_obj) -{ - 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); - - modify_chan_list_for_band(pdev_priv_obj->cur_chan_list, - pdev_priv_obj->band_capability); - - modify_chan_list_for_dfs_channels(pdev_priv_obj->cur_chan_list, - pdev_priv_obj->dfs_enabled); - - modify_chan_list_for_nol_list(pdev_priv_obj->cur_chan_list); - - modify_chan_list_for_indoor_channels(pdev_priv_obj->cur_chan_list, - pdev_priv_obj->indoor_chan_enabled); - - modify_chan_list_for_fcc_channel(pdev_priv_obj->cur_chan_list, - pdev_priv_obj->set_fcc_channel); -} - - QDF_STATUS reg_set_band(struct wlan_objmgr_pdev *pdev, enum band_info band) { struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; pdev_priv_obj = reg_get_pdev_obj(pdev); @@ -1767,7 +1986,6 @@ QDF_STATUS reg_set_band(struct wlan_objmgr_pdev *pdev, } reg_info("setting band_info: %d", band); - pdev_priv_obj->band_capability = band; init_pdev_chan_list(psoc_priv_obj, @@ -1775,7 +1993,9 @@ QDF_STATUS reg_set_band(struct wlan_objmgr_pdev *pdev, compute_pdev_current_chan_list(pdev_priv_obj); - return QDF_STATUS_SUCCESS; + status = send_scheduler_msg_sb(psoc, pdev); + + return status; } QDF_STATUS reg_set_fcc_constraint(struct wlan_objmgr_pdev *pdev, @@ -1784,6 +2004,7 @@ QDF_STATUS reg_set_fcc_constraint(struct wlan_objmgr_pdev *pdev, struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; pdev_priv_obj = reg_get_pdev_obj(pdev); if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { @@ -1816,7 +2037,9 @@ QDF_STATUS reg_set_fcc_constraint(struct wlan_objmgr_pdev *pdev, compute_pdev_current_chan_list(pdev_priv_obj); - return QDF_STATUS_SUCCESS; + status = send_scheduler_msg_sb(psoc, pdev); + + return status; } QDF_STATUS reg_enable_dfs_channels(struct wlan_objmgr_pdev *pdev, @@ -1825,6 +2048,7 @@ QDF_STATUS reg_enable_dfs_channels(struct wlan_objmgr_pdev *pdev, struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; pdev_priv_obj = reg_get_pdev_obj(pdev); if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { @@ -1858,7 +2082,9 @@ QDF_STATUS reg_enable_dfs_channels(struct wlan_objmgr_pdev *pdev, compute_pdev_current_chan_list(pdev_priv_obj); - return QDF_STATUS_SUCCESS; + status = send_scheduler_msg_sb(psoc, pdev); + + return status; } /** @@ -1883,7 +2109,6 @@ QDF_STATUS wlan_regulatory_pdev_obj_created_notification( uint32_t range_2g_low, range_2g_high, range_5g_low, range_5g_high; QDF_STATUS status; - enum channel_enum chan_enum; pdev_priv_obj = qdf_mem_malloc(sizeof(*pdev_priv_obj)); if (NULL == pdev_priv_obj) { @@ -1912,14 +2137,6 @@ QDF_STATUS wlan_regulatory_pdev_obj_created_notification( pdev_priv_obj->indoor_chan_enabled = psoc_priv_obj->indoor_chan_enabled; - qdf_mem_copy(pdev_priv_obj->cur_chan_list, - psoc_priv_obj->mas_chan_list, - NUM_CHANNELS * sizeof(struct regulatory_channel)); - - for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) - pdev_priv_obj->cur_chan_list[chan_enum].nol_chan = - psoc_priv_obj->nol_chan[chan_enum]; - reg_cap_ptr = parent_psoc->ext_service_param.reg_cap; for (cnt = 0; cnt < PSOC_MAX_PHY_REG_CAP; cnt++) { @@ -1953,6 +2170,11 @@ QDF_STATUS wlan_regulatory_pdev_obj_created_notification( compute_pdev_current_chan_list(pdev_priv_obj); + status = send_scheduler_msg_sb(parent_psoc, pdev); + + if (QDF_IS_STATUS_ERROR(status)) + return status; + status = wlan_objmgr_pdev_component_obj_attach(pdev, WLAN_UMAC_COMP_REGULATORY, pdev_priv_obj, @@ -2019,19 +2241,20 @@ QDF_STATUS reg_get_current_chan_list(struct wlan_objmgr_pdev *pdev, * * Return: None */ -void reg_update_nol_ch(struct wlan_objmgr_pdev *pdev, uint8_t *ch_list, - uint8_t num_ch, bool nol_ch) +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 wlan_regulatory_pdev_priv_obj *pdev_priv_obj; - struct regulatory_channel *reg_channels; - enum channel_state ch_state; - uint8_t i; + struct regulatory_channel *mas_chan_list; struct wlan_objmgr_psoc *psoc; struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; - uint32_t reg_ch_flags; + uint16_t i; + enum direction dir; + QDF_STATUS status; - if (!num_ch || !ch_list) { + if (!num_chan || !chan_list) { reg_err("chan_list or num_ch is NULL"); return; } @@ -2048,35 +2271,28 @@ void reg_update_nol_ch(struct wlan_objmgr_pdev *pdev, uint8_t *ch_list, return; } - 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; - } - - if (nol_ch || !pdev_priv_obj->dfs_enabled) { - ch_state = CHANNEL_STATE_DISABLE; - reg_ch_flags = REGULATORY_CHAN_DISABLED; - nol_ch = pdev_priv_obj->dfs_enabled; - } else { - ch_state = CHANNEL_STATE_DFS; - reg_ch_flags = REGULATORY_CHAN_RADAR; - } - - reg_channels = &pdev_priv_obj->cur_chan_list[0]; - for (i = 0; i < num_ch; i++) { - chan_enum = reg_get_chan_enum(ch_list[i]); + mas_chan_list = psoc_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 update nol request, ch %d", - ch_list[i]); + reg_err("Invalid ch in nol list, chan %d", + chan_list[i]); continue; } - reg_channels[chan_enum].state = ch_state; - reg_channels[chan_enum].nol_chan = nol_ch; - reg_channels[chan_enum].chan_flags |= reg_ch_flags; - psoc_priv_obj->nol_chan[chan_enum] = nol_ch; + mas_chan_list[chan_enum].nol_chan = nol_chan; } + + dir = SOUTHBOUND; + + status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID); + if (QDF_IS_STATUS_ERROR(status)) { + reg_err("error taking psoc ref cnt"); + return; + } + status = wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, + reg_propagate_mas_chan_list_to_pdev, + &dir, 1, WLAN_REGULATORY_SB_ID); + wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID); } static void reg_change_pdev_for_config(struct wlan_objmgr_psoc *psoc, @@ -2089,7 +2305,7 @@ static void reg_change_pdev_for_config(struct wlan_objmgr_psoc *psoc, wlan_psoc_obj_lock(psoc); psoc_priv_obj = (struct wlan_regulatory_psoc_priv_obj *) wlan_objmgr_psoc_get_comp_private_obj(psoc, - WLAN_UMAC_COMP_REGULATORY); + WLAN_UMAC_COMP_REGULATORY); wlan_psoc_obj_unlock(psoc); if (NULL == psoc_priv_obj) { @@ -2114,6 +2330,8 @@ static void reg_change_pdev_for_config(struct wlan_objmgr_psoc *psoc, pdev_priv_obj); compute_pdev_current_chan_list(pdev_priv_obj); + + send_scheduler_msg_sb(psoc, pdev); } QDF_STATUS reg_set_config_vars(struct wlan_objmgr_psoc *psoc, @@ -2145,9 +2363,15 @@ QDF_STATUS reg_set_config_vars(struct wlan_objmgr_psoc *psoc, config_vars.indoor_chan_enabled; psoc_priv_obj->band_capability = config_vars.band_capability; + status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID); + if (QDF_IS_STATUS_ERROR(status)) { + reg_err("error taking psoc ref cnt"); + return status; + } status = wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, reg_change_pdev_for_config, NULL, 1, WLAN_REGULATORY_SB_ID); + wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID); return status; } @@ -2187,6 +2411,7 @@ void reg_program_mas_chan_list(struct wlan_objmgr_psoc *psoc, struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; QDF_STATUS status; uint32_t count; + enum direction dir; wlan_psoc_obj_lock(psoc); psoc_priv_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, @@ -2199,7 +2424,7 @@ void reg_program_mas_chan_list(struct wlan_objmgr_psoc *psoc, } psoc_priv_obj->dfs_region = dfs_region; - qdf_mem_copy(psoc_priv_obj->default_country, alpha2, + qdf_mem_copy(psoc_priv_obj->current_country, alpha2, REG_ALPHA2_LEN); for (count = 0; count < NUM_CHANNELS; count++) { @@ -2207,16 +2432,107 @@ void reg_program_mas_chan_list(struct wlan_objmgr_psoc *psoc, channel_map[count].chan_num; reg_channels[count].center_freq = channel_map[count].center_freq; + reg_channels[count].nol_chan = false; } qdf_mem_copy(psoc_priv_obj->mas_chan_list, reg_channels, NUM_CHANNELS * sizeof(struct regulatory_channel)); - status = wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, - reg_propagate_mas_chan_list_to_pdev, - NULL, 1, WLAN_REGULATORY_SB_ID); + dir = SOUTHBOUND; + status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID); + if (QDF_IS_STATUS_ERROR(status)) { + reg_err("error taking psoc ref cnt"); + return; + } + status = wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, + reg_propagate_mas_chan_list_to_pdev, + &dir, 1, WLAN_REGULATORY_SB_ID); + wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID); +} + + +void reg_register_chan_change_callback(struct wlan_objmgr_psoc *psoc, + reg_chan_change_callback cbk, + void *arg) +{ + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + uint32_t count; + + + wlan_psoc_obj_lock(psoc); + psoc_priv_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_REGULATORY); + wlan_psoc_obj_unlock(psoc); + + if (NULL == psoc_priv_obj) { + reg_err("reg psoc private obj is NULL"); + return; + } + + qdf_spin_lock_bh(&psoc_priv_obj->cbk_list_lock); + for (count = 0; count < REG_MAX_CHAN_CHANGE_CBKS; count++) + if (psoc_priv_obj->cbk_list[count].cbk == NULL) { + psoc_priv_obj->cbk_list[count].cbk = cbk; + psoc_priv_obj->cbk_list[count].arg = arg; + psoc_priv_obj->num_chan_change_cbks++; + break; + } + qdf_spin_unlock_bh(&psoc_priv_obj->cbk_list_lock); + + if (count == REG_MAX_CHAN_CHANGE_CBKS) + reg_err("callback list is full, could not add the cbk"); +} + +void reg_unregister_chan_change_callback(struct wlan_objmgr_psoc *psoc, + reg_chan_change_callback cbk) +{ + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + uint32_t count; + + wlan_psoc_obj_lock(psoc); + psoc_priv_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_REGULATORY); + wlan_psoc_obj_unlock(psoc); + + if (NULL == psoc_priv_obj) { + reg_err("reg psoc private obj is NULL"); + return; + } + + qdf_spin_lock_bh(&psoc_priv_obj->cbk_list_lock); + for (count = 0; count < REG_MAX_CHAN_CHANGE_CBKS; count++) + if (psoc_priv_obj->cbk_list[count].cbk == cbk) { + psoc_priv_obj->cbk_list[count].cbk = NULL; + psoc_priv_obj->num_chan_change_cbks--; + break; + } + qdf_spin_unlock_bh(&psoc_priv_obj->cbk_list_lock); + + if (count == REG_MAX_CHAN_CHANGE_CBKS) + reg_err("callback not found in the list"); +} + +enum country_src reg_get_cc_and_src(struct wlan_objmgr_psoc *psoc, + uint8_t *alpha2) +{ + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + + wlan_psoc_obj_lock(psoc); + psoc_priv_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_REGULATORY); + wlan_psoc_obj_unlock(psoc); + + if (NULL == psoc_priv_obj) { + reg_err("reg psoc private obj is NULL"); + return false; + } + + qdf_mem_copy(alpha2, psoc_priv_obj->current_country, + REG_ALPHA2_LEN + 1); + + return psoc_priv_obj->cc_src; } QDF_STATUS reg_program_default_cc(struct wlan_objmgr_psoc *psoc, @@ -2244,7 +2560,7 @@ QDF_STATUS reg_program_default_cc(struct wlan_objmgr_psoc *psoc, (sizeof(struct cur_regulatory_info)); if (reg_info == NULL) { reg_err("reg info is NULL"); - return QDF_STATUS_E_FAILURE; + return QDF_STATUS_E_NOMEM; } reg_info->psoc = psoc; @@ -2322,7 +2638,7 @@ QDF_STATUS reg_program_chan_list(struct wlan_objmgr_psoc *psoc, (sizeof(struct cur_regulatory_info)); if (reg_info == NULL) { reg_err("reg info is NULL"); - return QDF_STATUS_E_FAILURE; + return QDF_STATUS_E_NOMEM; } reg_info->psoc = psoc; @@ -2360,6 +2676,7 @@ QDF_STATUS reg_program_chan_list(struct wlan_objmgr_psoc *psoc, 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); diff --git a/umac/regulatory/core/src/reg_services.h b/umac/regulatory/core/src/reg_services.h index 079808bbf6fb..8c3f4ad6e933 100644 --- a/umac/regulatory/core/src/reg_services.h +++ b/umac/regulatory/core/src/reg_services.h @@ -162,8 +162,8 @@ QDF_STATUS reg_set_default_country(struct wlan_objmgr_psoc *psoc, /** * reg_set_country() - Set the current regulatory country - * @pdev: The physical dev to set current country for - * @country: The country information to configure + * @pdev: pdev device for country information + * @country: country value * * Return: QDF_STATUS */ @@ -239,7 +239,7 @@ QDF_STATUS wlan_regulatory_pdev_obj_destroyed_notification( void *arg_list); static inline struct wlan_lmac_if_reg_tx_ops * -get_reg_psoc_tx_ops(struct wlan_objmgr_psoc *psoc) +reg_get_psoc_tx_ops(struct wlan_objmgr_psoc *psoc) { return &((psoc->soc_cb.tx_ops.reg_ops)); } @@ -298,5 +298,26 @@ QDF_STATUS reg_get_current_cc(struct wlan_objmgr_psoc *psoc, QDF_STATUS reg_get_curr_band(struct wlan_objmgr_pdev *pdev, enum band_info *band); +typedef void (*reg_chan_change_callback)(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev, + struct regulatory_channel + *chan_list, + void *arg); + +void reg_register_chan_change_callback(struct wlan_objmgr_psoc *psoc, + reg_chan_change_callback cbk, + void *arg); + +void reg_unregister_chan_change_callback(struct wlan_objmgr_psoc *psoc, + reg_chan_change_callback cbk); + + +struct chan_change_cbk_entry { + reg_chan_change_callback cbk; + void *arg; +}; + +enum country_src reg_get_cc_and_src(struct wlan_objmgr_psoc *psoc, + uint8_t *alpha2); #endif diff --git a/umac/regulatory/dispatcher/inc/reg_services_public_struct.h b/umac/regulatory/dispatcher/inc/reg_services_public_struct.h index 85f41bfad238..86f2f685aab1 100644 --- a/umac/regulatory/dispatcher/inc/reg_services_public_struct.h +++ b/umac/regulatory/dispatcher/inc/reg_services_public_struct.h @@ -29,6 +29,7 @@ #define REG_SBS_SEPARATION_THRESHOLD 100 #define REG_MAX_CHANNELS_PER_OPERATING_CLASS 25 #define REG_MAX_SUPP_OPER_CLASSES 32 +#define REG_MAX_CHAN_CHANGE_CBKS 30 /** * enum channel_enum - channel enumeration @@ -498,4 +499,24 @@ struct reg_freq_range { uint32_t high_freq; }; +/** + * struct reg_sched_payload + * @psoc: psoc ptr + * @pdev: pdev ptr + */ +struct reg_sched_payload { + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_pdev *pdev; +}; + +/** + * enum direction + * @NORTHBOUND: northbound + * @SOUTHBOUND: southbound + */ +enum direction { + NORTHBOUND, + SOUTHBOUND, +}; + #endif diff --git a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h index 6449301b8098..32bb754203ac 100644 --- a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h +++ b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h @@ -29,6 +29,7 @@ #include "../../core/src/reg_services.h" #include + #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 @@ -62,7 +63,6 @@ #define WLAN_REG_CHAN_TO_BAND(chan_num) reg_chan_to_band(chan_num) - /** * wlan_reg_get_channel_list_with_power() - Provide the channel list with power * @ch_list: pointer to the channel list. @@ -337,4 +337,27 @@ uint32_t wlan_reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, */ QDF_STATUS wlan_reg_set_country(struct wlan_objmgr_pdev *pdev, uint8_t *country); + +/** + * wlan_reg_register_chan_change_callback () - add chan change cbk + * @psoc: channel number + * @cbk: callback + * @arg: argument + * + * Return: true or false + */ +void wlan_reg_register_chan_change_callback(struct wlan_objmgr_psoc *psoc, + reg_chan_change_callback cbk, + void *arg); + +/** + * wlan_reg_unregister_chan_change_callback () - remove chan change cbk + * @psoc: channel number + * @cbk: callback + * + * Return: true or false + */ +void wlan_reg_unregister_chan_change_callback(struct wlan_objmgr_psoc *psoc, + reg_chan_change_callback cbk); + #endif diff --git a/umac/regulatory/dispatcher/inc/wlan_reg_ucfg_api.h b/umac/regulatory/dispatcher/inc/wlan_reg_ucfg_api.h index 0d49e543deab..89eac9e04be6 100644 --- a/umac/regulatory/dispatcher/inc/wlan_reg_ucfg_api.h +++ b/umac/regulatory/dispatcher/inc/wlan_reg_ucfg_api.h @@ -81,8 +81,8 @@ QDF_STATUS ucfg_reg_set_default_country(struct wlan_objmgr_psoc *psoc, * * Return: QDF_STATUS */ -QDF_STATUS ucfg_reg_set_country(struct wlan_objmgr_pdev *pdev, - uint8_t *country_code); +QDF_STATUS ucfg_reg_set_country(struct wlan_objmgr_pdev *dev, + uint8_t *country_code); /** * ucfg_reg_reset_country() - Reset the regulatory country to default @@ -167,4 +167,35 @@ void ucfg_reg_program_mas_chan_list(struct wlan_objmgr_psoc *psoc, uint8_t *alpha2, enum dfs_reg dfs_region); +/** + * ucfg_reg_register_chan_change_callback () - add chan change cbk + * @psoc: psoc ptr + * @cbk: callback + * @arg: argument + * + * Return: void + */ +void ucfg_reg_register_chan_change_callback(struct wlan_objmgr_psoc *psoc, + reg_chan_change_callback cbk, + void *arg); + +/** + * ucfg_reg_unregister_chan_change_callback () - remove chan change cbk + * @psoc: psoc ptr + * @cbk: callback + * + * Return: void + */ +void ucfg_reg_unregister_chan_change_callback(struct wlan_objmgr_psoc *psoc, + reg_chan_change_callback cbk); + +/** + * ucfg_reg_get_cc_and_src () - get country code and src + * @psoc: psoc ptr + * @alpha2: country code alpha2 + * + * Return: void + */ +enum country_src ucfg_reg_get_cc_and_src(struct wlan_objmgr_psoc *psoc, + uint8_t *alpha2); #endif diff --git a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c index ea00875fbf69..2e685a8e9e70 100644 --- a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c +++ b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c @@ -334,7 +334,7 @@ QDF_STATUS regulatory_psoc_open(struct wlan_objmgr_psoc *psoc) { struct wlan_lmac_if_reg_tx_ops *tx_ops; - tx_ops = get_reg_psoc_tx_ops(psoc); + tx_ops = reg_get_psoc_tx_ops(psoc); if (tx_ops->register_master_handler) tx_ops->register_master_handler(psoc, NULL); @@ -345,7 +345,7 @@ QDF_STATUS regulatory_psoc_close(struct wlan_objmgr_psoc *psoc) { struct wlan_lmac_if_reg_tx_ops *tx_ops; - tx_ops = get_reg_psoc_tx_ops(psoc); + tx_ops = reg_get_psoc_tx_ops(psoc); if (tx_ops->unregister_master_handler) tx_ops->unregister_master_handler(psoc, NULL); @@ -393,3 +393,19 @@ QDF_STATUS wlan_reg_set_country(struct wlan_objmgr_pdev *pdev, { return reg_set_country(pdev, country); } + +void wlan_reg_register_chan_change_callback(struct wlan_objmgr_psoc *psoc, + reg_chan_change_callback cbk, + void *arg) +{ + reg_register_chan_change_callback(psoc, cbk, arg); + +} + +void wlan_reg_unregister_chan_change_callback(struct wlan_objmgr_psoc *psoc, + reg_chan_change_callback cbk) +{ + reg_unregister_chan_change_callback(psoc, cbk); + +} + diff --git a/umac/regulatory/dispatcher/src/wlan_reg_ucfg_api.c b/umac/regulatory/dispatcher/src/wlan_reg_ucfg_api.c index 6e1f967ac42b..f175febae003 100644 --- a/umac/regulatory/dispatcher/src/wlan_reg_ucfg_api.c +++ b/umac/regulatory/dispatcher/src/wlan_reg_ucfg_api.c @@ -151,7 +151,7 @@ QDF_STATUS ucfg_reg_set_default_country(struct wlan_objmgr_psoc *psoc, * Return: QDF_STATUS */ QDF_STATUS ucfg_reg_set_country(struct wlan_objmgr_pdev *pdev, - uint8_t *country) + uint8_t *country) { return reg_set_country(pdev, country); } @@ -185,3 +185,22 @@ QDF_STATUS ucfg_reg_get_curr_band(struct wlan_objmgr_pdev *pdev, return reg_get_curr_band(pdev, band); } + +void ucfg_reg_register_chan_change_callback(struct wlan_objmgr_psoc *psoc, + reg_chan_change_callback cbk, + void *arg) +{ + reg_register_chan_change_callback(psoc, cbk, arg); +} + +void ucfg_reg_unregister_chan_change_callback(struct wlan_objmgr_psoc *psoc, + reg_chan_change_callback cbk) +{ + reg_unregister_chan_change_callback(psoc, cbk); +} + +enum country_src ucfg_reg_get_cc_and_src(struct wlan_objmgr_psoc *psoc, + uint8_t *alpha2) +{ + return reg_get_cc_and_src(psoc, alpha2); +} diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 2d940af265d7..1ecbb96bc225 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -17309,6 +17309,27 @@ static QDF_STATUS extract_reg_chan_list_update_event_tlv( reg_info->dfs_region = chan_list_event_hdr->dfs_region; reg_info->phybitmap = chan_list_event_hdr->phybitmap; reg_info->offload_enabled = true; + reg_info->num_phy = chan_list_event_hdr->num_phy; + reg_info->ctry_code = chan_list_event_hdr->country_id; + reg_info->reg_dmn_pair = chan_list_event_hdr->domain_code; + if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_STATUS_PASS) + reg_info->status_code = REG_SET_CC_STATUS_PASS; + else if (chan_list_event_hdr->status_code == + WMI_REG_CURRENT_ALPHA2_NOT_FOUND) + reg_info->status_code = REG_CURRENT_ALPHA2_NOT_FOUND; + else if (chan_list_event_hdr->status_code == + WMI_REG_INIT_ALPHA2_NOT_FOUND) + reg_info->status_code = REG_INIT_ALPHA2_NOT_FOUND; + else if (chan_list_event_hdr->status_code == + WMI_REG_SET_CC_CHANGE_NOT_ALLOWED) + reg_info->status_code = REG_SET_CC_CHANGE_NOT_ALLOWED; + else if (chan_list_event_hdr->status_code == + WMI_REG_SET_CC_STATUS_NO_MEMORY) + reg_info->status_code = REG_SET_CC_STATUS_NO_MEMORY; + else if (chan_list_event_hdr->status_code == + WMI_REG_SET_CC_STATUS_FAIL) + reg_info->status_code = REG_SET_CC_STATUS_FAIL; + reg_info->min_bw_2g = chan_list_event_hdr->min_bw_2g; reg_info->max_bw_2g = chan_list_event_hdr->max_bw_2g; reg_info->min_bw_5g = chan_list_event_hdr->min_bw_5g;