From d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 02:45:28 +0000
Subject: [PATCH] add boot partition  size

---
 kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/bcmwifi_channels.c |  733 ++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 498 insertions(+), 235 deletions(-)

diff --git a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/bcmwifi_channels.c b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/bcmwifi_channels.c
index 3a138ed..18747aa 100644
--- a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/bcmwifi_channels.c
+++ b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/bcmwifi_channels.c
@@ -1,17 +1,18 @@
-/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Misc utility routines used by kernel or app-level.
  * Contents are wifi-specific, used by any kernel or app-level
  * software that might want wifi things as it grows.
  *
- * Copyright (C) 1999-2019, Broadcom Corporation
- * 
+ * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
+ *
+ * Copyright (C) 1999-2017, Broadcom Corporation
+ *
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
  * under the terms of the GNU General Public License version 2 (the "GPL"),
  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
  * following added to such license:
- * 
+ *
  *      As a special exception, the copyright holders of this software give you
  * permission to link this software with independent modules, and to copy and
  * distribute the resulting executable under terms of your choice, provided that
@@ -19,7 +20,7 @@
  * the license of that module.  An independent module is a module which is not
  * derived from this software.  The special exception does not apply to any
  * modifications of the software.
- * 
+ *
  *      Notwithstanding the above, under no circumstances may you combine this
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
@@ -27,7 +28,7 @@
  *
  * <<Broadcom-WL-IPTag/Open:>>
  *
- * $Id: bcmwifi_channels.c 309193 2012-01-19 00:03:57Z $
+ * $Id: bcmwifi_channels.c 695288 2017-04-19 17:20:39Z $
  */
 
 #include <bcm_cfg.h>
@@ -44,19 +45,21 @@
 #include <ctype.h>
 #ifndef ASSERT
 #define ASSERT(exp)
-#endif
+#endif // endif
 #endif /* BCMDRIVER */
 
 #include <bcmwifi_channels.h>
 
 #if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL))
 #include <bcmstdlib.h> 	/* For wl/exe/GNUmakefile.brcm_wlu and GNUmakefile.wlm_dll */
-#endif
+#endif // endif
 
-/* Definitions for D11AC capable Chanspec type */
+#include <802.11.h>
 
-/* Chanspec ASCII representation with 802.11ac capability:
- * [<band> 'g'] <channel> ['/'<bandwidth> [<ctl-sideband>]['/'<1st80channel>'-'<2nd80channel>]]
+/* Definitions for D11AC capable (80MHz+) Chanspec type */
+
+/* Chanspec ASCII representation:
+ * [<band> 'g'] <channel> ['/'<bandwidth> [<primary-sideband>]['/'<1st80channel>'-'<2nd80channel>]]
  *
  * <band>:
  *      (optional) 2, 3, 4, 5 for 2.4GHz, 3GHz, 4GHz, and 5GHz respectively.
@@ -82,18 +85,18 @@
  * <1st80Channel>:
  * <2nd80Channel>:
  *      Required for 80+80, otherwise not allowed.
- *      Specifies the center channel of the first and second 80MHz band.
+ *      Specifies the center channel of the primary and secondary 80MHz band.
  *
  * In its simplest form, it is a 20MHz channel number, with the implied band
  * of 2.4GHz if channel number <= 14, and 5GHz otherwise.
  *
  * To allow for backward compatibility with scripts, the old form for
- * 40MHz channels is also allowed: <channel><ctl-sideband>
+ * 40MHz channels is also allowed: <channel><primary-sideband>
  *
  * <channel>:
  *	primary channel of 40MHz, channel <= 14 is 2GHz, otherwise 5GHz
- * <ctl-sideband>:
- * 	"U" for upper, "L" for lower (or lower case "u" "l")
+ * <primary-sideband>:
+ *	"U" for upper, "L" for lower (or lower case "u" "l")
  *
  * 5 GHz Examples:
  *      Chanspec        BW        Center Ch  Channel Range  Primary Ch
@@ -130,11 +133,7 @@
 	"80",
 	"160",
 	"80+80",
-#ifdef WL11ULB
-	"2.5"
-#else /* WL11ULB */
 	"na"
-#endif /* WL11ULB */
 };
 
 static const uint8 wf_chspec_bw_mhz[] =
@@ -145,13 +144,13 @@
 
 /* 40MHz channels in 5GHz band */
 static const uint8 wf_5g_40m_chans[] =
-{38, 46, 54, 62, 102, 110, 118, 126, 134, 142, 151, 159};
+{38, 46, 54, 62, 102, 110, 118, 126, 134, 142, 151, 159, 167, 175};
 #define WF_NUM_5G_40M_CHANS \
 	(sizeof(wf_5g_40m_chans)/sizeof(uint8))
 
 /* 80MHz channels in 5GHz band */
 static const uint8 wf_5g_80m_chans[] =
-{42, 58, 106, 122, 138, 155};
+{42, 58, 106, 122, 138, 155, 171};
 #define WF_NUM_5G_80M_CHANS \
 	(sizeof(wf_5g_80m_chans)/sizeof(uint8))
 
@@ -161,10 +160,82 @@
 #define WF_NUM_5G_160M_CHANS \
 	(sizeof(wf_5g_160m_chans)/sizeof(uint8))
 
+/* Based on IEEE 802.11ax D6.1 */
+/* 40MHz channels in 6GHz band */
+static const uint8 wf_6g_40m_chans[] =
+{3, 11, 19, 27, 35, 43, 51, 59, 67, 75, 83, 91, 99,
+107, 115, 123, 131, 139, 147, 155, 163, 171, 179,
+187, 195, 203, 211, 219, 227};
+#define WF_NUM_6G_40M_CHANS \
+	(sizeof(wf_6g_40m_chans)/sizeof(uint8))
 
