diff --git a/umac/dfs/core/src/dfs.h b/umac/dfs/core/src/dfs.h index de4ce095db4a..21bd980f49f3 100644 --- a/umac/dfs/core/src/dfs.h +++ b/umac/dfs/core/src/dfs.h @@ -1003,6 +1003,7 @@ struct dfs_event_log { * @dfs_spoof_test_done: Indicates if the sppof test is done. * @dfs_status_timeout_override: Used to change the timeout value of * dfs_host_wait_timer. + * @dfs_is_stadfs_enabled: Is STADFS enabled. * @dfs_min_sidx: Minimum sidx of the received radar pulses. * @dfs_max_sidx: Maximum sidx of the received radar pulses. * @dfs_seg_id: Segment ID of the radar hit channel. @@ -1140,6 +1141,7 @@ struct wlan_dfs { struct dfs_channel dfs_radar_found_chan; int dfs_status_timeout_override; #endif + bool dfs_is_stadfs_enabled; uint32_t dfs_min_sidx; uint32_t dfs_max_sidx; uint8_t dfs_seg_id; diff --git a/umac/dfs/core/src/misc/dfs_nol.c b/umac/dfs/core/src/misc/dfs_nol.c index b8502a40d8fd..4f24f3f808cc 100644 --- a/umac/dfs/core/src/misc/dfs_nol.c +++ b/umac/dfs/core/src/misc/dfs_nol.c @@ -292,34 +292,35 @@ void dfs_print_nol(struct wlan_dfs *dfs) void dfs_print_nolhistory(struct wlan_dfs *dfs) { - struct dfs_channel *c, lc; - int i, j = 0; - int nchans = 0; + struct dfs_channel *chan_list; + int i, j; + int nchans; if (!dfs) { dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); return; } - c = &lc; + nchans = dfs_get_num_chans(); - dfs_mlme_get_dfs_ch_nchans(dfs->dfs_pdev_obj, &nchans); - for (i = 0; i < nchans; i++) { - dfs_mlme_get_dfs_ch_channels(dfs->dfs_pdev_obj, - &(c->dfs_ch_freq), - &(c->dfs_ch_flags), - &(c->dfs_ch_flagext), - &(c->dfs_ch_ieee), - &(c->dfs_ch_vhtop_ch_freq_seg1), - &(c->dfs_ch_vhtop_ch_freq_seg2), - i); - if (WLAN_IS_CHAN_HISTORY_RADAR(c)) { - dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, - "nolhistory:%d channel=%d MHz Flags=%llx", - j, c->dfs_ch_freq, c->dfs_ch_flags); - j++; - } + chan_list = qdf_mem_malloc(nchans * sizeof(*chan_list)); + if (!chan_list) + return; + + utils_dfs_get_nol_history_chan_list(dfs->dfs_pdev_obj, + (void *)chan_list, &nchans); + if (!nchans) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "zero chans"); + qdf_mem_free(chan_list); + return; } + + for (i = 0, j = 0; i < nchans; i++, j++) + dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, + "nolhistory = %d channel = %d MHz", + j, chan_list[i].dfs_ch_freq); + + qdf_mem_free(chan_list); } void dfs_get_nol(struct wlan_dfs *dfs, @@ -592,24 +593,36 @@ void dfs_getnol(struct wlan_dfs *dfs, void *dfs_nolinfo) void dfs_clear_nolhistory(struct wlan_dfs *dfs) { - /* We should have a dfs_clear_nolhistory API from Regdomain. */ - struct dfs_channel *c, lc; - int i; + struct dfs_channel *chan_list; int nchans = 0; + bool sta_opmode; - c = &lc; - dfs_mlme_get_dfs_ch_nchans(dfs->dfs_pdev_obj, &nchans); - for (i = 0; i < nchans; i++) { - dfs_mlme_get_dfs_ch_channels(dfs->dfs_pdev_obj, - &(c->dfs_ch_freq), - &(c->dfs_ch_flags), - &(c->dfs_ch_flagext), - &(c->dfs_ch_ieee), - &(c->dfs_ch_vhtop_ch_freq_seg1), - &(c->dfs_ch_vhtop_ch_freq_seg2), - i); - WLAN_CHAN_CLR_HISTORY_RADAR(c); + if (!dfs->dfs_is_stadfs_enabled) + return; + + sta_opmode = dfs_mlme_is_opmode_sta(dfs->dfs_pdev_obj); + if (!sta_opmode) + return; + + nchans = dfs_get_num_chans(); + + chan_list = qdf_mem_malloc(nchans * sizeof(*chan_list)); + if (!chan_list) + return; + + utils_dfs_get_nol_history_chan_list(dfs->dfs_pdev_obj, + (void *)chan_list, &nchans); + if (!nchans) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "zero chans"); + qdf_mem_free(chan_list); + return; } + + utils_dfs_reg_update_nol_history_ch(dfs->dfs_pdev_obj, + (void *)chan_list, nchans, + DFS_NOL_HISTORY_RESET); + + qdf_mem_free(chan_list); } #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) diff --git a/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c b/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c index 5933b198e95a..3b1c4980cc8a 100644 --- a/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c +++ b/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c @@ -170,6 +170,13 @@ static QDF_STATUS dfs_radar_add_channel_list_to_nol(struct wlan_dfs *dfs, utils_dfs_reg_update_nol_ch(dfs->dfs_pdev_obj, nollist, num_ch, DFS_NOL_SET); + + if (dfs->dfs_is_stadfs_enabled) + if (dfs_mlme_is_opmode_sta(dfs->dfs_pdev_obj)) + utils_dfs_reg_update_nol_history_ch( + dfs->dfs_pdev_obj, nollist, num_ch, + DFS_NOL_HISTORY_SET); + dfs_nol_update(dfs); utils_dfs_save_nol(dfs->dfs_pdev_obj); diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h index 73b5f9baad13..dab1edda5d17 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h @@ -281,4 +281,12 @@ void dfs_mlme_handle_dfs_scan_violation(struct wlan_objmgr_pdev *pdev) { } #endif + +/** + * dfs_mlme_is_opmode_sta() - Check if pdev opmode is STA. + * @pdev: Pointer to DFS pdev object. + * + * Return: true if pdev opmode is STA, else false. + */ +bool dfs_mlme_is_opmode_sta(struct wlan_objmgr_pdev *pdev); #endif /* _WLAN_DFS_MLME_API_H_ */ diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h index aac43dd84fa8..4931e4961b9d 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h @@ -395,6 +395,21 @@ QDF_STATUS tgt_dfs_reset_spoof_test(struct wlan_objmgr_pdev *pdev) } #endif +/** + * tgt_dfs_enable_stadfs() - Enable/Disable STADFS capability. + * @pdev: Pointer to DFS pdev object. + * @val: input value. + */ +void tgt_dfs_enable_stadfs(struct wlan_objmgr_pdev *pdev, bool val); + +/** + * tgt_dfs_is_stadfs_enabled() - Get STADFS capability + * @pdev: Pointer to DFS pdev object. + * + * Return: true if STADFS is enabled, else false. + */ +bool tgt_dfs_is_stadfs_enabled(struct wlan_objmgr_pdev *pdev); + /** * tgt_dfs_is_pdev_5ghz() - Check if the input pdev is 5GHZ. * @pdev: Pointer to DFS pdev object. diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h index 69e8a19ebf30..2314fcd2efaa 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h @@ -52,6 +52,7 @@ * Channel Switch Announcement. * @mlme_nol_timeout_notification: NOL timeout notification. * @mlme_clist_update: Updates the channel list. + * @mlme_is_opmode_sta: Check if pdev opmode is STA. * @mlme_get_cac_timeout: Gets the CAC timeout. * @mlme_rebuild_chan_list_with_non_dfs_channel: Rebuild channels with non-dfs * channels. @@ -132,6 +133,7 @@ struct dfs_to_mlme { QDF_STATUS (*mlme_clist_update)(struct wlan_objmgr_pdev *pdev, void *nollist, int nentries); + bool (*mlme_is_opmode_sta)(struct wlan_objmgr_pdev *pdev); QDF_STATUS (*mlme_get_cac_timeout)(struct wlan_objmgr_pdev *pdev, uint16_t dfs_ch_freq, uint8_t c_vhtop_ch_freq_seg2, diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h index fe53d9d0b033..b24eb07426ce 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h @@ -34,6 +34,12 @@ /* Remove channel from nol */ #define DFS_NOL_RESET 0 +/* Mark nol-history flag for the channel */ +#define DFS_NOL_HISTORY_SET 1 + +/* Clear nol-history flag from the channel */ +#define DFS_NOL_HISTORY_RESET 0 + /* Max nol channels */ #define DFS_MAX_NOL_CHANNEL 80 @@ -560,6 +566,31 @@ void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, void *clist, uint32_t *num_chan); +/** + * utils_dfs_get_nol_history_chan_list() - Get nol_history channels from regdb + * component. + * @pdev: Pointer to pdev structure. + * @clist: Pointer to channel list. + * @num_chan: number of channels. + */ +void utils_dfs_get_nol_history_chan_list(struct wlan_objmgr_pdev *pdev, + void *clist, uint32_t *num_chan); + +/** + * utils_dfs_reg_update_nol_history_ch() - set nol history channel + * + * @pdev: pdev ptr + * @ch_list: channel list to be returned + * @num_ch: number of channels + * @nol_history_ch: nol history flag + * + * Return: void + */ +void utils_dfs_reg_update_nol_history_ch(struct wlan_objmgr_pdev *pdev, + uint8_t *ch_list, + uint8_t num_ch, + bool nol_history_ch); + /** * utils_dfs_check_for_cac_start() - Check for DFS CAC start conditions. * @pdev: pdev ptr diff --git a/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c b/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c index ded8ad941122..f5594ad14571 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c @@ -102,6 +102,8 @@ void register_dfs_callbacks(void) mlme_dfs_rebuild_chan_list_with_non_dfs_channels; tmp_dfs_to_mlme->mlme_restart_vaps_with_non_dfs_chan = mlme_dfs_restart_vaps_with_non_dfs_chan; + tmp_dfs_to_mlme->mlme_is_opmode_sta = + mlme_dfs_is_opmode_sta; tmp_dfs_to_mlme->mlme_check_allowed_prim_chanlist = mlme_dfs_check_allowed_prim_chanlist; tmp_dfs_to_mlme->mlme_update_scan_channel_list = diff --git a/umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c b/umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c index 801d12f6dd82..94b5b96d073c 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c @@ -338,3 +338,11 @@ void dfs_mlme_handle_dfs_scan_violation(struct wlan_objmgr_pdev *pdev) global_dfs_to_mlme.mlme_update_scan_channel_list(pdev); } #endif + +bool dfs_mlme_is_opmode_sta(struct wlan_objmgr_pdev *pdev) +{ + if (!global_dfs_to_mlme.mlme_is_opmode_sta) + return false; + + return global_dfs_to_mlme.mlme_is_opmode_sta(pdev); +} diff --git a/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c b/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c index a4cc0ea264b6..ecee93d23b91 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c @@ -610,3 +610,29 @@ QDF_STATUS tgt_dfs_send_usenol_pdev_param(struct wlan_objmgr_pdev *pdev, qdf_export_symbol(tgt_dfs_send_usenol_pdev_param); #endif + +void tgt_dfs_enable_stadfs(struct wlan_objmgr_pdev *pdev, bool val) +{ + struct wlan_dfs *dfs; + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + dfs->dfs_is_stadfs_enabled = val; +} + +bool tgt_dfs_is_stadfs_enabled(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_dfs *dfs; + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return false; + } + + return dfs->dfs_is_stadfs_enabled; +} diff --git a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c index f7ae9b97b245..1328ac36ec7c 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c @@ -429,6 +429,43 @@ static void utils_dfs_get_max_sup_width(struct wlan_objmgr_pdev *pdev, } #ifndef QCA_DFS_USE_POLICY_MANAGER +void utils_dfs_get_nol_history_chan_list(struct wlan_objmgr_pdev *pdev, + void *clist, uint32_t *num_chan) +{ + int i, j = 0; + struct regulatory_channel *cur_chan_list; + struct wlan_dfs *dfs; + struct dfs_channel *chan_list = (struct dfs_channel *)clist; + + *num_chan = 0; + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) + return; + + cur_chan_list = qdf_mem_malloc(NUM_CHANNELS * sizeof(*cur_chan_list)); + if (!cur_chan_list) + return; + + if (wlan_reg_get_current_chan_list( + pdev, cur_chan_list) != QDF_STATUS_SUCCESS) { + dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, + "failed to get cur_chan list"); + qdf_mem_free(cur_chan_list); + return; + } + + for (i = 0; i < NUM_CHANNELS; i++) { + if (cur_chan_list[i].nol_history) { + chan_list[j].dfs_ch_freq = cur_chan_list[i].center_freq; + j++; + } + } + + *num_chan = j; + qdf_mem_free(cur_chan_list); +} + void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, void *clist, uint32_t *num_chan) { @@ -467,6 +504,10 @@ void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, if (state == CHANNEL_STATE_DFS) chan_list[j].dfs_ch_flagext = WLAN_CHAN_DFS; + + if (cur_chan_list[i].nol_history) + chan_list[j].dfs_ch_flagext |= + WLAN_CHAN_HISTORY_RADAR; j++; } } @@ -477,19 +518,20 @@ void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, } /** - * utils_dfs_get_channel_list() - Get channel list from regdb component based + * utils_dfs_get_channel_list() - Get channel list from regdb component, based * on current channel list. * @pdev: Pointer to pdev structure. - * @chan_list: Pointer to regdb channel list. + * @chan: Pointer to channel list. * @num_chan: number of channels. * * Get regdb channel list based on dfs current channel. - * ex: When AP is operating in 5GHz channel, filter 2.4GHz and 4.9GHZ channels + * Ex: When AP is operating in 5GHz channel, filter 2.4GHz and 4.9GHZ channels * so that the random channel function does not select either 2.4GHz or 4.9GHz * channel. */ static void utils_dfs_get_channel_list(struct wlan_objmgr_pdev *pdev, - struct dfs_channel *chan_list, uint32_t *num_chan) + struct dfs_channel *chan_list, + uint32_t *num_chan) { struct dfs_channel *tmp_chan_list = NULL; struct wlan_dfs *dfs; @@ -554,6 +596,12 @@ static void utils_dfs_get_channel_list(struct wlan_objmgr_pdev *pdev, #else +void utils_dfs_get_nol_history_chan_list(struct wlan_objmgr_pdev *pdev, + void *clist, uint32_t *num_chan) +{ + utils_dfs_get_chan_list(pdev, clist, num_chan); +} + void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, void *clist, uint32_t *num_chan) { @@ -601,15 +649,9 @@ void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, "num channels %d", i); } -/** - * utils_dfs_get_channel_list() - Wrapper function to get channel list from - * regdb component. - * @pdev: Pointer to pdev structure. - * @chan_list: Pointer to regdb channel list. - * @num_chan: number of channels. - */ static void utils_dfs_get_channel_list(struct wlan_objmgr_pdev *pdev, - struct dfs_channel *chan_list, uint32_t *num_chan) + struct dfs_channel *chan_list, + uint32_t *num_chan) { utils_dfs_get_chan_list(pdev, (void *)chan_list, num_chan); } @@ -886,6 +928,14 @@ void utils_dfs_reg_update_nol_ch(struct wlan_objmgr_pdev *pdev, } qdf_export_symbol(utils_dfs_reg_update_nol_ch); +void utils_dfs_reg_update_nol_history_ch(struct wlan_objmgr_pdev *pdev, + uint8_t *ch_list, + uint8_t num_ch, + bool nol_history_ch) +{ + wlan_reg_update_nol_history_ch(pdev, ch_list, num_ch, nol_history_ch); +} + uint8_t utils_dfs_freq_to_chan(uint32_t freq) { uint8_t chan;