qcacmn: Add APIs to skip DFS CAC

Skip CAC if cac is already started on the same channel or the new channel
is subset of CAC started channel.

Change-Id: I8f6121f1f8d034acf3f0514a60401a3232becaa2
CRs-Fixed: 2309911
This commit is contained in:
Shashikala Prabhu 2018-09-04 16:02:09 +05:30 • committed by nshrivas
commit 6b4d64dbfa
8 changed files with 258 additions and 76 deletions

View file

@ -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.

View file

@ -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_ */

View file

@ -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_ */

View file

@ -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));
}

View file

@ -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;
}

View file

@ -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)

View file

@ -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.

View file

@ -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,