-/* convert bandwidth from chanspec to MHz */
-static uint
-bw_chspec_to_mhz(chanspec_t chspec)
+/* 80MHz channels in 6GHz band */
+static const uint8 wf_6g_80m_chans[] =
+{7, 23, 39, 55, 71, 87, 103, 119, 135, 151, 167, 183,
+199, 215};
+#define WF_NUM_6G_80M_CHANS \
+	(sizeof(wf_6g_80m_chans)/sizeof(uint8))
+
+/* 160MHz channels in 6GHz band */
+static const uint8 wf_6g_160m_chans[] =
+{15, 47, 79, 111, 143, 175, 207};
+#define WF_NUM_6G_160M_CHANS \
+	(sizeof(wf_6g_160m_chans)/sizeof(uint8))
+
+/* 6GHz PSC channels */
+uint8 wf_6g_psc_chans[] =
+{5, 21, 37, 53, 69, 85, 101, 117, 133, 149, 165, 181,
+197, 213, 229};
+#define WF_NUM_6G_PSC_CHANS \
+	(sizeof(wf_6g_psc_chans)/sizeof(uint8))
+
+/* opclass and channel information for US. Table E-1 */
+static const uint16 opclass_data[] = {
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_5)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_5)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_10)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_10)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_2G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_3G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_3G |((WL_CHANSPEC_BW_10)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_3G |((WL_CHANSPEC_BW_5)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_5)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_10)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	0,
+	0,
+	0,
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+	(WL_CHANSPEC_BAND_2G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+	(WL_CHANSPEC_BAND_2G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+};
+
+/**
+ * Return the chanspec bandwidth in MHz
+ * Bandwidth of 160 MHz will be returned for 80+80MHz chanspecs.
+ *
+ * @param	chspec		chanspec_t
+ *
+ * @return	bandwidth of chspec in MHz units
+ */
+uint
+wf_bw_chspec_to_mhz(chanspec_t chspec)
 {
 	uint bw;
 
@@ -194,34 +265,34 @@
 	return (uint8)(center_ch - center_chan_to_edge(bw));
 }
 
-/* return side band number given center channel and control channel
+/* return side band number given center channel and primary20 channel
  * return -1 on error
  */
 static int
-channel_to_sb(uint center_ch, uint ctl_ch, uint bw)
+channel_to_sb(uint center_ch, uint primary_ch, uint bw)
 {
 	uint lowest = channel_low_edge(center_ch, bw);
 	uint sb;
 
-	if ((ctl_ch - lowest) % 4) {
-		/* bad ctl channel, not mult 4 */
+	if ((primary_ch - lowest) % 4) {
+		/* bad primary channel, not mult 4 */
 		return -1;
 	}
 
-	sb = ((ctl_ch - lowest) / 4);
+	sb = ((primary_ch - lowest) / 4);
 
 	/* sb must be a index to a 20MHz channel in range */
 	if (sb >= (bw / 20)) {
-		/* ctl_ch must have been too high for the center_ch */
+		/* primary_ch must have been too high for the center_ch */
 		return -1;
 	}
 
-	return sb;
+	return (int)sb;
 }
 
-/* return control channel given center channel and side band */
+/* return primary20 channel given center channel and side band */
 static uint8
-channel_to_ctl_chan(uint center_ch, uint bw, uint sb)
+channel_to_primary20_chan(uint center_ch, uint bw, uint sb)
 {
 	return (uint8)(channel_low_edge(center_ch, bw) + sb * 4);
 }
@@ -235,7 +306,7 @@
 	uint i;
 	for (i = 0; i < WF_NUM_5G_80M_CHANS; i ++) {
 		if (ch == wf_5g_80m_chans[i])
-			return i;
+			return (int)i;
 	}
 
 	return -1;
@@ -262,7 +333,7 @@
 wf_chspec_ntoa(chanspec_t chspec, char *buf)
 {
 	const char *band;
-	uint ctl_chan;
+	uint pri_chan;
 
 	if (wf_chspec_malformed(chspec))
 		return NULL;
@@ -274,32 +345,32 @@
 	    (CHSPEC_IS5G(chspec) && CHSPEC_CHANNEL(chspec) <= CH_MAX_2G_CHANNEL))
 		band = (CHSPEC_IS2G(chspec)) ? "2g" : "5g";
 
-	/* ctl channel */
-	ctl_chan = wf_chspec_ctlchan(chspec);
+	/* primary20 channel */
+	pri_chan = wf_chspec_primary20_chan(chspec);
 
-	/* bandwidth and ctl sideband */
+	/* bandwidth and primary20 sideband */
 	if (CHSPEC_IS20(chspec)) {
-		snprintf(buf, CHANSPEC_STR_LEN, "%s%d", band, ctl_chan);
+		snprintf(buf, CHANSPEC_STR_LEN, "%s%d", band, pri_chan);
 	} else if (!CHSPEC_IS8080(chspec)) {
 		const char *bw;
 		const char *sb = "";
 
-		bw = wf_chspec_bw_str[(chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT];
+		bw = wf_chspec_to_bw_str(chspec);
 
 #ifdef CHANSPEC_NEW_40MHZ_FORMAT
-		/* ctl sideband string if needed for 2g 40MHz */
+		/* primary20 sideband string if needed for 2g 40MHz */
 		if (CHSPEC_IS40(chspec) && CHSPEC_IS2G(chspec)) {
 			sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l";
 		}
 
-		snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s%s", band, ctl_chan, bw, sb);
+		snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s%s", band, pri_chan, bw, sb);
 #else
-		/* ctl sideband string instead of BW for 40MHz */
+		/* primary20 sideband string instead of BW for 40MHz */
 		if (CHSPEC_IS40(chspec)) {
 			sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l";
-			snprintf(buf, CHANSPEC_STR_LEN, "%s%d%s", band, ctl_chan, sb);
+			snprintf(buf, CHANSPEC_STR_LEN, "%s%d%s", band, pri_chan, sb);
 		} else {
-			snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s", band, ctl_chan, bw);
+			snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s", band, pri_chan, bw);
 		}
 #endif /* CHANSPEC_NEW_40MHZ_FORMAT */
 
@@ -313,7 +384,7 @@
 		chan2 = (chan2 < WF_NUM_5G_80M_CHANS) ? wf_5g_80m_chans[chan2] : 0;
 
 		/* Outputs a max of CHANSPEC_STR_LEN chars including '\0'  */
-		snprintf(buf, CHANSPEC_STR_LEN, "%d/80+80/%d-%d", ctl_chan, chan1, chan2);
+		snprintf(buf, CHANSPEC_STR_LEN, "%d/80+80/%d-%d", pri_chan, chan1, chan2);
 	}
 
 	return (buf);
@@ -339,14 +410,15 @@
 }
 
 /* given a chanspec string, convert to a chanspec.
+ * if bandwidth not specified in chanspec input string, then use default_bw as bandwidth.
  * On error return 0
  */
 chanspec_t
-wf_chspec_aton(const char *a)
+wf_chspec_aton_ex(const char *a, const uint default_bw)
 {
 	chanspec_t chspec;
 	uint chspec_ch, chspec_band, bw, chspec_bw, chspec_sb;
-	uint num, ctl_ch;
+	uint num, pri_ch;
 	uint ch1, ch2;
 	char c, sb_ul = '\0';
 	int i;
@@ -359,7 +431,7 @@
 	if (!read_uint(&a, &num))
 		return 0;
 	/* if we are looking at a 'g', then the first number was a band */
-	c = tolower((int)a[0]);
+	c = tolower(a[0]);
 	if (c == 'g') {
 		a++; /* consume the char */
 
@@ -372,21 +444,22 @@
 			return 0;
 
 		/* read the channel number */
-		if (!read_uint(&a, &ctl_ch))
+		if (!read_uint(&a, &pri_ch))
 			return 0;
 
-		c = tolower((int)a[0]);
+		c = tolower(a[0]);
 	}
 	else {
 		/* first number is channel, use default for band */
-		ctl_ch = num;
-		chspec_band = ((ctl_ch <= CH_MAX_2G_CHANNEL) ?
+		pri_ch = num;
+		chspec_band = ((pri_ch <= CH_MAX_2G_CHANNEL) ?
 		               WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G);
 	}
 
 	if (c == '\0') {
-		/* default BW of 20MHz */
-		chspec_bw = WL_CHANSPEC_BW_20;
+		/* bandwidth not specified in chanspec input string, so use default_bw bandwidth */
+		chspec_bw = default_bw;
+		bw = wf_bw_chspec_to_mhz(default_bw);
 		goto done_read;
 	}
 
@@ -408,9 +481,7 @@
 		return 0;
 
 	/* convert to chspec value */
-	if (bw == 2) {
-		chspec_bw = WL_CHANSPEC_BW_2P5;
-	} else if (bw == 5) {
+	if (bw == 5) {
 		chspec_bw = WL_CHANSPEC_BW_5;
 	} else if (bw == 10) {
 		chspec_bw = WL_CHANSPEC_BW_10;
@@ -428,11 +499,10 @@
 
 	/* So far we have <band>g<chan>/<bw>
 	 * Can now be followed by u/l if bw = 40,
-	 * or '+80' if bw = 80, to make '80+80' bw,
-	 * or '.5' if bw = 2.5 to make '2.5' bw .
+	 * or '+80' if bw = 80, to make '80+80' bw.
 	 */
 
-	c = tolower((int)a[0]);
+	c = (char)tolower((int)a[0]);
 
 	/* if we have a 2g/40 channel, we should have a l/u spec now */
 	if (chspec_band == WL_CHANSPEC_BAND_2G && bw == 40) {
@@ -474,19 +544,6 @@
 		/* read secondary 80MHz channel */
 		if (!read_uint(&a, &ch2))
 			return 0;
-	} else if (c == '.') {
-		/* 2.5 */
-		/* must be looking at '.5'
-		 * check and consume this string.
-		 */
-		chspec_bw = WL_CHANSPEC_BW_2P5;
-
-		a ++; /* consume the char '.' */
-
-		/* consume the '5' string */
-		if (*a++ != '5') {
-			return 0;
-		}
 	}
 
 done_read:
@@ -500,9 +557,9 @@
 		return 0;
 
 	/* Now have all the chanspec string parts read;
-	 * chspec_band, ctl_ch, chspec_bw, sb_ul, ch1, ch2.
+	 * chspec_band, pri_ch, chspec_bw, sb_ul, ch1, ch2.
 	 * chspec_band and chspec_bw are chanspec values.
-	 * Need to convert ctl_ch, sb_ul, and ch1,ch2 into
+	 * Need to convert pri_ch, sb_ul, and ch1,ch2 into
 	 * a center channel (or two) and sideband.
 	 */
 
@@ -511,23 +568,23 @@
 	 */
 	if (sb_ul != '\0') {
 		if (sb_ul == 'l') {
-			chspec_ch = UPPER_20_SB(ctl_ch);
+			chspec_ch = UPPER_20_SB(pri_ch);
 			chspec_sb = WL_CHANSPEC_CTL_SB_LLL;
 		} else if (sb_ul == 'u') {
-			chspec_ch = LOWER_20_SB(ctl_ch);
+			chspec_ch = LOWER_20_SB(pri_ch);
 			chspec_sb = WL_CHANSPEC_CTL_SB_LLU;
 		}
 	}
 	/* if the bw is 20, center and sideband are trivial */
-	else if (BW_LE20(chspec_bw)) {
-		chspec_ch = ctl_ch;
+	else if (chspec_bw == WL_CHANSPEC_BW_20) {
+		chspec_ch = pri_ch;
 		chspec_sb = WL_CHANSPEC_CTL_SB_NONE;
 	}
 	/* if the bw is 40/80/160, not 80+80, a single method
 	 * can be used to to find the center and sideband
 	 */
 	else if (chspec_bw != WL_CHANSPEC_BW_8080) {
-		/* figure out ctl sideband based on ctl channel and bandwidth */
+		/* figure out primary20 sideband based on primary20 channel and bandwidth */
 		const uint8 *center_ch = NULL;
 		int num_ch = 0;
 		int sb = -1;
@@ -546,10 +603,10 @@
 		}
 
 		for (i = 0; i < num_ch; i ++) {
-			sb = channel_to_sb(center_ch[i], ctl_ch, bw);
+			sb = channel_to_sb(center_ch[i], pri_ch, bw);
 			if (sb >= 0) {
 				chspec_ch = center_ch[i];
-				chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT;
+				chspec_sb = (uint)(sb << WL_CHANSPEC_CTL_SB_SHIFT);
 				break;
 			}
 		}
@@ -579,16 +636,16 @@
 		/* figure out primary 20 MHz sideband */
 
 		/* is the primary channel contained in the 1st 80MHz channel? */
-		sb = channel_to_sb(ch1, ctl_ch, bw);
+		sb = channel_to_sb(ch1, pri_ch, bw);
 		if (sb < 0) {
-			/* no match for primary channel 'ctl_ch' in segment0 80MHz channel */
+			/* no match for primary channel 'pri_ch' in segment0 80MHz channel */
 			return 0;
 		}
 
-		chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT;
+		chspec_sb = (uint)(sb << WL_CHANSPEC_CTL_SB_SHIFT);
 	}
 
-	chspec = (chspec_ch | chspec_band | chspec_bw | chspec_sb);
+	chspec = (chanspec_t)(chspec_ch | chspec_band | chspec_bw | chspec_sb);
 
 	if (wf_chspec_malformed(chspec))
 		return 0;
@@ -596,9 +653,18 @@
 	return chspec;
 }
 
+/* given a chanspec string, convert to a chanspec.
+ * On error return 0
+ */
+chanspec_t
+wf_chspec_aton(const char *a)
+{
+	return wf_chspec_aton_ex(a, WL_CHANSPEC_BW_20);
+}
+
 /*
  * Verify the chanspec is using a legal set of parameters, i.e. that the
- * chanspec specified a band, bw, ctl_sb and channel and that the
+ * chanspec specified a band, bw, pri_sb and channel and that the
  * combination could be legal given any set of circumstances.
  * RETURNS: TRUE is the chanspec is malformed, false if it looks good.
  */
@@ -608,10 +674,9 @@
 	uint chspec_bw = CHSPEC_BW(chanspec);
 	uint chspec_ch = CHSPEC_CHANNEL(chanspec);
 
-	/* must be 2G or 5G band */
 	if (CHSPEC_IS2G(chanspec)) {
-		/* must be valid bandwidth */
-		if (!BW_LE40(chspec_bw)) {
+		/* must be valid bandwidth and channel */
+		if (!BW_LE40(chspec_bw) || (chspec_ch > CH_MAX_2G_CHANNEL)) {
 			return TRUE;
 		}
 	} else if (CHSPEC_IS5G(chanspec)) {
@@ -624,7 +689,29 @@
 			if (ch1_id >= WF_NUM_5G_80M_CHANS || ch2_id >= WF_NUM_5G_80M_CHANS)
 				return TRUE;
 
-		} else if (BW_LE160(chspec_bw)) {
+		} else if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40 ||
+		           chspec_bw == WL_CHANSPEC_BW_80 || chspec_bw == WL_CHANSPEC_BW_160) {
+
+			if (chspec_ch > MAXCHANNEL) {
+				return TRUE;
+			}
+		} else {
+			/* invalid bandwidth */
+			return TRUE;
+		}
+	} else if (CHSPEC_IS6G(chanspec)) {
+		if (chspec_bw == WL_CHANSPEC_BW_8080) {
+			uint ch1_id, ch2_id;
+
+			/* channel IDs in 80+80 must be in range */
+			ch1_id = CHSPEC_CHAN1(chanspec);
+			ch2_id = CHSPEC_CHAN2(chanspec);
+			if (ch1_id >= WF_NUM_6G_80M_CHANS || ch2_id >= WF_NUM_6G_80M_CHANS)
+				return TRUE;
+
+		} else if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40 ||
+		           chspec_bw == WL_CHANSPEC_BW_80 || chspec_bw == WL_CHANSPEC_BW_160) {
+
 			if (chspec_ch > MAXCHANNEL) {
 				return TRUE;
 			}
@@ -633,12 +720,13 @@
 			return TRUE;
 		}
 	} else {
-		/* must be 2G or 5G band */
+
+		/* must be 2G, 5G or 6G band */
 		return TRUE;
 	}
 
 	/* side band needs to be consistent with bandwidth */
-	if (BW_LE20(chspec_bw)) {
+	if (chspec_bw == WL_CHANSPEC_BW_20) {
 		if (CHSPEC_CTL_SB(chanspec) != WL_CHANSPEC_CTL_SB_LLL)
 			return TRUE;
 	} else if (chspec_bw == WL_CHANSPEC_BW_40) {
@@ -646,6 +734,9 @@
 			return TRUE;
 	} else if (chspec_bw == WL_CHANSPEC_BW_80 ||
 	           chspec_bw == WL_CHANSPEC_BW_8080) {
+		/* both 80MHz and 80+80MHz use 80MHz side bands.
+		 * 80+80 SB info is relative to the primary 80MHz sub-band.
+		 */
 		if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LUU)
 			return TRUE;
 	}
@@ -670,7 +761,7 @@
 
 	if (CHSPEC_IS2G(chanspec)) {
 		/* must be valid bandwidth and channel range */
-		if (BW_LE20(chspec_bw)) {
+		if (chspec_bw == WL_CHANSPEC_BW_20) {
 			if (chspec_ch >= 1 && chspec_ch <= 14)
 				return TRUE;
 		} else if (chspec_bw == WL_CHANSPEC_BW_40) {
@@ -692,7 +783,7 @@
 			const uint8 *center_ch;
 			uint num_ch, i;
 
-			if (BW_LE40(chspec_bw)) {
+			if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40) {
 				center_ch = wf_5g_40m_chans;
 				num_ch = WF_NUM_5G_40M_CHANS;
 			} else if (chspec_bw == WL_CHANSPEC_BW_80) {
@@ -707,7 +798,7 @@
 			}
 
 			/* check for a valid center channel */
-			if (BW_LE20(chspec_bw)) {
+			if (chspec_bw == WL_CHANSPEC_BW_20) {
 				/* We don't have an array of legal 20MHz 5G channels, but they are
 				 * each side of the legal 40MHz channels.  Check the chanspec
 				 * channel against either side of the 40MHz channels.
@@ -749,12 +840,66 @@
 }
 
 /*
- * This function returns the channel number that control traffic is being sent on, for 20MHz
- * channels this is just the channel number, for 40MHZ, 80MHz, 160MHz channels it is the 20MHZ
- * sideband depending on the chanspec selected
+ * This function returns TRUE if both the chanspec can co-exist in PHY.
+ * Addition to primary20 channel, the function checks for side band for 2g 40 channels
+ */
+bool
+wf_chspec_coexist(chanspec_t chspec1, chanspec_t chspec2)
+{
+	bool same_primary;
+
+	same_primary = (wf_chspec_primary20_chan(chspec1) == wf_chspec_primary20_chan(chspec2));
+
+	if (same_primary && CHSPEC_IS2G(chspec1)) {
+	    if (CHSPEC_IS40(chspec1) && CHSPEC_IS40(chspec2)) {
+	        return (CHSPEC_CTL_SB(chspec1) == CHSPEC_CTL_SB(chspec2));
+	    }
+	}
+	return same_primary;
+}
+
+/**
+ * Create a 20MHz chanspec for the given band.
+ *
+ * This function returns a 20MHz chanspec in the given band.
+ *
+ * @param	channel   20MHz channel number
+ * @param	band      a chanspec band (e.g. WL_CHANSPEC_BAND_2G)
+ *
+ * @return Returns a 20MHz chanspec, or IVNCHANSPEC in case of error.
+ */
+chanspec_t
+wf_create_20MHz_chspec(uint channel, chanspec_band_t band)
+{
+	chanspec_t chspec;
+
+	if (channel <= WL_CHANSPEC_CHAN_MASK &&
+	    (band == WL_CHANSPEC_BAND_2G ||
+	     band == WL_CHANSPEC_BAND_5G)) {
+		chspec = band | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE | channel;
+		if (!wf_chspec_valid(chspec)) {
+			chspec = INVCHANSPEC;
+		}
+	} else {
+		chspec = INVCHANSPEC;
+	}
+
+	return chspec;
+}
+
+/**
+ * Return the primary 20MHz channel.
+ *
+ * This function returns the channel number of the primary 20MHz channel. For
+ * 20MHz channels this is just the channel number. For 40MHz or wider channels
+ * it is the primary 20MHz channel specified by the chanspec.
+ *
+ * @param	chspec    input chanspec
+ *
+ * @return Returns the channel number of the primary 20MHz channel
  */
 uint8
-wf_chspec_ctlchan(chanspec_t chspec)
+wf_chspec_primary20_chan(chanspec_t chspec)
 {
 	uint center_chan;
 	uint bw_mhz;
@@ -763,7 +908,7 @@
 	ASSERT(!wf_chspec_malformed(chspec));
 
 	/* Is there a sideband ? */
-	if (CHSPEC_BW_LE20(chspec)) {
+	if (CHSPEC_IS20(chspec)) {
 		return CHSPEC_CHANNEL(chspec);
 	} else {
 		sb = CHSPEC_CTL_SB(chspec) >> WL_CHANSPEC_CTL_SB_SHIFT;
@@ -780,46 +925,46 @@
 			center_chan = wf_5g_80m_chans[chan_id];
 		}
 		else {
-			bw_mhz = bw_chspec_to_mhz(chspec);
+			bw_mhz = wf_bw_chspec_to_mhz(chspec);
 			center_chan = CHSPEC_CHANNEL(chspec) >> WL_CHANSPEC_CHAN_SHIFT;
 		}
 
-		return (channel_to_ctl_chan(center_chan, bw_mhz, sb));
+		return (channel_to_primary20_chan(center_chan, bw_mhz, sb));
 	}
 }
 
 /* given a chanspec, return the bandwidth string */
-char *
-wf_chspec_to_bw_str(chanspec_t chspec)
+const char *
+BCMRAMFN(wf_chspec_to_bw_str)(chanspec_t chspec)
 {
-		return (char *)wf_chspec_bw_str[(CHSPEC_BW(chspec) >> WL_CHANSPEC_BW_SHIFT)];
+	return wf_chspec_bw_str[(CHSPEC_BW(chspec) >> WL_CHANSPEC_BW_SHIFT)];
 }
 
 /*
- * This function returns the chanspec of the control channel of a given chanspec
+ * Return the primary 20MHz chanspec of the given chanspec
  */
 chanspec_t
-wf_chspec_ctlchspec(chanspec_t chspec)
+wf_chspec_primary20_chspec(chanspec_t chspec)
 {
-	chanspec_t ctl_chspec = chspec;
-	uint8 ctl_chan;
+	chanspec_t pri_chspec = chspec;
+	uint8 pri_chan;
 
 	ASSERT(!wf_chspec_malformed(chspec));
 
 	/* Is there a sideband ? */
-	if (!CHSPEC_BW_LE20(chspec)) {
-		ctl_chan = wf_chspec_ctlchan(chspec);
-		ctl_chspec = ctl_chan | WL_CHANSPEC_BW_20;
-		ctl_chspec |= CHSPEC_BAND(chspec);
+	if (!CHSPEC_IS20(chspec)) {
+		pri_chan = wf_chspec_primary20_chan(chspec);
+		pri_chspec = pri_chan | WL_CHANSPEC_BW_20;
+		pri_chspec |= CHSPEC_BAND(chspec);
 	}
-	return ctl_chspec;
+	return pri_chspec;
 }
 
-/* return chanspec given control channel and bandwidth
+/* return chanspec given primary 20MHz channel and bandwidth
  * return 0 on error
  */
 uint16
-wf_channel2chspec(uint ctl_ch, uint bw)
+wf_channel2chspec(uint pri_ch, uint bw)
 {
 	uint16 chspec;
 	const uint8 *center_ch = NULL;
@@ -827,7 +972,7 @@
 	int sb = -1;
 	int i = 0;
 
-	chspec = ((ctl_ch <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G);
+	chspec = ((pri_ch <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G);
 
 	chspec |= bw;
 
@@ -843,15 +988,15 @@
 		center_ch = wf_5g_160m_chans;
 		num_ch = WF_NUM_5G_160M_CHANS;
 		bw = 160;
-	} else if (BW_LE20(bw)) {
-		chspec |= ctl_ch;
+	} else if (bw == WL_CHANSPEC_BW_20) {
+		chspec |= pri_ch;
 		return chspec;
 	} else {
 		return 0;
 	}
 
 	for (i = 0; i < num_ch; i ++) {
-		sb = channel_to_sb(center_ch[i], ctl_ch, bw);
+		sb = channel_to_sb(center_ch[i], pri_ch, bw);
 		if (sb >= 0) {
 			chspec |= center_ch[i];
 			chspec |= (sb << WL_CHANSPEC_CTL_SB_SHIFT);
@@ -868,9 +1013,9 @@
 }
 
 /*
- * This function returns the chanspec for the primary 40MHz of an 80MHz channel.
- * The control sideband specifies the same 20MHz channel that the 80MHz channel is using
- * as the primary 20MHz channel.
+ * This function returns the chanspec for the primary 40MHz of an 80MHz or wider channel.
+ * The primary 20MHz channel of the returned 40MHz chanspec is the same as the primary 20MHz
+ * channel of the input chanspec.
  */
 extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec)
 {
@@ -902,7 +1047,7 @@
 		}
 
 		/* Create primary 40MHz chanspec */
-		chspec40 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_40 |
+		chspec40 = (chanspec_t)(WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_40 |
 		            sb | center_chan);
 	}
 
@@ -926,7 +1071,7 @@
  * frequency is not a 2.4 GHz channel, or if the frequency is not and even
  * multiple of 5 MHz from the base frequency to the base plus 1 GHz.
  *
- * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
+ * Reference 802.11-2016, section 17.3.8.3 and section 16.3.6.3
  */
 int
 wf_mhz2channel(uint freq, uint start_factor)
@@ -952,7 +1097,7 @@
 	if ((freq < base) || (freq > base + 1000))
 		return -1;
 
-	offset = freq - base;
+	offset = (int)(freq - base);
 	ch = offset / 5;
 
 	/* check that frequency is a 5MHz multiple from the base */
@@ -980,7 +1125,7 @@
  * the answer is rounded down to an integral MHz.
  * -1 is returned for an out of range channel.
  *
- * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
+ * Reference 802.11-2016, section 17.3.8.3 and section 16.3.6.3
  */
 int
 wf_channel2mhz(uint ch, uint start_factor)
@@ -993,7 +1138,7 @@
 	else if ((start_factor == WF_CHAN_FACTOR_2_4_G) && (ch == 14))
 		freq = 2484;
 	else
-		freq = ch * 5 + start_factor / 2;
+		freq = (int)(ch * 5 + start_factor / 2);
 
 	return freq;
 }
@@ -1026,7 +1171,7 @@
 
 	for (i = 0; i < WF_NUM_SIDEBANDS_80MHZ; i++) {
 		chanspec_cur = CH80MHZ_CHSPEC(center_channel, sidebands[i]);
-		if (primary_channel == wf_chspec_ctlchan(chanspec_cur)) {
+		if (primary_channel == wf_chspec_primary20_chan(chanspec_cur)) {
 			chanspec = chanspec_cur;
 			break;
 		}
@@ -1051,7 +1196,7 @@
  *
  * Returns INVCHANSPEC in case of error.
  *
- * Refer to IEEE802.11ac section 22.3.14 "Channelization".
+ * Refer to 802.11-2016 section 22.3.14 "Channelization".
  */
 chanspec_t
 wf_chspec_get8080_chspec(uint8 primary_20mhz, uint8 chan0, uint8 chan1)
@@ -1078,7 +1223,7 @@
 		/* no, so does the primary channel fit with the 2nd 80MHz channel ? */
 		sb = channel_to_sb(chan1, primary_20mhz, 80);
 		if (sb < 0) {
-			/* no match for ctl_ch to either 80MHz center channel */
+			/* no match for pri_ch to either 80MHz center channel */
 			return INVCHANSPEC;
 		}
 		/* swapped, so chan1 is frequency segment 0, and chan0 is seg 1 */
@@ -1086,7 +1231,7 @@
 		seg1 = chan0_id;
 	}
 
-	chanspec = ((seg0 << WL_CHANSPEC_CHAN1_SHIFT) |
+	chanspec = (uint16)((seg0 << WL_CHANSPEC_CHAN1_SHIFT) |
 	            (seg1 << WL_CHANSPEC_CHAN2_SHIFT) |
 	            (sb << WL_CHANSPEC_CTL_SB_SHIFT) |
 	            WL_CHANSPEC_BW_8080 |
@@ -1108,93 +1253,47 @@
 }
 
 /*
- * Returns the primary 80 Mhz channel for the provided chanspec
- *
- *    chanspec - Input chanspec for which the 80MHz primary channel has to be retrieved
- *
- *  returns -1 in case the provided channel is 20/40 Mhz chanspec
+ * Returns the center channel of the primary 80 MHz sub-band of the provided chanspec
  */
-
 uint8
 wf_chspec_primary80_channel(chanspec_t chanspec)
 {
+	chanspec_t primary80_chspec;
 	uint8 primary80_chan;
 
-	if (CHSPEC_IS80(chanspec))	{
-		primary80_chan = CHSPEC_CHANNEL(chanspec);
-	}
-	else if (CHSPEC_IS8080(chanspec)) {
-		/* Channel ID 1 corresponds to frequency segment 0, the primary 80 MHz segment */
-		primary80_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chanspec));
-	}
-	else if (CHSPEC_IS160(chanspec)) {
-		uint8 center_chan = CHSPEC_CHANNEL(chanspec);
-		uint sb = CHSPEC_CTL_SB(chanspec) >> WL_CHANSPEC_CTL_SB_SHIFT;
+	primary80_chspec = wf_chspec_primary80_chspec(chanspec);
 
-		/* based on the sb value primary 80 channel can be retrieved
-		 * if sb is in range 0 to 3 the lower band is the 80Mhz primary band
-		 */
-		if (sb < 4) {
-			primary80_chan = center_chan - CH_40MHZ_APART;
-		}
-		/* if sb is in range 4 to 7 the upper band is the 80Mhz primary band */
-		else
-		{
-			primary80_chan = center_chan + CH_40MHZ_APART;
-		}
+	if (primary80_chspec == INVCHANSPEC) {
+		primary80_chan = INVCHANNEL;
+	} else {
+		primary80_chan = CHSPEC_CHANNEL(primary80_chspec);
 	}
-	else {
-		/* for 20 and 40 Mhz */
-		primary80_chan = -1;
-	}
+
 	return primary80_chan;
 }
 
 /*
- * Returns the secondary 80 Mhz channel for the provided chanspec
- *
- *    chanspec - Input chanspec for which the 80MHz secondary channel has to be retrieved
- *
- *  returns -1 in case the provided channel is 20/40/80 Mhz chanspec
+ * Returns the center channel of the secondary 80 MHz sub-band of the provided chanspec
  */
 uint8
 wf_chspec_secondary80_channel(chanspec_t chanspec)
 {
+	chanspec_t secondary80_chspec;
 	uint8 secondary80_chan;
 
-	if (CHSPEC_IS8080(chanspec)) {
-		secondary80_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chanspec));
-	}
-	else if (CHSPEC_IS160(chanspec)) {
-		uint8 center_chan = CHSPEC_CHANNEL(chanspec);
-		uint sb = CHSPEC_CTL_SB(chanspec) >> WL_CHANSPEC_CTL_SB_SHIFT;
+	secondary80_chspec = wf_chspec_secondary80_chspec(chanspec);
 
-		/* based on the sb value  secondary 80 channel can be retrieved
-		 * if sb is in range 0 to 3 upper band is the secondary 80Mhz band
-		 */
-		if (sb < 4) {
-			secondary80_chan = center_chan + CH_40MHZ_APART;
-		}
-		/* if sb is in range 4 to 7 the lower band is the secondary 80Mhz band */
-		else
-		{
-			secondary80_chan = center_chan - CH_40MHZ_APART;
-		}
+	if (secondary80_chspec == INVCHANSPEC) {
+		secondary80_chan = INVCHANNEL;
+	} else {
+		secondary80_chan = CHSPEC_CHANNEL(secondary80_chspec);
 	}
-	else {
-		/* for 20, 40, and 80 Mhz */
-		secondary80_chan = -1;
-	}
+
 	return secondary80_chan;
 }
 
 /*
- * This function returns the chanspec for the primary 80MHz of an 160MHz or 80+80 channel.
- *
- *    chanspec - Input chanspec for which the primary 80Mhz chanspec has to be retreived
- *
- *  returns the input chanspec in case the provided chanspec is an 80 MHz chanspec
- *  returns INVCHANSPEC in case the provided channel is 20/40 MHz chanspec
+ * Returns the chanspec for the primary 80MHz sub-band of an 160MHz or 80+80 channel
  */
 chanspec_t
 wf_chspec_primary80_chspec(chanspec_t chspec)
@@ -1204,18 +1303,18 @@
 	uint sb;
 
 	ASSERT(!wf_chspec_malformed(chspec));
+
 	if (CHSPEC_IS80(chspec)) {
 		chspec80 = chspec;
 	}
 	else if (CHSPEC_IS8080(chspec)) {
-
-		/* Channel ID 1 corresponds to frequency segment 0, the primary 80 MHz segment */
-		center_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chspec));
-
 		sb = CHSPEC_CTL_SB(chspec);
 
+		/* primary sub-band is stored in seg0 */
+		center_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chspec));
+
 		/* Create primary 80MHz chanspec */
-		chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan);
+		chspec80 = (chanspec_t)(WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan);
 	}
 	else if (CHSPEC_IS160(chspec)) {
 		center_chan = CHSPEC_CHANNEL(chspec);
@@ -1230,14 +1329,88 @@
 			center_chan += CH_40MHZ_APART;
 			sb -= WL_CHANSPEC_CTL_SB_ULL;
 		}
+
 		/* Create primary 80MHz chanspec */
-		chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan);
+		chspec80 = (chanspec_t)(WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan);
 	}
 	else {
 		chspec80 = INVCHANSPEC;
 	}
 
 	return chspec80;
+}
+
+/*
+ * Returns the chanspec for the secondary 80MHz sub-band of an 160MHz or 80+80 channel
+ */
+chanspec_t
+wf_chspec_secondary80_chspec(chanspec_t chspec)
+{
+	chanspec_t chspec80;
+	uint center_chan;
+
+	ASSERT(!wf_chspec_malformed(chspec));
+
+	if (CHSPEC_IS8080(chspec)) {
+		/* secondary sub-band is stored in seg1 */
+		center_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chspec));
+
+		/* Create secondary 80MHz chanspec */
+		chspec80 = (chanspec_t)(WL_CHANSPEC_BAND_5G |
+		            WL_CHANSPEC_BW_80 |
+		            WL_CHANSPEC_CTL_SB_LL |
+		            center_chan);
+	}
+	else if (CHSPEC_IS160(chspec)) {
+		center_chan = CHSPEC_CHANNEL(chspec);
+
+		if (CHSPEC_CTL_SB(chspec) < WL_CHANSPEC_CTL_SB_ULL) {
+			/* Primary 80MHz is on lower side */
+			center_chan -= CH_40MHZ_APART;
+		}
+		else {
+			/* Primary 80MHz is on upper side */
+			center_chan += CH_40MHZ_APART;
+		}
+
+		/* Create secondary 80MHz chanspec */
+		chspec80 = (chanspec_t)(WL_CHANSPEC_BAND_5G |
+		            WL_CHANSPEC_BW_80 |
+		            WL_CHANSPEC_CTL_SB_LL |
+		            center_chan);
+	}
+	else {
+		chspec80 = INVCHANSPEC;
+	}
+
+	return chspec80;
+}
+
+/*
+ * For 160MHz or 80P80 chanspec, set ch[0]/ch[1] to be the low/high 80 Mhz channels
+ *
+ * For 20/40/80MHz chanspec, set ch[0] to be the center freq, and chan[1]=-1
+ */
+void
+wf_chspec_get_80p80_channels(chanspec_t chspec, uint8 *ch)
+{
+
+	if (CHSPEC_IS8080(chspec)) {
+		ch[0] = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chspec));
+		ch[1] = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chspec));
+	}
+	else if (CHSPEC_IS160(chspec)) {
+		uint8 center_chan = CHSPEC_CHANNEL(chspec);
+		ch[0] = center_chan - CH_40MHZ_APART;
+		ch[1] = center_chan + CH_40MHZ_APART;
+	}
+	else {
+		/* for 20, 40, and 80 Mhz */
+		ch[0] = CHSPEC_CHANNEL(chspec);
+		ch[1] = 0xFFu;
+	}
+	return;
+
 }
 
 #ifdef WL11AC_80P80
