From 1b9dcf5a12fdbffc121c9816bb631e7107e35397 Mon Sep 17 00:00:00 2001 From: Arif Hussain Date: Sat, 4 Mar 2017 21:49:00 -0800 Subject: [PATCH] qcacmn: Add support to process radar found indication Add support to process radar found indication, find and update radar affected channels to nol. Change-Id: Icb2d601f422e43e9a98840dd22325a571fd92f27 CRs-Fixed: 2017481 --- .../core/src/dfs_process_radar_found_ind.h | 94 ++++++ .../src/misc/dfs_process_radar_found_ind.c | 282 ++++++++++++++++++ 2 files changed, 376 insertions(+) create mode 100644 umac/dfs/core/src/dfs_process_radar_found_ind.h create mode 100644 umac/dfs/core/src/misc/dfs_process_radar_found_ind.c diff --git a/umac/dfs/core/src/dfs_process_radar_found_ind.h b/umac/dfs/core/src/dfs_process_radar_found_ind.h new file mode 100644 index 000000000000..a188443333b8 --- /dev/null +++ b/umac/dfs/core/src/dfs_process_radar_found_ind.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2017 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: dfs_process_radar_found_ind.h + * This file provides prototypes of the routines needed for the + * external components to utilize the services provided by the + * DFS component. + */ + +/* Number of channel marking offsets */ +#define DFS_NUM_FREQ_OFFSET 3 + +/* Lower channel from 20 Mhz center channel */ +#define DFS_20MHZ_LOWER_CHANNEL(_f) ((_f) - 20) +/* Upper channel from 20 Mhz center channel */ +#define DFS_20MHZ_UPPER_CHANNEL(_f) ((_f) + 20) +/* 1st lower channel from center channel of bandwidth 40/80/160Mhz */ +#define DFS_FIRST_LOWER_CHANNEL(_f) ((_f) - 10) +/* 2nd lower channel from center channel of bandwidth 40/80/160Mhz */ +#define DFS_SECOND_LOWER_CHANNEL(_f) ((_f) - 30) +/* 3rd lower channel from center channel of bandwidth 80/160Mhz */ +#define DFS_THIRD_LOWER_CHANNEL(_f) ((_f) - 50) +/* 1st upper channel from center channel of bandwidth 40/80/160Mhz */ +#define DFS_FIRST_UPPER_CHANNEL(_f) ((_f) + 10) +/* 2nd upper channel from center channel of bandwidth 40/80/160Mhz */ +#define DFS_SECOND_UPPER_CHANNEL(_f) ((_f) + 30) +/* 3rd upper channel from center channel of bandwidth 80/160Mhz */ +#define DFS_THIRD_UPPER_CHANNEL(_f) ((_f) + 50) + +/* 20 Mhz freq_offset lower */ +#define DFS_20MZ_OFFSET_LOWER (-10) +/* 20 Mhz freq_offset upper */ +#define DFS_20MZ_OFFSET_UPPER (10) +/* 40/80 Mhz freq_offset first lower */ +#define DFS_OFFET_FIRST_LOWER (-20) +/* 40/80 Mhz freq_offset second lower */ +#define DFS_OFFET_SECOND_LOWER (-40) +/* 40/80 Mhz freq_offset first upper */ +#define DFS_OFFET_FIRST_UPPER (20) +/* 40/80 Mhz freq_offset second upper */ +#define DFS_OFFET_SECOND_UPPER (40) + +/* Frequency offset to sidx */ +#define DFS_FREQ_OFFSET_TO_SIDX(_f) ((32 * (_f)) / 10) +/* sidx offset boundry */ +#define DFS_BOUNDRY_SIDX 32 +/* freq offset for chirp */ +#define DFS_CHIRP_OFFSET 10 +/* second segment freq offset */ +#define DFS_160MHZ_SECOND_SEG_OFFSET 40 + +/** + * struct freqs_offsets - frequency and offset informat + * @chan_num: channel number. + * @freq: channel frequency in mhz. + * @offset: offset from center frequency. + * + * This information is needed to find and mark radar infected + * channels in NOL and regulatory database. + */ +struct freqs_offsets { + uint32_t chan_num[DFS_NUM_FREQ_OFFSET]; + int32_t freq[DFS_NUM_FREQ_OFFSET]; + uint32_t offset[DFS_NUM_FREQ_OFFSET]; +}; + +/** + * dfs_process_radar_found_indication() - Process radar found indication + * @dfs: Pointer to wlan_dfs structure. + * @radar_found: radar found info. + * + * Process radar found indication and update radar effected channel in NOL + * and regulatory. + * + * Return: None + */ +void dfs_process_radar_found_indication(struct wlan_dfs *dfs, + struct radar_found_info *radar_found); 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 new file mode 100644 index 000000000000..126e5cffd388 --- /dev/null +++ b/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2017 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: API for processing radar found indication. + * + */ + +#include "../dfs.h" +#include "../dfs_process_radar_found_ind.h" +#include +#include + +/** + * A) If is chirp or radar found at boundary, two channels will effected. + * freq_offset.freq[0] = fn+1 + * freq_offset.freq[1] = fn+1 + * freq_offset.freq[2] = fn + * + * Two channels, ch(n) and ch(n+1) will be added to nol. + * + * + * dfs_freq_offset (radar found freq) + * | + * | + * V + * _______________________________________________________________________ + * | center freq | center freq | center freq | + * | ch(n-1) | ch(n) | ch(n+1) | + * | | | | | | | + * | | | | | | | + * | | | | | | | + * fn-1 fn boundary fn+1 + * <-------- 20 Mhz ------> + * + * + * B) Else only one channel will be effected + * freq_offset.freq[0] = fn + * freq_offset.freq[1] = fn + * freq_offset.freq[2] = fn + * + * One channel ch(n) will be added to nol. + * + * + * dfs_freq_offset (radar found freq) + * | + * | + * V + * _______________________________________________________________________ + * | center freq | center freq | center freq | + * | ch(n-1) | ch(n) | ch(n+1) | + * | | | | | | | + * | | | | | | | + * | | | | | | | + * fn-1 fn boundary fn+1 + * <-------- 20 Mhz ------> + */ + +/** + * dfs_radar_add_to_nol()- add channel to nol list + * @dfs: dfs handler + * @freq_offset: freq offset + * + * add channel to nol list. + * + * Return: None + */ +static void dfs_radar_add_to_nol(struct wlan_dfs *dfs, + struct freqs_offsets *freq_offset) +{ + int i; + uint8_t last_chan = 0; + uint8_t nollist[DFS_NUM_FREQ_OFFSET]; + 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_PRINTK("%s: ch=%d is not dfs skip\n", + __func__, freq_offset->chan_num[i]); + continue; + } + last_chan = freq_offset->chan_num[i]; + dfs_nol_addchan(dfs, (uint16_t)freq_offset->freq[i], + DFS_NOL_TIMEOUT_S); + nollist[num_ch++] = last_chan; + DFS_PRINTK("%s: ch=%d Added to NOL\n", __func__, last_chan); + } + utils_dfs_reg_update_nol_ch(dfs->dfs_pdev_obj, + nollist, num_ch, DFS_NOL_SET); + dfs_save_nol(dfs->dfs_pdev_obj); +} + +/** + * dfs_radar_chan_for_80()- Find frequency offsets for 80MHz + * @freq_offset: freq offset + * @center_freq: center frequency + * + * Find frequency offsets for 80MHz + * + * Return: None + */ +static void dfs_radar_chan_for_80(struct freqs_offsets *freq_offset, + uint32_t center_freq) +{ + int i; + + for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { + if (freq_offset->offset[i] < DFS_OFFET_SECOND_LOWER) + freq_offset->freq[i] = + DFS_THIRD_LOWER_CHANNEL(center_freq); + else if ((freq_offset->offset[i] > DFS_OFFET_SECOND_LOWER) && + (freq_offset->offset[i] < DFS_OFFET_FIRST_LOWER)) + freq_offset->freq[i] = + DFS_SECOND_LOWER_CHANNEL(center_freq); + else if ((freq_offset->offset[i] > DFS_OFFET_FIRST_LOWER) && + (freq_offset->offset[i] < 0)) + freq_offset->freq[i] = + DFS_FIRST_LOWER_CHANNEL(center_freq); + else if ((freq_offset->offset[i] > 0) && + (freq_offset->offset[i] < DFS_OFFET_FIRST_UPPER)) + freq_offset->freq[i] = + DFS_FIRST_UPPER_CHANNEL(center_freq); + else if ((freq_offset->offset[i] > DFS_OFFET_FIRST_UPPER) && + (freq_offset->offset[i] < DFS_OFFET_SECOND_UPPER)) + freq_offset->freq[i] = + DFS_SECOND_UPPER_CHANNEL(center_freq); + else if (freq_offset->offset[i] > DFS_OFFET_SECOND_UPPER) + freq_offset->freq[i] = + DFS_THIRD_UPPER_CHANNEL(center_freq); + } +} + +/** + * dfs_radar_chan_for_40()- Find frequency offsets for 40MHz + * @freq_offset: freq offset + * @center_freq: center frequency + * + * Find frequency offsets for 40MHz + * + * Return: None + */ +static void dfs_radar_chan_for_40(struct freqs_offsets *freq_offset, + uint32_t center_freq) +{ + int i; + + for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { + if (freq_offset->offset[i] < DFS_OFFET_FIRST_LOWER) + freq_offset->freq[i] = + DFS_SECOND_LOWER_CHANNEL(center_freq); + else if ((freq_offset->offset[i] > DFS_OFFET_FIRST_LOWER) && + (freq_offset->offset[i] < 0)) + freq_offset->freq[i] = + DFS_FIRST_LOWER_CHANNEL(center_freq); + else if ((freq_offset->offset[i] > 0) && + (freq_offset->offset[i] < DFS_OFFET_FIRST_UPPER)) + freq_offset->freq[i] = + DFS_FIRST_UPPER_CHANNEL(center_freq); + else if (freq_offset->offset[i] > DFS_OFFET_FIRST_UPPER) + freq_offset->freq[i] = + DFS_SECOND_UPPER_CHANNEL(center_freq); + } +} + +/** + * dfs_radar_chan_for_20()- Find frequency offsets for 20MHz + * @freq_offset: freq offset + * @center_freq: center frequency + * + * Find frequency offsets for 20MHz + * + * Return: None + */ +static void dfs_radar_chan_for_20(struct freqs_offsets *freq_offset, + uint32_t center_freq) +{ + int i; + + for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { + if (freq_offset->offset[i] <= DFS_20MZ_OFFSET_LOWER) + freq_offset->freq[i] = + DFS_20MHZ_LOWER_CHANNEL(center_freq); + else if ((freq_offset->offset[i] > DFS_20MZ_OFFSET_LOWER) && + (freq_offset->offset[i] < DFS_20MZ_OFFSET_UPPER)) + freq_offset->freq[i] = center_freq; + else if (freq_offset->offset[i] >= DFS_20MZ_OFFSET_UPPER) + freq_offset->freq[i] = + DFS_20MHZ_UPPER_CHANNEL(center_freq); + } +} + +void dfs_process_radar_found_indication(struct wlan_dfs *dfs, + struct radar_found_info *radar_found) +{ + int i; + struct freqs_offsets freq_offset; + uint32_t freq_center, flag; + int32_t sidx; + + if (!dfs || !dfs->dfs_curchan) { + DFS_PRINTK("%s: dfs is null\n", __func__); + return; + } + + qdf_mem_set(&freq_offset, sizeof(freq_offset), 0); + flag = dfs->dfs_curchan->ic_flags; + + for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) + freq_offset.offset[i] = radar_found->freq_offset; + + sidx = DFS_FREQ_OFFSET_TO_SIDX(radar_found->freq_offset); + + if (!radar_found->segment_id) + freq_center = utils_dfs_chan_to_freq(dfs->dfs_pdev_obj, + dfs->dfs_curchan->ic_vhtop_ch_freq_seg1); + else { + freq_center = utils_dfs_chan_to_freq(dfs->dfs_pdev_obj, + dfs->dfs_curchan->ic_vhtop_ch_freq_seg2); + if (flag & IEEE80211_CHAN_VHT160) + freq_center += DFS_160MHZ_SECOND_SEG_OFFSET; + } + + DFS_PRINTK("%s: seg=%d, sidx=%d, offset=%d, chirp=%d, flag=%d, f=%d\n", + __func__, radar_found->segment_id, sidx, + radar_found->freq_offset, radar_found->is_chirp, + flag, freq_center); + + if ((flag & IEEE80211_CHAN_HT20) || + (flag & IEEE80211_CHAN_VHT20)) { + if (radar_found->is_chirp || + (sidx && !(abs(sidx) % DFS_BOUNDRY_SIDX))) { + freq_offset.offset[1] -= DFS_CHIRP_OFFSET; + freq_offset.offset[2] += DFS_CHIRP_OFFSET; + } + dfs_radar_chan_for_20(&freq_offset, freq_center); + } else if ((flag & IEEE80211_CHAN_VHT40PLUS) || + (flag & IEEE80211_CHAN_HT40PLUS) || + (flag & IEEE80211_CHAN_VHT40MINUS) || + (flag & IEEE80211_CHAN_HT40MINUS)) { + if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDRY_SIDX)) { + freq_offset.offset[1] -= DFS_CHIRP_OFFSET; + freq_offset.offset[2] += DFS_CHIRP_OFFSET; + } + dfs_radar_chan_for_40(&freq_offset, freq_center); + } else if ((flag & IEEE80211_CHAN_VHT80) || + (flag & IEEE80211_CHAN_VHT80_80) || + (flag & IEEE80211_CHAN_VHT160)) { + if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDRY_SIDX)) { + freq_offset.offset[1] -= DFS_CHIRP_OFFSET; + freq_offset.offset[2] += DFS_CHIRP_OFFSET; + } + dfs_radar_chan_for_80(&freq_offset, freq_center); + } + + for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { + freq_offset.chan_num[i] = utils_dfs_freq_to_chan( + dfs->dfs_pdev_obj, freq_offset.freq[i]); + DFS_PRINTK("%s: offset=%d, channel%d\n", + __func__, i, freq_offset.chan_num[i]); + } + + dfs_radar_add_to_nol(dfs, &freq_offset); +}