qcacmn: Add support to mark bonding channels to nol

If sub-channel marking is not supported then make sure to
add all the dfs channels in bonding channel list to NOL.

Change-Id: I27d738974bb2b2cfdb9dbcd944f5843cc3aeed93
CRs-Fixed: 2164692
Esse commit está contido em:
Arif Hussain
2018-02-02 22:22:21 +05:30
commit de snandini
commit 5aa8c07392
3 arquivos alterados com 172 adições e 92 exclusões

Ver arquivo

@@ -913,6 +913,9 @@ struct dfs_event_log {
* @dfs_use_nol: Use the NOL when radar found(default: TRUE)
* @dfs_nol_lock: Lock to protect nol list.
* @tx_leakage_threshold: Tx leakage threshold for dfs.
* @dfs_use_nol_subchannel_marking: Use subchannel marking logic to add only
* radar affected subchannel instead of all
* bonding channels.
*/
struct wlan_dfs {
uint32_t dfs_debug_mask;
@@ -1011,6 +1014,7 @@ struct wlan_dfs {
int dfs_use_nol;
qdf_spinlock_t dfs_nol_lock;
uint16_t tx_leakage_threshold;
bool dfs_use_nol_subchannel_marking;
};
/**

Ver arquivo

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017 The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -59,7 +59,7 @@
/* Frequency offset to sidx */
#define DFS_FREQ_OFFSET_TO_SIDX(_f) ((32 * (_f)) / 10)
/* sidx offset boundary */
#define DFS_BOUNDRY_SIDX 32
#define DFS_BOUNDARY_SIDX 32
/* freq offset for chirp */
#define DFS_CHIRP_OFFSET 10
/* second segment freq offset */
@@ -70,9 +70,17 @@
#define LEFT_CH 1
#define RIGHT_CH 2
/* Next channel number offset's from center channel number */
#define DFS_5GHZ_NEXT_CHAN_OFFSET 2
#define DFS_5GHZ_2ND_CHAN_OFFSET 6
#define DFS_5GHZ_3RD_CHAN_OFFSET 10
#define DFS_5GHZ_4TH_CHAN_OFFSET 14
/* Max number of bonding channels in 160 MHz segment */
#define NUM_CHANNELS_160MHZ 8
/**
* struct freqs_offsets - frequency and offset information
* @chan_num: channel number.
* @freq: channel frequency in mhz.
* @offset: offset from center frequency.
*
@@ -84,7 +92,6 @@
* channels in NOL and regulatory database.
*/
struct freqs_offsets {
uint32_t chan_num[DFS_NUM_FREQ_OFFSET];
uint32_t freq[DFS_NUM_FREQ_OFFSET];
int32_t offset[DFS_NUM_FREQ_OFFSET];
};

Ver arquivo

@@ -118,47 +118,55 @@
*/
/**
* dfs_radar_add_to_nol()- add channel to nol list
* @dfs: dfs handler
* @freq_offset: freq offset
* dfs_radar_add_channel_list_to_nol()- Add given channels to nol
* @dfs: Pointer to wlan_dfs structure.
* @channels: Pointer to the channel list.
* @num_channels: Number of channels in the list.
*
* add channel to nol list.
* Add list of channels to nol, only if the channel is dfs.
*
* Return: None
* Return: QDF_STATUS
*/
static QDF_STATUS dfs_radar_add_to_nol(struct wlan_dfs *dfs,
struct freqs_offsets *freq_offset)
static QDF_STATUS dfs_radar_add_channel_list_to_nol(struct wlan_dfs *dfs,
uint8_t *channels,
uint8_t num_channels)
{
int i;
uint8_t last_chan = 0;
uint8_t nollist[DFS_NUM_FREQ_OFFSET];
uint8_t nollist[NUM_CHANNELS_160MHZ];
uint8_t num_ch = 0;
for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
if (freq_offset->chan_num[i] == 0 ||
freq_offset->chan_num[i] == last_chan)
continue;
if (!utils_is_dfs_ch(dfs->dfs_pdev_obj,
freq_offset->chan_num[i])) {
dfs_info(dfs, WLAN_DEBUG_DFS,
"ch=%d is not dfs, skip",
freq_offset->chan_num[i]);
continue;
}
last_chan = freq_offset->chan_num[i];
DFS_NOL_ADD_CHAN_LOCKED(dfs,
(uint16_t)freq_offset->freq[i],
dfs->wlan_dfs_nol_timeout);
nollist[num_ch++] = last_chan;
dfs_info(dfs, WLAN_DEBUG_DFS,
"ch = %d Added to NOL", last_chan);
if (num_channels > NUM_CHANNELS_160MHZ) {
dfs_err(dfs, WLAN_DEBUG_DFS,
"Invalid num channels: %d", num_channels);
return QDF_STATUS_E_FAILURE;
}
if (!num_ch)
for (i = 0; i < num_channels; i++) {
if (channels[i] == 0 ||
channels[i] == last_chan)
continue;
if (!utils_is_dfs_ch(dfs->dfs_pdev_obj, channels[i])) {
dfs_info(dfs, WLAN_DEBUG_DFS, "ch=%d is not dfs, skip",
channels[i]);
continue;
}
last_chan = channels[i];
DFS_NOL_ADD_CHAN_LOCKED(dfs,
(uint16_t)utils_dfs_chan_to_freq(channels[i]),
dfs->wlan_dfs_nol_timeout);
nollist[num_ch++] = last_chan;
dfs_info(dfs, WLAN_DEBUG_DFS, "ch=%d Added to NOL", last_chan);
}
if (!num_ch) {
dfs_err(dfs, WLAN_DEBUG_DFS,
"dfs channels not found in channel list");
return QDF_STATUS_E_FAILURE;
}
utils_dfs_reg_update_nol_ch(dfs->dfs_pdev_obj,
nollist, num_ch, DFS_NOL_SET);
nollist, num_ch, DFS_NOL_SET);
dfs_nol_update(dfs);
utils_dfs_save_nol(dfs->dfs_pdev_obj);
@@ -175,7 +183,7 @@ static QDF_STATUS dfs_radar_add_to_nol(struct wlan_dfs *dfs,
* Return: None
*/
static void dfs_radar_chan_for_80(struct freqs_offsets *freq_offset,
uint32_t center_freq)
uint32_t center_freq)
{
int i;
@@ -215,7 +223,7 @@ static void dfs_radar_chan_for_80(struct freqs_offsets *freq_offset,
* Return: None
*/
static void dfs_radar_chan_for_40(struct freqs_offsets *freq_offset,
uint32_t center_freq)
uint32_t center_freq)
{
int i;
@@ -247,7 +255,7 @@ static void dfs_radar_chan_for_40(struct freqs_offsets *freq_offset,
* Return: None
*/
static void dfs_radar_chan_for_20(struct freqs_offsets *freq_offset,
uint32_t center_freq)
uint32_t center_freq)
{
int i;
@@ -268,23 +276,26 @@ static void dfs_radar_chan_for_20(struct freqs_offsets *freq_offset,
* dfs_find_radar_affected_subchans() - Finds radar affected sub channels.
* @dfs: Pointer to wlan_dfs structure.
* @radar_found: Pointer to radar_found structure.
* @freq_offset: Pointer to save radar affected channels.
* @channels: Pointer to save radar affected channels.
*
* Return: Number of channels.
*/
static void dfs_find_radar_affected_subchans(
struct wlan_dfs *dfs,
struct radar_found_info *radar_found,
struct freqs_offsets *freq_offset)
static uint8_t dfs_find_radar_affected_subchans(struct wlan_dfs *dfs,
struct radar_found_info
*radar_found,
uint8_t *channels)
{
int i;
uint32_t freq_center, flag;
int32_t sidx;
struct dfs_channel *curchan = dfs->dfs_curchan;
struct freqs_offsets freq_offset;
qdf_mem_set(freq_offset, sizeof(*freq_offset), 0);
qdf_mem_set(&freq_offset, sizeof(freq_offset), 0);
flag = curchan->dfs_ch_flags;
for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++)
freq_offset->offset[i] = radar_found->freq_offset;
freq_offset.offset[i] = radar_found->freq_offset;
sidx = DFS_FREQ_OFFSET_TO_SIDX(radar_found->freq_offset);
@@ -304,52 +315,104 @@ static void dfs_find_radar_affected_subchans(
}
dfs_info(dfs, WLAN_DEBUG_DFS,
"seg=%d, sidx=%d, offset=%d, chirp=%d, flag=%d, f=%d",
radar_found->segment_id, sidx,
radar_found->freq_offset, radar_found->is_chirp,
flag, freq_center);
"seg=%d, sidx=%d, offset=%d, chirp=%d, flag=%d, f=%d",
radar_found->segment_id, sidx,
radar_found->freq_offset, radar_found->is_chirp,
flag, freq_center);
if ((WLAN_IS_CHAN_A(curchan)) ||
WLAN_IS_CHAN_MODE_20(curchan)) {
if ((WLAN_IS_CHAN_A(curchan)) ||
WLAN_IS_CHAN_MODE_20(curchan)) {
if (radar_found->is_chirp ||
(sidx && !(abs(sidx) % DFS_BOUNDRY_SIDX))) {
freq_offset->offset[LEFT_CH] -= DFS_CHIRP_OFFSET;
freq_offset->offset[RIGHT_CH] += DFS_CHIRP_OFFSET;
(sidx && !(abs(sidx) % DFS_BOUNDARY_SIDX))) {
freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET;
freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET;
}
dfs_radar_chan_for_20(freq_offset, freq_center);
dfs_radar_chan_for_20(&freq_offset, freq_center);
} else if (WLAN_IS_CHAN_MODE_40(curchan)) {
if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDRY_SIDX)) {
freq_offset->offset[LEFT_CH] -= DFS_CHIRP_OFFSET;
freq_offset->offset[RIGHT_CH] += DFS_CHIRP_OFFSET;
if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) {
freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET;
freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET;
}
dfs_radar_chan_for_40(freq_offset, freq_center);
dfs_radar_chan_for_40(&freq_offset, freq_center);
} else if (WLAN_IS_CHAN_MODE_80(curchan) ||
WLAN_IS_CHAN_MODE_160(curchan) ||
WLAN_IS_CHAN_MODE_80_80(curchan)) {
if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDRY_SIDX)) {
freq_offset->offset[LEFT_CH] -= DFS_CHIRP_OFFSET;
freq_offset->offset[RIGHT_CH] += DFS_CHIRP_OFFSET;
if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) {
freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET;
freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET;
}
dfs_radar_chan_for_80(freq_offset, freq_center);
dfs_radar_chan_for_80(&freq_offset, freq_center);
} else {
dfs_err(dfs, WLAN_DEBUG_DFS,
"channel flag(%d) is invalid", flag);
return;
"channel flag=%d is invalid", flag);
return 0;
}
for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
freq_offset->chan_num[i] = utils_dfs_freq_to_chan(
freq_offset->freq[i]);
dfs_info(dfs, WLAN_DEBUG_DFS, "offset = %d, channel = %d",
i, freq_offset->chan_num[i]);
channels[i] = utils_dfs_freq_to_chan(freq_offset.freq[i]);
dfs_info(dfs, WLAN_DEBUG_DFS, "offset=%d, channel=%d",
i, channels[i]);
}
return i;
}
/**
* dfs_get_bonding_channels() - Get bonding channels.
* @curchan: Pointer to dfs_channels to know width and primary channel.
* @segment_id: Segment id, useful for 80+80/160 MHz operating band.
* @channels: Pointer to save radar affected channels.
*
* Return: Number of channels.
*/
static uint8_t dfs_get_bonding_channels(struct dfs_channel *curchan,
uint32_t segment_id,
uint8_t *channels)
{
uint8_t center_chan;
uint8_t nchannels = 0;
if (!segment_id)
center_chan = curchan->dfs_ch_vhtop_ch_freq_seg1;
else
center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2;
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) ||
WLAN_IS_CHAN_MODE_80_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_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;
}
QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs,
struct radar_found_info *radar_found)
struct radar_found_info *radar_found)
{
struct freqs_offsets freq_offset;
bool wait_for_csa = false;
uint8_t channels[NUM_CHANNELS_160MHZ];
uint8_t num_channels;
QDF_STATUS status;
if (!dfs->dfs_curchan) {
@@ -360,7 +423,7 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs,
/* Check if the current channel is a non DFS channel */
if (!dfs_radarevent_basic_sanity(dfs, dfs->dfs_curchan)) {
dfs_err(dfs, WLAN_DEBUG_DFS,
"radar event on a non-DFS channel");
"radar event on a non-DFS channel");
return QDF_STATUS_E_FAILURE;
}
@@ -369,24 +432,31 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs,
return QDF_STATUS_SUCCESS;
}
dfs_find_radar_affected_subchans(dfs, radar_found, &freq_offset);
if (dfs->dfs_use_nol_subchannel_marking)
num_channels = dfs_find_radar_affected_subchans(dfs,
radar_found,
channels);
else
num_channels = dfs_get_bonding_channels(dfs->dfs_curchan,
radar_found->segment_id,
channels);
status = dfs_radar_add_to_nol(dfs, &freq_offset);
status = dfs_radar_add_channel_list_to_nol(dfs, channels, num_channels);
if (QDF_IS_STATUS_ERROR(status)) {
dfs_err(dfs, WLAN_DEBUG_DFS,
"radar event received on invalid channel");
"radar event received on invalid channel");
return status;
}
if (radar_found->segment_id == SEG_ID_SECONDARY)
dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
"Radar found on second segment VHT80 freq=%d MHz",
dfs->dfs_precac_secondary_freq);
"Radar found on second segment VHT80 freq=%d MHz",
dfs->dfs_precac_secondary_freq);
else
dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS,
"Radar found on channel %d (%d MHz)",
dfs->dfs_curchan->dfs_ch_ieee,
dfs->dfs_curchan->dfs_ch_freq);
"Radar found on channel=%d, freq=%d MHz",
dfs->dfs_curchan->dfs_ch_ieee,
dfs->dfs_curchan->dfs_ch_freq);
/*
* If precac is running and the radar found in secondary
@@ -395,9 +465,9 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs,
* channel.
*/
dfs_debug(dfs, WLAN_DEBUG_DFS,
"found_on_second = %d is_pre = %d",
dfs->is_radar_found_on_secondary_seg,
dfs_is_precac_timer_running(dfs));
"found_on_second=%d is_pre=%d",
dfs->is_radar_found_on_secondary_seg,
dfs_is_precac_timer_running(dfs));
/*
* Even if radar found on primary, we need to move the channel
@@ -405,17 +475,16 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs,
* precac-nol-list.
*/
if (dfs->dfs_precac_enable)
dfs_mark_precac_dfs(dfs,
dfs->is_radar_found_on_secondary_seg);
dfs_mark_precac_dfs(dfs, dfs->is_radar_found_on_secondary_seg);
if (!dfs->dfs_is_offload_enabled) {
if (dfs->is_radar_found_on_secondary_seg) {
dfs_second_segment_radar_disable(dfs);
dfs->is_radar_found_on_secondary_seg = 0;
if (dfs->is_radar_during_precac) {
dfs->is_radar_during_precac = 0;
return QDF_STATUS_SUCCESS;
}
if (!dfs->dfs_is_offload_enabled &&
dfs->is_radar_found_on_secondary_seg) {
dfs_second_segment_radar_disable(dfs);
dfs->is_radar_found_on_secondary_seg = 0;
if (dfs->is_radar_during_precac) {
dfs->is_radar_during_precac = 0;
return QDF_STATUS_SUCCESS;
}
}
@@ -428,10 +497,10 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs,
* NOL code isn't used, that flag is never cleared. This
* needs to be fixed. See EV 105776.
*/
dfs_mlme_start_rcsa(dfs->dfs_pdev_obj,
&wait_for_csa);
dfs_mlme_start_rcsa(dfs->dfs_pdev_obj, &wait_for_csa);
if (wait_for_csa)
return QDF_STATUS_SUCCESS;
/*
* EV 129487 : We have detected radar in the channel,
* stop processing PHY error data as this can cause