@@ -1253,40 +1426,130 @@
 }
 #endif /* WL11AC_80P80 */
 
-#ifdef WL_OLDPPR
-/* given a chanspec and a string buffer, format the chanspec as a
- * string, and return the original pointer a.
- * Min buffer length must be CHANSPEC_STR_LEN.
- * On error return NULL
+/* This routine returns the chanspec for a given operating class and
+ * channel number
  */
-char *
-wf_chspec_ntoa_old(chanspec_t chspec, char *buf)
+chanspec_t
+wf_channel_create_chspec_frm_opclass(uint8 opclass, uint8 channel)
 {
-	const char *band, *bw, *sb;
-	uint channel;
-
-	band = "";
-	bw = "";
-	sb = "";
-	channel = CHSPEC_CHANNEL_OLD(chspec);
-	/* check for non-default band spec */
-	if ((CHSPEC_IS2G_OLD(chspec) && channel > CH_MAX_2G_CHANNEL) ||
-	    (CHSPEC_IS5G_OLD(chspec) && channel <= CH_MAX_2G_CHANNEL))
-		band = (CHSPEC_IS2G_OLD(chspec)) ? "b" : "a";
-	if (CHSPEC_IS40_OLD(chspec)) {
-		if (CHSPEC_SB_UPPER_OLD(chspec)) {
-			sb = "u";
-			channel += CH_10MHZ_APART;
-		} else {
-			sb = "l";
-			channel -= CH_10MHZ_APART;
-		}
-	} else if (CHSPEC_IS10_OLD(chspec)) {
-		bw = "n";
+	chanspec_t chanspec = 0;
+	uint16 opclass_info = 0;
+	uint16 lookupindex = 0;
+	switch (opclass) {
+		case 115:
+			lookupindex = 1;
+			break;
+		case 124:
+			lookupindex = 3;
+			break;
+		case 125:
+			lookupindex = 5;
+			break;
+		case 81:
+			lookupindex = 12;
+			break;
+		case 116:
+			lookupindex = 22;
+			break;
+		case 119:
+			lookupindex = 23;
+			break;
+		case 126:
+			lookupindex = 25;
+			break;
+		case 83:
+			lookupindex = 32;
+			break;
+		case 84:
+			lookupindex = 33;
+			break;
+		default:
+			lookupindex = 12;
 	}
 
-	/* Outputs a max of 6 chars including '\0'  */
-	snprintf(buf, 6, "%d%s%s%s", channel, band, bw, sb);
-	return (buf);
+	if (lookupindex < 33) {
+		opclass_info = opclass_data[lookupindex-1];
+	}
+	else {
+		opclass_info = opclass_data[11];
+	}
+	chanspec = opclass_info | (uint16)channel;
+	return chanspec;
 }
-#endif /* WL_OLDPPR */
+
+/* This routine returns the opclass for a given chanspec */
+int
+wf_channel_create_opclass_frm_chspec(chanspec_t chspec)
+{
+	BCM_REFERENCE(chspec);
+	/* TODO: Implement this function ! */
+	return 12; /* opclass 12 for basic 2G channels */
+}
+
+/* Populates array with all 20MHz side bands of a given chanspec_t in the following order:
+ *		primary20, secondary20, two secondary40s, four secondary80s.
+ *    'chspec' is the chanspec of interest
+ *    'pext' must point to an uint8 array of long enough to hold all side bands of the given chspec
+ *
+ * Works with 20, 40, 80, 80p80 and 160MHz chspec
+ */
+void
+wf_get_all_ext(chanspec_t chspec, uint8 *pext)
+{
+#ifdef WL11N_20MHZONLY
+	GET_ALL_SB(chspec, pext);
+#else /* !WL11N_20MHZONLY */
+	chanspec_t t = (CHSPEC_IS160(chspec) || CHSPEC_IS8080(chspec)) ? /* if bw > 80MHz */
+	wf_chspec_primary80_chspec(chspec) : (chspec); /* extract primary 80 */
+	/* primary20 channel as first element */
+	uint8 pri_ch = (pext)[0] = wf_chspec_primary20_chan(t);
+	if (CHSPEC_IS20(chspec)) return; /* nothing more to do since 20MHz chspec */
+	/* 20MHz EXT */
+	(pext)[1] = pri_ch + (uint8)(IS_CTL_IN_L20(t) ? CH_20MHZ_APART : -CH_20MHZ_APART);
+	if (CHSPEC_IS40(chspec)) return; /* nothing more to do since 40MHz chspec */
+	/* center 40MHz EXT */
+	t = wf_channel2chspec((uint)(pri_ch + (IS_CTL_IN_L40(chspec) ?
+		CH_40MHZ_APART : -CH_40MHZ_APART)), WL_CHANSPEC_BW_40);
+	GET_ALL_SB(t, &((pext)[2])); /* get the 20MHz side bands in 40MHz EXT */
+	if (CHSPEC_IS80(chspec)) return; /* nothing more to do since 80MHz chspec */
+	t = CH80MHZ_CHSPEC(wf_chspec_secondary80_channel(chspec), WL_CHANSPEC_CTL_SB_LLL);
+	/* get the 20MHz side bands in 80MHz EXT (secondary) */
+	GET_ALL_SB(t, &((pext)[4]));
+#endif /* !WL11N_20MHZONLY */
+}
+
+/*
+ * Given two chanspecs, returns true if they overlap.
+ * (Overlap: At least one 20MHz subband is common between the two chanspecs provided)
+ */
+bool wf_chspec_overlap(chanspec_t chspec0, chanspec_t chspec1)
+{
+	uint8 ch0, ch1;
+
+	FOREACH_20_SB(chspec0, ch0) {
+		FOREACH_20_SB(chspec1, ch1) {
+			if (ABS(ch0 - ch1) < CH_20MHZ_APART) {
+				return TRUE;
+			}
+		}
+	}
+
+	return FALSE;
+}
+
+uint8
+channel_bw_to_width(chanspec_t chspec)
+{
+	uint8 channel_width;
+
+	if (CHSPEC_IS80(chspec))
+		channel_width = VHT_OP_CHAN_WIDTH_80;
+	else if (CHSPEC_IS160(chspec))
+		channel_width = VHT_OP_CHAN_WIDTH_160;
+	else if (CHSPEC_IS8080(chspec))
+		channel_width = VHT_OP_CHAN_WIDTH_80_80;
+	else
+		channel_width = VHT_OP_CHAN_WIDTH_20_40;
+
+	return channel_width;
+}

--
Gitblit v1.6.2