From 90ae139bc4c25b2e2b812fd1e20fefd04c1d0020 Mon Sep 17 00:00:00 2001 From: Amar Singhal Date: Fri, 12 May 2017 16:39:23 -0700 Subject: [PATCH] qcacmn: Add callback for dynamic changes to current channel list For dynamic master channel list, compute per pdev current channel list as well. Provide API for user to register callback to be called whenever current channel list for a pdev changes. CRs-Fixed: 2012415 Change-Id: Ie86a719306178a1c3579c2b534a52a12ec3e0b1d --- umac/regulatory/core/src/reg_priv.h | 6 + umac/regulatory/core/src/reg_services.c | 679 +++++++++++++----- umac/regulatory/core/src/reg_services.h | 27 +- .../inc/reg_services_public_struct.h | 21 + .../dispatcher/inc/wlan_reg_services_api.h | 25 +- .../dispatcher/inc/wlan_reg_ucfg_api.h | 35 +- .../dispatcher/src/wlan_reg_services_api.c | 20 +- .../dispatcher/src/wlan_reg_ucfg_api.c | 21 +- wmi/src/wmi_unified_tlv.c | 21 + 9 files changed, 665 insertions(+), 190 deletions(-) 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;