Browse Source

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
Arif Hussain 8 years ago
parent
commit
1b9dcf5a12

+ 94 - 0
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);

+ 282 - 0
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 <wlan_reg_services_api.h>
+#include <wlan_dfs_utils_api.h>
+
+/**
+ * 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);
+}