diff --git a/umac/dfs/core/src/dfs.h b/umac/dfs/core/src/dfs.h index a448d4dc5684..6381792901f6 100644 --- a/umac/dfs/core/src/dfs.h +++ b/umac/dfs/core/src/dfs.h @@ -1983,19 +1983,6 @@ void dfs_cancel_cac_timer(struct wlan_dfs *dfs); */ void dfs_start_cac_timer(struct wlan_dfs *dfs); -/** - * dfs_is_subset_channel() - Check if the new_chan is subset of the old_chan. - * @dfs: Pointer to wlan_dfs structure. - * @old_chan: Pointer to old channel. - * @new_chan: Pointer to new channel. - * - * Return: true if the new channel is subset of or same as the old channel, - * else false. - */ -bool dfs_is_subset_channel(struct wlan_dfs *dfs, - struct dfs_channel *old_chan, - struct dfs_channel *new_chan); - /** * dfs_is_curchan_subset_of_cac_started_chan() - Check if the dfs current * channel is subset of cac started channel. @@ -2010,12 +1997,6 @@ bool dfs_is_subset_channel(struct wlan_dfs *dfs, */ bool dfs_is_curchan_subset_of_cac_started_chan(struct wlan_dfs *dfs); -/** - * dfs_clear_cac_started_chan() - Clear dfs cac started channel. - * @dfs: Pointer to wlan_dfs structure. - */ -void dfs_clear_cac_started_chan(struct wlan_dfs *dfs); - /** * dfs_set_update_nol_flag() - Sets update_nol flag. * @dfs: Pointer to wlan_dfs structure. @@ -2591,16 +2572,20 @@ bool dfs_process_nol_ie_bitmap(struct wlan_dfs *dfs, uint8_t nol_ie_bandwidth, uint8_t nol_ie_bitmap); /** - * dfs_check_for_cac_start() - Check for DFS CAC start conditions. + * dfs_is_cac_required() - Check if DFS CAC is required for the current channel. * @dfs: Pointer to wlan_dfs structure. + * @cur_chan: Pointer to current channel of dfs_channel structure. + * @prev_chan: Pointer to previous channel of dfs_channel structure. * @continue_current_cac: If AP can start CAC then this variable indicates * whether to continue with the current CAC or restart the CAC. This variable * is valid only if this function returns true. * - * Return: true if AP can start or continue the current CAC, else false. + * Return: true if AP requires CAC or can continue current CAC, else false. */ -bool dfs_check_for_cac_start(struct wlan_dfs *dfs, - bool *continue_current_cac); +bool dfs_is_cac_required(struct wlan_dfs *dfs, + struct dfs_channel *cur_chan, + struct dfs_channel *prev_chan, + bool *continue_current_cac); /** * dfs_task_testtimer_reset() - stop dfs test timer. @@ -2672,11 +2657,20 @@ int dfs_reinit_timers(struct wlan_dfs *dfs); * dfs_skip_cac_after_vdev_restart() - Skip CAC if new channel is same * as old channel after vdev restart. * @dfs: Pointer to wlan_dfs structure. + * @cur_chan: Pointer to current channel of the pdev. + * @prev_chan: Pointer to previous channel of the pdev. + * + * Return: False if CAC can be skipped, else true. */ #ifdef QCA_SKIP_CAC_AFTER_RESTART -bool dfs_skip_cac_after_vdev_restart(struct wlan_dfs *dfs); +bool dfs_skip_cac_after_vdev_restart(struct wlan_dfs *dfs, + struct dfs_channel *cur_chan, + struct dfs_channel *prev_chan); #else -static inline bool dfs_skip_cac_after_vdev_restart(struct wlan_dfs *dfs) +static inline bool +dfs_skip_cac_after_vdev_restart(struct wlan_dfs *dfs, + struct dfs_channel *cur_chan, + struct dfs_channel *prev_chan) { return true; } diff --git a/umac/dfs/core/src/misc/dfs_cac.c b/umac/dfs/core/src/misc/dfs_cac.c index 0a1423067455..6417aab6588a 100644 --- a/umac/dfs/core/src/misc/dfs_cac.c +++ b/umac/dfs/core/src/misc/dfs_cac.c @@ -94,6 +94,16 @@ static os_timer_func(dfs_cac_valid_timeout) dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, ": Timed out!!"); } +/** + * dfs_clear_cac_started_chan() - Clear dfs cac started channel. + * @dfs: Pointer to wlan_dfs structure. + */ +static void dfs_clear_cac_started_chan(struct wlan_dfs *dfs) +{ + qdf_mem_zero(&dfs->dfs_cac_started_chan, + sizeof(dfs->dfs_cac_started_chan)); +} + /** * dfs_cac_timeout() - DFS cactimeout function. * @@ -156,6 +166,7 @@ static os_timer_func(dfs_cac_timeout) secondary_chan_ieee, ch_width); } + dfs_clear_cac_started_chan(dfs); /* Iterate over the nodes, processing the CAC completion event. */ dfs_mlme_proc_cac(dfs->dfs_pdev_obj, 0); @@ -190,9 +201,7 @@ void dfs_cac_timer_reset(struct wlan_dfs *dfs) qdf_timer_stop(&dfs->dfs_cac_timer); dfs_get_override_cac_timeout(dfs, &(dfs->dfs_cac_timeout_override)); - qdf_mem_zero(&dfs->dfs_cac_started_chan, - sizeof(dfs->dfs_cac_started_chan)); - + dfs_clear_cac_started_chan(dfs); } void dfs_cac_timer_detach(struct wlan_dfs *dfs) @@ -233,6 +242,7 @@ void dfs_start_cac_timer(struct wlan_dfs *dfs) void dfs_cancel_cac_timer(struct wlan_dfs *dfs) { qdf_timer_stop(&dfs->dfs_cac_timer); + dfs_clear_cac_started_chan(dfs); } void dfs_cac_stop(struct wlan_dfs *dfs) @@ -246,6 +256,7 @@ void dfs_cac_stop(struct wlan_dfs *dfs) qdf_timer_stop(&dfs->dfs_cac_timer); if (dfs->dfs_cac_timer_running) dfs->dfs_cac_aborted = 1; + dfs_clear_cac_started_chan(dfs); dfs->dfs_cac_timer_running = 0; } @@ -257,51 +268,20 @@ void dfs_stacac_stop(struct wlan_dfs *dfs) dfs_debug(dfs, WLAN_DEBUG_DFS, "Stopping STA CAC Timer %d procphyerr 0x%08x", dfs->dfs_curchan->dfs_ch_freq, phyerr); + dfs_clear_cac_started_chan(dfs); } -bool dfs_is_subset_channel(struct wlan_dfs *dfs, - struct dfs_channel *old_chan, - struct dfs_channel *new_chan) +static bool +dfs_is_subset_channel(uint8_t *old_subchans, + uint8_t old_n_chans, + uint8_t *new_subchans, + uint8_t new_n_chans) { - uint8_t old_subchans[NUM_CHANNELS_160MHZ]; - uint8_t new_subchans[NUM_CHANNELS_160MHZ]; - uint8_t old_n_chans; - uint8_t new_n_chans; - int i = 0, j = 0; - bool is_found = false; + bool is_found; + int i, j; - if (WLAN_IS_CHAN_11AC_VHT160(old_chan) || - WLAN_IS_CHAN_11AC_VHT80_80(old_chan)) { - /* If primary segment is NON-DFS */ - if (!WLAN_IS_CHAN_DFS(old_chan)) - old_n_chans = dfs_get_bonding_channels(dfs, - old_chan, - SEG_ID_SECONDARY, - DETECTOR_ID_0, - old_subchans); - else - old_n_chans = dfs_get_bonding_channels_without_seg_info( - old_chan, old_subchans); - } else { - old_n_chans = dfs_get_bonding_channels_without_seg_info( - old_chan, old_subchans); - } - - if (WLAN_IS_CHAN_11AC_VHT160(new_chan) || - WLAN_IS_CHAN_11AC_VHT80_80(new_chan)) { - /* If primary segment is NON-DFS */ - if (WLAN_IS_CHAN_DFS(new_chan)) - new_n_chans = dfs_get_bonding_channels( - dfs, new_chan, SEG_ID_SECONDARY, - DETECTOR_ID_0, - new_subchans); - else - new_n_chans = dfs_get_bonding_channels_without_seg_info( - new_chan, new_subchans); - } else { - new_n_chans = dfs_get_bonding_channels_without_seg_info( - new_chan, new_subchans); - } + if (!new_n_chans) + return true; if (new_n_chans > old_n_chans) return false; @@ -325,22 +305,79 @@ bool dfs_is_subset_channel(struct wlan_dfs *dfs, return is_found; } -bool dfs_is_curchan_subset_of_cac_started_chan(struct wlan_dfs *dfs) +static uint8_t +dfs_find_dfs_sub_channels(struct wlan_dfs *dfs, + struct dfs_channel *channel, + uint8_t *subchan_arr) { - return dfs_is_subset_channel(dfs, &dfs->dfs_cac_started_chan, - dfs->dfs_curchan); + if (WLAN_IS_CHAN_MODE_160(channel) || + WLAN_IS_CHAN_MODE_80_80(channel)) { + if (WLAN_IS_CHAN_DFS(channel) && + WLAN_IS_CHAN_DFS_CFREQ2(channel)) + return + dfs_get_bonding_channels_without_seg_info(channel, + subchan_arr); + if (WLAN_IS_CHAN_DFS(channel)) + return dfs_get_bonding_channels(dfs, + channel, + SEG_ID_PRIMARY, + DETECTOR_ID_0, + subchan_arr); + if (WLAN_IS_CHAN_DFS_CFREQ2(channel)) + return dfs_get_bonding_channels(dfs, + channel, + SEG_ID_SECONDARY, + DETECTOR_ID_0, + subchan_arr); + /* All channels in 160/80_80 BW are non DFS, return 0 + * as number of subchannels + */ + return 0; + } else if (WLAN_IS_CHAN_DFS(channel)) { + return dfs_get_bonding_channels_without_seg_info(channel, + subchan_arr); + } + /* All channels are non DFS, return 0 as number of subchannels*/ + return 0; } -void dfs_clear_cac_started_chan(struct wlan_dfs *dfs) +/* dfs_is_new_chan_subset_of_old_chan() - Find if new channel is subset of + * old channel. + * @dfs: Pointer to wlan_dfs structure. + * @new_chan: Pointer to new channel of dfs_channel structure. + * @old_chan: Pointer to old channel of dfs_channel structure. + * + * Return: True if new channel is subset of old channel, else false. + */ +static bool +dfs_is_new_chan_subset_of_old_chan(struct wlan_dfs *dfs, + struct dfs_channel *new_chan, + struct dfs_channel *old_chan) { - qdf_mem_zero(&dfs->dfs_cac_started_chan, - sizeof(dfs->dfs_cac_started_chan)); + uint8_t new_subchans[NUM_CHANNELS_160MHZ]; + uint8_t old_subchans[NUM_CHANNELS_160MHZ]; + uint8_t n_new_subchans = 0; + uint8_t n_old_subchans = 0; + + /* Given channel is the old channel. i.e. The channel which + * should have the new channel as subset. + */ + n_old_subchans = dfs_find_dfs_sub_channels(dfs, old_chan, old_subchans); + /* cur_chan is the new channel to be check if subset of old channel */ + n_new_subchans = dfs_find_dfs_sub_channels(dfs, new_chan, new_subchans); + + return dfs_is_subset_channel(old_subchans, + n_old_subchans, + new_subchans, + n_new_subchans); } #ifdef QCA_SKIP_CAC_AFTER_RESTART -bool dfs_skip_cac_after_vdev_restart(struct wlan_dfs *dfs) +bool dfs_skip_cac_after_vdev_restart(struct wlan_dfs *dfs, + struct dfs_channel *cur_chan, + struct dfs_channel *prev_chan) { - if (dfs_is_curchan_subset_of_cac_started_chan(dfs)) { + if (dfs_is_new_chan_subset_of_old_chan(dfs, cur_chan, prev_chan)) { /* AP bandwidth reduce case: * When AP detects the RADAR in in-service monitoring * mode in channel A, it cancels the running CAC and @@ -354,14 +391,17 @@ bool dfs_skip_cac_after_vdev_restart(struct wlan_dfs *dfs) return false; } } - return true; } #endif -bool dfs_check_for_cac_start(struct wlan_dfs *dfs, - bool *continue_current_cac) +bool dfs_is_cac_required(struct wlan_dfs *dfs, + struct dfs_channel *cur_chan, + struct dfs_channel *prev_chan, + bool *continue_current_cac) { + struct dfs_channel *cac_started_chan = &dfs->dfs_cac_started_chan; + if (dfs->dfs_ignore_dfs || dfs->dfs_cac_valid || dfs->dfs_ignore_cac) { dfs_debug(dfs, WLAN_DEBUG_DFS, "Skip CAC, ignore_dfs = %d cac_valid = %d ignore_cac = %d", @@ -378,10 +418,10 @@ bool dfs_check_for_cac_start(struct wlan_dfs *dfs, } /* If the channel has completed PRE-CAC then CAC can be skipped here. */ - if (dfs_is_precac_done(dfs, dfs->dfs_curchan)) { + if (dfs_is_precac_done(dfs, cur_chan)) { dfs_debug(dfs, WLAN_DEBUG_DFS, "PRE-CAC alreay done on this channel %d", - dfs->dfs_curchan->dfs_ch_ieee); + cur_chan->dfs_ch_ieee); return false; } @@ -394,7 +434,9 @@ bool dfs_check_for_cac_start(struct wlan_dfs *dfs, * VAP(1) comes up in the same channel then instead of * cancelling the CAC we can let the CAC continue. */ - if (dfs_is_curchan_subset_of_cac_started_chan(dfs)) { + if (dfs_is_new_chan_subset_of_old_chan(dfs, + cur_chan, + cac_started_chan)) { *continue_current_cac = true; } else { /* New CAC is needed, cancel the running CAC @@ -414,7 +456,9 @@ bool dfs_check_for_cac_start(struct wlan_dfs *dfs, dfs_cancel_cac_timer(dfs); } } else { /* CAC timer is not running. */ - return dfs_skip_cac_after_vdev_restart(dfs); + return dfs_skip_cac_after_vdev_restart(dfs, + cur_chan, + prev_chan); } return true; diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h index ca0b4e902357..4070d84b8fc1 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h @@ -729,16 +729,20 @@ void utils_dfs_reg_update_nol_history_ch(struct wlan_objmgr_pdev *pdev, bool nol_history_ch); /** - * utils_dfs_check_for_cac_start() - Check for DFS CAC start conditions. + * utils_dfs_is_cac_required() - Check if CAC is required on the cur_chan. * @pdev: pdev ptr + * @cur_chan: Pointer to current channel of wlan_channel structure. + * @prev_chan: Pointer to previous channel of wlan_channel structure. * @continue_current_cac: If AP can start CAC then this variable indicates * whether to continue with the current CAC or restart the CAC. This variable * is valid only if this function returns true. * - * Return: true if AP can start or continue the current CAC, else false. + * Return: true if AP requires CAC or can continue current CAC, else false. */ -bool utils_dfs_check_for_cac_start(struct wlan_objmgr_pdev *pdev, - bool *continue_current_cac); +bool utils_dfs_is_cac_required(struct wlan_objmgr_pdev *pdev, + struct wlan_channel *cur_chan, + struct wlan_channel *prev_chan, + bool *continue_current_cac); /** utils_dfs_is_precac_done() - Check if precac has been done in chosen channel * @pdev: Pointer to DFS pdev object. @@ -779,10 +783,4 @@ QDF_STATUS utils_dfs_get_disable_radar_marking(struct wlan_objmgr_pdev *pdev, */ void utils_dfs_deliver_event(struct wlan_objmgr_pdev *pdev, uint16_t freq, enum WLAN_DFS_EVENTS event); - -/** - * utils_dfs_clear_cac_started_chan() - Clear dfs cac started channel. - * @pdev: pdev ptr - */ -void utils_dfs_clear_cac_started_chan(struct wlan_objmgr_pdev *pdev); #endif /* _WLAN_DFS_UTILS_API_H_ */ diff --git a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c index 834676ec46e5..705d015f20aa 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c @@ -233,17 +233,6 @@ QDF_STATUS utils_dfs_cac_stop(struct wlan_objmgr_pdev *pdev) } qdf_export_symbol(utils_dfs_cac_stop); -void utils_dfs_clear_cac_started_chan(struct wlan_objmgr_pdev *pdev) -{ - struct wlan_dfs *dfs; - - dfs = wlan_pdev_get_dfs_obj(pdev); - if (!dfs) - return; - - dfs_clear_cac_started_chan(dfs); -} - /** dfs_fill_chan_info() - Fill the dfs channel structure with wlan * channel. * @chan: Pointer to DFS channel structure. @@ -277,16 +266,26 @@ bool utils_dfs_is_precac_done(struct wlan_objmgr_pdev *pdev, return dfs_is_precac_done(dfs, &chan); } -bool utils_dfs_check_for_cac_start(struct wlan_objmgr_pdev *pdev, - bool *continue_current_cac) +bool utils_dfs_is_cac_required(struct wlan_objmgr_pdev *pdev, + struct wlan_channel *cur_chan, + struct wlan_channel *prev_chan, + bool *continue_current_cac) { struct wlan_dfs *dfs; + struct dfs_channel cur_channel; + struct dfs_channel prev_channel; dfs = wlan_pdev_get_dfs_obj(pdev); if (!dfs) return false; - return dfs_check_for_cac_start(dfs, continue_current_cac); + dfs_fill_chan_info(&cur_channel, cur_chan); + dfs_fill_chan_info(&prev_channel, prev_chan); + + return dfs_is_cac_required(dfs, + &cur_channel, + &prev_channel, + continue_current_cac); } QDF_STATUS utils_dfs_stacac_stop(struct wlan_objmgr_pdev *pdev)