diff --git a/umac/dfs/core/src/dfs.h b/umac/dfs/core/src/dfs.h index c41a299bf19a..7d34b93b53fd 100644 --- a/umac/dfs/core/src/dfs.h +++ b/umac/dfs/core/src/dfs.h @@ -942,6 +942,9 @@ struct dfs_event_log { * @dfs_precac_required_list: PreCAC required list. * @dfs_precac_done_list: PreCAC done list. * @dfs_precac_nol_list: PreCAC NOL List. + * @dfs_curchan: DFS current channel. + * @dfs_cac_started_chan: CAC started channel. + * @dfs_pdev_obj: DFS pdev object. * @dfs_is_offload_enabled: Set if DFS offload enabled. * @dfs_use_nol: Use the NOL when radar found(default: TRUE) * @dfs_nol_lock: Lock to protect nol list. @@ -974,6 +977,7 @@ struct dfs_event_log { * @dfs_bw_reduced: DFS bandwidth reduced channel bit. * @dfs_freq_offset: Frequency offset where radar was found. * @dfs_enhanced_bangradar: DFS enhance bagradar bit for Full offload. + * @dfs_cac_aborted: DFS cac is aborted. */ struct wlan_dfs { uint32_t dfs_debug_mask; @@ -1076,6 +1080,7 @@ struct wlan_dfs { #endif struct dfs_channel *dfs_curchan; + struct dfs_channel dfs_cac_started_chan; struct wlan_objmgr_pdev *dfs_pdev_obj; bool dfs_is_offload_enabled; int dfs_use_nol; @@ -1102,6 +1107,7 @@ struct wlan_dfs { uint8_t dfs_bw_reduced; int32_t dfs_freq_offset; uint8_t dfs_enhanced_bangradar; + bool dfs_cac_aborted; }; /** @@ -1857,6 +1863,37 @@ 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. + * @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 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. + * @dfs: Pointer to wlan_dfs structure. + * + * If the current channel and the cac_started_chan is same or + * if the current channel is subset of the cac_started_chan then + * this function returns true. + * + * Return: true if current channel is same or subset of cac started channel, + * else false. + */ +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. diff --git a/umac/dfs/core/src/dfs_etsi_precac.h b/umac/dfs/core/src/dfs_etsi_precac.h index 1a297d06a962..2bc20852bbff 100644 --- a/umac/dfs/core/src/dfs_etsi_precac.h +++ b/umac/dfs/core/src/dfs_etsi_precac.h @@ -216,23 +216,4 @@ static inline void dfs_add_to_etsi_precac_done_list(struct wlan_dfs *dfs) } #endif -/** - * dfs_get_bonding_channels_without_seg_info() - Get bonding channels in curchan - * @curchan: Pointer to dfs_channel structure. - * @channels: channel array holding list of bonded channels. - * - * Return: number of sub channels in the current channel. - */ -#ifdef QCA_SUPPORT_ETSI_PRECAC_DFS -uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *curchan, - uint8_t *channels); -#else -static inline uint8_t -dfs_get_bonding_channels_without_seg_info(struct dfs_channel *curchan, - uint8_t *channels) -{ - return 0; -} -#endif - #endif /* _DFS_ETSI_PRECAC_H_ */ diff --git a/umac/dfs/core/src/dfs_process_radar_found_ind.h b/umac/dfs/core/src/dfs_process_radar_found_ind.h index 26f739a27ac2..09269f5c6fa2 100644 --- a/umac/dfs/core/src/dfs_process_radar_found_ind.h +++ b/umac/dfs/core/src/dfs_process_radar_found_ind.h @@ -23,6 +23,9 @@ * DFS component. */ +#ifndef _DFS_PROCESS_RADAR_FOUND_IND_H_ +#define _DFS_PROCESS_RADAR_FOUND_IND_H_ + /* Number of channel marking offsets */ #define DFS_NUM_FREQ_OFFSET 3 @@ -144,3 +147,14 @@ void dfs_radarfound_action_generic(struct wlan_dfs *dfs, uint8_t seg_id); uint8_t dfs_get_bonding_channels(struct dfs_channel *curchan, uint32_t segment_id, uint8_t *channels); + +/** + * dfs_get_bonding_channels_without_seg_info() - Get bonding channels in chan + * @chan: Pointer to dfs_channel structure. + * @channels: channel array holding list of bonded channels. + * + * Return: number of sub channels in the input channel. + */ +uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *chan, + uint8_t *channels); +#endif /*_DFS_PROCESS_RADAR_FOUND_IND_H_ */ diff --git a/umac/dfs/core/src/misc/dfs_cac.c b/umac/dfs/core/src/misc/dfs_cac.c index afed5094604c..c761f2a6e3e0 100644 --- a/umac/dfs/core/src/misc/dfs_cac.c +++ b/umac/dfs/core/src/misc/dfs_cac.c @@ -34,6 +34,7 @@ #include "wlan_dfs_utils_api.h" #include "wlan_dfs_mlme_api.h" #include "../dfs_internal.h" +#include "../dfs_process_radar_found_ind.h" #define IS_CHANNEL_WEATHER_RADAR(freq) ((freq >= 5600) && (freq <= 5650)) #define ADJACENT_WEATHER_RADAR_CHANNEL 5580 @@ -183,6 +184,8 @@ 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)); } @@ -201,11 +204,24 @@ int dfs_is_ap_cac_timer_running(struct wlan_dfs *dfs) void dfs_start_cac_timer(struct wlan_dfs *dfs) { - qdf_timer_mod(&dfs->dfs_cac_timer, - dfs_mlme_get_cac_timeout(dfs->dfs_pdev_obj, - dfs->dfs_curchan->dfs_ch_freq, - dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2, - dfs->dfs_curchan->dfs_ch_flags) * 1000); + int cac_timeout = 0; + struct dfs_channel *chan = dfs->dfs_curchan; + + cac_timeout = dfs_mlme_get_cac_timeout(dfs->dfs_pdev_obj, + chan->dfs_ch_freq, + chan->dfs_ch_vhtop_ch_freq_seg2, + chan->dfs_ch_flags); + + dfs->dfs_cac_started_chan = *chan; + + dfs_debug(dfs, WLAN_DEBUG_DFS, + "chan = %d cfreq2 = %d timeout = %d sec, curr_time = %d sec", + chan->dfs_ch_ieee, chan->dfs_ch_vhtop_ch_freq_seg2, + cac_timeout, + qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000); + + qdf_timer_mod(&dfs->dfs_cac_timer, cac_timeout * 1000); + dfs->dfs_cac_aborted = 0; } void dfs_cancel_cac_timer(struct wlan_dfs *dfs) @@ -222,6 +238,8 @@ void dfs_cac_stop(struct wlan_dfs *dfs) "Stopping CAC Timer %d procphyerr 0x%08x", dfs->dfs_curchan->dfs_ch_freq, phyerr); qdf_timer_stop(&dfs->dfs_cac_timer); + if (dfs->dfs_cac_timer_running) + dfs->dfs_cac_aborted = 1; dfs->dfs_cac_timer_running = 0; } @@ -234,3 +252,77 @@ void dfs_stacac_stop(struct wlan_dfs *dfs) "Stopping STA CAC Timer %d procphyerr 0x%08x", dfs->dfs_curchan->dfs_ch_freq, phyerr); } + +bool dfs_is_subset_channel(struct dfs_channel *old_chan, + struct dfs_channel *new_chan) +{ + 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; + + 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(old_chan, + SEG_ID_SECONDARY, + 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( + new_chan, SEG_ID_SECONDARY, + 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 > old_n_chans) + return false; + + for (i = 0; i < new_n_chans; i++) { + is_found = false; + for (j = 0; j < old_n_chans; j++) { + if (new_subchans[i] == old_subchans[j]) { + is_found = true; + break; + } + } + + /* If new_subchans[i] is not found in old_subchans, then, + * new_chan is not subset of old_chan. + */ + if (!is_found) + break; + } + + return is_found; +} + +bool dfs_is_curchan_subset_of_cac_started_chan(struct wlan_dfs *dfs) +{ + return dfs_is_subset_channel(&dfs->dfs_cac_started_chan, + dfs->dfs_curchan); +} + +void dfs_clear_cac_started_chan(struct wlan_dfs *dfs) +{ + qdf_mem_zero(&dfs->dfs_cac_started_chan, + sizeof(dfs->dfs_cac_started_chan)); +} diff --git a/umac/dfs/core/src/misc/dfs_etsi_precac.c b/umac/dfs/core/src/misc/dfs_etsi_precac.c index 3f4fbcc8734c..d0a083d3b6a0 100644 --- a/umac/dfs/core/src/misc/dfs_etsi_precac.c +++ b/umac/dfs/core/src/misc/dfs_etsi_precac.c @@ -346,51 +346,3 @@ void dfs_add_to_etsi_precac_done_list(struct wlan_dfs *dfs) dfs_add_chan_to_etsi_done_list(dfs, channels[i]); } } - -uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *curchan, - uint8_t *channels) -{ - uint8_t center_chan; - uint8_t nchannels = 0; - - center_chan = curchan->dfs_ch_vhtop_ch_freq_seg1; - - if (WLAN_IS_CHAN_MODE_20(curchan)) { - nchannels = 1; - channels[0] = center_chan; - } else if (WLAN_IS_CHAN_MODE_40(curchan)) { - nchannels = 2; - channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; - channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; - } else if (WLAN_IS_CHAN_MODE_80(curchan)) { - nchannels = 4; - channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; - channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; - channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; - channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; - } else if (WLAN_IS_CHAN_MODE_80_80(curchan)) { - nchannels = 8; - channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; - channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; - channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; - channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; - center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2; - channels[4] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; - channels[5] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; - channels[6] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; - channels[7] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; - } else if (WLAN_IS_CHAN_MODE_160(curchan)) { - nchannels = 8; - center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2; - channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET; - channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET; - channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; - channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; - channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; - channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; - channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET; - channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET; - } - - return nchannels; -} 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 1f523140c920..6879446c0bcb 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 @@ -360,6 +360,54 @@ static uint8_t dfs_find_radar_affected_subchans(struct wlan_dfs *dfs, return i; } +uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *chan, + uint8_t *channels) +{ + uint8_t center_chan; + uint8_t nchannels = 0; + + center_chan = chan->dfs_ch_vhtop_ch_freq_seg1; + + if (WLAN_IS_CHAN_MODE_20(chan)) { + nchannels = 1; + channels[0] = center_chan; + } else if (WLAN_IS_CHAN_MODE_40(chan)) { + nchannels = 2; + channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; + } else if (WLAN_IS_CHAN_MODE_80(chan)) { + nchannels = 4; + channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; + channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; + } else if (WLAN_IS_CHAN_MODE_80_80(chan)) { + nchannels = 8; + channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; + channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; + center_chan = chan->dfs_ch_vhtop_ch_freq_seg2; + channels[4] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; + channels[5] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[6] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[7] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; + } else if (WLAN_IS_CHAN_MODE_160(chan)) { + nchannels = 8; + center_chan = chan->dfs_ch_vhtop_ch_freq_seg2; + channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET; + channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET; + channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; + channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; + channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; + channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET; + channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET; + } + + return nchannels; +} + uint8_t dfs_get_bonding_channels(struct dfs_channel *curchan, uint32_t segment_id, uint8_t *channels) diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h index ccbf754fccc9..21a625fba699 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h @@ -242,6 +242,34 @@ QDF_STATUS utils_dfs_cac_stop(struct wlan_objmgr_pdev *pdev); */ QDF_STATUS utils_dfs_stacac_stop(struct wlan_objmgr_pdev *pdev); +/** + * utils_dfs_is_curchan_subset_of_cac_started_chan() - Check if the dfs current + * channel is subset of cac started channel. + * @pdev: Pointer to DFS pdev object. + * + * wrapper function for dfs_is_curchan_subset_of_cac_started_chan(). this + * function called from outside of dfs component. + * + * Return: true if current channel is same or subset of cac started channel, + * else false. + */ +bool utils_dfs_is_curchan_subset_of_cac_started_chan( + struct wlan_objmgr_pdev *pdev); + +/** + * utils_dfs_is_cac_aborted() - Check if previous CAC was aborted. + * @pdev: Pointer to DFS pdev object. + * + * Return: true if previous CAC was aborted, else false. + */ +bool utils_dfs_is_cac_aborted(struct wlan_objmgr_pdev *pdev); + +/** + * utils_dfs_clear_cac_started_chan() - Clear dfs cac started channel. + * @pdev: Pointer to DFS pdev object. + */ +void utils_dfs_clear_cac_started_chan(struct wlan_objmgr_pdev *pdev); + /** * utils_dfs_get_usenol() - Returns use_nol flag. * @pdev: Pointer to DFS pdev object. diff --git a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c index 2f6e3c5e7ad4..95c2c2b92c18 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c @@ -247,6 +247,40 @@ QDF_STATUS utils_dfs_stacac_stop(struct wlan_objmgr_pdev *pdev) } qdf_export_symbol(utils_dfs_stacac_stop); +bool utils_dfs_is_curchan_subset_of_cac_started_chan( + struct wlan_objmgr_pdev *pdev) +{ + struct wlan_dfs *dfs; + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) + return false; + + return dfs_is_curchan_subset_of_cac_started_chan(dfs); +} + +bool utils_dfs_is_cac_aborted(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_dfs *dfs; + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) + return false; + + return dfs->dfs_cac_aborted; +} + +void utils_dfs_clear_cac_started_chan(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_dfs *dfs; + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) + return; + + dfs_clear_cac_started_chan(dfs); +} + QDF_STATUS utils_dfs_get_usenol(struct wlan_objmgr_pdev *pdev, uint16_t *usenol) { struct wlan_dfs *dfs; @@ -794,10 +828,6 @@ QDF_STATUS utils_dfs_bw_reduced_channel( dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1; ch_params->center_freq_seg1 = dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2; - /*If bandwidth reduction is applied, - * dfs_ignore_cac ensures we skip CAC. - */ - dfs->dfs_ignore_cac = 1; dfs->dfs_bw_reduced = 1; wlan_reg_set_channel_params(pdev, dfs->dfs_curchan->dfs_ch_ieee,