linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/12] Additional support for 802.11ah (S1G)
@ 2022-07-11  1:08 Kieran Frewen
  2022-07-11  1:08 ` [PATCH 01/12] cfg80211: regulatory: extend regulatory support for S1G Kieran Frewen
                   ` (11 more replies)
  0 siblings, 12 replies; 19+ messages in thread
From: Kieran Frewen @ 2022-07-11  1:08 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Kieran Frewen

This patchset builds on the work down by Thomas Pedersen to add further
support for 802.11ah in cfg80211 and mac80211. The ultimate goal is
to enable the successful starting of an AP on 802.11ah using 802.11ah
terms by implementing the various features that are required by the
AP. The features are split into their own commits, please see those
patches for more details.

The patchset has been tested on both real hardware (Morse Micro MM610x)
and mac80211_hwsim, in AP and STA modes. Basic regression testing was
performed on 802.11n with mac80211_hwsim by starting an AP and having a
STA interface connect to it.

802.11ah features/support missing:
 - Rate control integration
 - Regulatory database updates (only US regulatory information exists)
 - Optional 802.11ah (S1G) features such as RAW, TWT and AID grouping

Kieran Frewen (12):
  cfg80211: regulatory: extend regulatory support for S1G
  mac80211: update TIM for S1G specification changes
  mac80211: S1G beacon/short beacon support
  nl80211: support setting S1G short beacon period
  nl80211: support advertising S1G capabilities
  mac80211: support ieee80211_ext format
  mac80211: S1G capabilities information element in probe request
  cfg80211: S1G rate flags
  nl80211: support advertising S1G rate information
  mac80211: support S1G rate encoding.
  cfg80211: support for calculating S1G bitrates
  mac80211_hwsim: support for S1G rate information

 drivers/net/wireless/mac80211_hwsim.c |  40 +++-
 include/net/cfg80211.h                |  16 +-
 include/net/mac80211.h                |  33 ++-
 include/uapi/linux/nl80211.h          |  27 +++
 net/mac80211/cfg.c                    |  43 +++-
 net/mac80211/ieee80211_i.h            |   1 +
 net/mac80211/rx.c                     |  32 ++-
 net/mac80211/sta_info.c               |   7 +
 net/mac80211/sta_info.h               |   7 +
 net/mac80211/tx.c                     |  27 ++-
 net/mac80211/util.c                   |  67 +++++-
 net/wireless/nl80211.c                |  37 ++++
 net/wireless/reg.c                    |  50 +++--
 net/wireless/reg_s1g.h                | 281 ++++++++++++++++++++++++++
 net/wireless/util.c                   | 144 ++++++++++++-
 15 files changed, 758 insertions(+), 54 deletions(-)
 create mode 100644 net/wireless/reg_s1g.h

-- 
2.25.1


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 01/12] cfg80211: regulatory: extend regulatory support for S1G
  2022-07-11  1:08 [PATCH 00/12] Additional support for 802.11ah (S1G) Kieran Frewen
@ 2022-07-11  1:08 ` Kieran Frewen
  2022-07-11 17:47   ` Jeff Johnson
  2022-07-11  1:08 ` [PATCH 02/12] mac80211: update TIM for S1G specification changes Kieran Frewen
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 19+ messages in thread
From: Kieran Frewen @ 2022-07-11  1:08 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Kieran Frewen, Bassem Dawood

Extend the S1G regulatory information to support all regulatory
domains. An reg_s1g.h file is included containing structs with key
regulatory class information. These structs were required to ensure
the right combination of information was available to a series of
functions which support the mapping between frequencies, bandwidths,
and channels.

Signed-off-by: Kieran Frewen <kieran.frewen@morsemicro.com>
Signed-off-by: Bassem Dawood <bassem@morsemicro.com>
---
 net/wireless/reg.c     |  50 ++++++--
 net/wireless/reg_s1g.h | 281 +++++++++++++++++++++++++++++++++++++++++
 net/wireless/util.c    |  31 ++++-
 3 files changed, 349 insertions(+), 13 deletions(-)
 create mode 100644 net/wireless/reg_s1g.h

diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index c7383ede794f..d9ed6b619164 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -62,6 +62,7 @@
 #include "reg.h"
 #include "rdev-ops.h"
 #include "nl80211.h"
+#include "reg_s1g.h"
 
 /*
  * Grace period we give before making sure all current interfaces reside on
@@ -1737,26 +1738,44 @@ static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd
 		 * the largest bandwidth which cleanly divides the freq_range.
 		 */
 		int edge_offset;
-		int ch_bw = max_bandwidth_khz;
+		int ch_bw, freq_end, freq_start, class_idx;
+		unsigned int i;
+		const struct s1g_oper_class *oper = reg_s1g_get_oper_class(regd->alpha2);
+
+		for (i = 0; i < oper->class_count; i++) {
+			if (center_freq_khz >= oper->class[i].start_freq &&
+			    center_freq_khz <= oper->class[i].end_freq) {
+				class_idx = i;
+				break;
+			}
+		}
+
+		ch_bw = oper->class[class_idx].max_bw_khz;
+		freq_start = oper->class[class_idx].start_freq;
+		freq_end = oper->class[class_idx].end_freq;
 
 		while (ch_bw) {
-			edge_offset = (center_freq_khz - ch_bw / 2) -
-				      freq_range->start_freq_khz;
-			if (edge_offset % ch_bw == 0) {
-				switch (KHZ_TO_MHZ(ch_bw)) {
-				case 1:
+			if (oper->class[class_idx].align_to_end)
+				edge_offset = freq_end -
+					(center_freq_khz - (ch_bw) / 2);
+			else
+				edge_offset = (center_freq_khz - (ch_bw) / 2) -
+					freq_start;
+			if (edge_offset % (ch_bw) == 0) {
+				switch (ch_bw) {
+				case MHZ_TO_KHZ(1):
 					bw_flags |= IEEE80211_CHAN_1MHZ;
 					break;
-				case 2:
+				case MHZ_TO_KHZ(2):
 					bw_flags |= IEEE80211_CHAN_2MHZ;
 					break;
-				case 4:
+				case MHZ_TO_KHZ(4):
 					bw_flags |= IEEE80211_CHAN_4MHZ;
 					break;
-				case 8:
+				case MHZ_TO_KHZ(8):
 					bw_flags |= IEEE80211_CHAN_8MHZ;
 					break;
-				case 16:
+				case MHZ_TO_KHZ(16):
 					bw_flags |= IEEE80211_CHAN_16MHZ;
 					break;
 				default:
@@ -2555,9 +2574,16 @@ static void handle_channel_custom(struct wiphy *wiphy,
 	const struct ieee80211_reg_rule *reg_rule = NULL;
 	const struct ieee80211_power_rule *power_rule = NULL;
 	u32 bw, center_freq_khz;
+	bool is_s1g = chan->band == NL80211_BAND_S1GHZ;
 
-	center_freq_khz = ieee80211_channel_to_khz(chan);
-	for (bw = MHZ_TO_KHZ(20); bw >= min_bw; bw = bw / 2) {
+	if (is_s1g) {
+		bw = MHZ_TO_KHZ(16);
+		min_bw = MHZ_TO_KHZ(1);
+	} else {
+		bw = MHZ_TO_KHZ(20);
+	}
+
+	for (; bw >= min_bw; bw = bw / 2) {
 		reg_rule = freq_reg_info_regd(center_freq_khz, regd, bw);
 		if (!IS_ERR(reg_rule))
 			break;
diff --git a/net/wireless/reg_s1g.h b/net/wireless/reg_s1g.h
new file mode 100644
index 000000000000..69dd4e2cd4d3
--- /dev/null
+++ b/net/wireless/reg_s1g.h
@@ -0,0 +1,281 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NET_WIRELESS_REG_S1G_H
+#define __NET_WIRELESS_REG_S1G_H
+
+#include "reg.h"
+
+/**
+ * Struct cca_class
+ *
+ * The specifics of a cca level classification used to validate bw/frequency
+ *	combinations in a regulatory domain
+ * @band_start: The channel starting frequency for that CCA classification
+ * @start_freq: The start of the valid frequency range for the CCA
+ *	classification
+ * @end_freq: The end of the valid frequency range for the CCA classification
+ * @max_bw_khz: The maximum valid bw for the CCA classification
+ * @align_to_end: True if the maximum valid BW for the range is aligned to the
+ *	end_freq
+ * @supported_chan: A list of supported channel indexes
+ * @n_supported_chan: A count of the supported channels for this CCA
+ *	classification
+ */
+struct s1g_cca_classification {
+	u32 band_start;
+	u32 start_freq;
+	u32 end_freq;
+	u32 max_bw_khz;
+	u8 align_to_end;
+	const u8 *supported_chan;
+	u8 n_supported_chan;
+};
+
+
+/**
+
+ * Struct s1g_oper_class
+ *
+ * An aggregated view of the operating classes for a single regulatory
+ * domain
+ * @cc: country code
+ * @class_count: The number of CCA level classifications that exist
+ *	within that country
+ * @class: The specifics of a CCA level classification within a regulatory
+ *	domain.
+ */
+struct s1g_oper_class {
+	char *cc;
+	int class_count;
+	struct s1g_cca_classification class[];
+};
+
+/* The following channel lists have been retrieved from
+ * IEEE Std 802.11-2020 Table E-5
+ */
+static const u8 us_supported_channels[] = {
+	1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+	14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+	24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+	34, 35, 37, 38, 39, 40, 41, 42, 43, 44,
+	45, 46, 47, 48, 49, 50, 51
+};
+
+static const u8 eu_supported_channels_863[] = {
+	1, 3, 5, 7, 9
+};
+
+static const u8 eu_supported_channels_901_4[] = {
+	33, 35
+};
+
+static const u8 jp_supported_channels[] = {
+	1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21
+};
+
+static const u8 kr_supported_channels[] = {
+	1, 2, 3, 5, 6, 7, 8, 9, 10, 11
+};
+
+static const u8 sg_supported_channels_863[] = {
+	7, 9, 10, 11
+};
+
+static const u8 sg_supported_channels_902[] = {
+	37, 38, 39, 40, 41, 42, 43, 45
+};
+
+static const u8 au_nz_supported_channels[] = {
+	27, 29, 30, 31, 32, 33, 34, 35, 37, 38, 39,
+	40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+	51
+};
+
+
+/* The following s1g_oper_class structs are taken from
+ * IEEE Std 802.11-2020 Table E-5
+ */
+static const struct s1g_oper_class country_class_au = {
+	.cc = "AU",
+	.class_count = 2,
+	.class = {
+	{
+		.band_start = 902000,
+		.start_freq = 915000,
+		.end_freq = 920000,
+		.max_bw_khz = MHZ_TO_KHZ(4),
+		.align_to_end = 0,
+		.supported_chan = au_nz_supported_channels,
+		.n_supported_chan = sizeof(au_nz_supported_channels),
+	},
+	{
+		.band_start = 902000,
+		.start_freq = 920000,
+		.end_freq = 928000,
+		.max_bw_khz = MHZ_TO_KHZ(8),
+		.align_to_end = 1,
+		.supported_chan = NULL,
+		.n_supported_chan = 0,
+	}
+	},
+};
+
+static const struct s1g_oper_class country_class_nz = {
+	.cc = "NZ",
+	.class_count = 2,
+	.class = {
+	{
+		.band_start = 902000,
+		.start_freq = 915000,
+		.end_freq = 924000,
+		.max_bw_khz = MHZ_TO_KHZ(8),
+		.align_to_end = 0,
+		.supported_chan = au_nz_supported_channels,
+		.n_supported_chan = sizeof(au_nz_supported_channels),
+	},
+	{
+		.band_start = 902000,
+		.start_freq = 924000,
+		.end_freq = 928000,
+		.max_bw_khz = MHZ_TO_KHZ(8),
+		.align_to_end = 0,
+		.supported_chan = NULL,
+		.n_supported_chan = 0,
+	}
+	},
+};
+
+static const struct s1g_oper_class country_class_us = {
+	.cc = "US",
+	.class_count = 3,
+	.class = {
+	{
+		.band_start = 902000,
+		.start_freq = 902000,
+		.end_freq = 904000,
+		.max_bw_khz = MHZ_TO_KHZ(16),
+		.align_to_end = 0,
+		.supported_chan = us_supported_channels,
+		.n_supported_chan = sizeof(us_supported_channels),
+	},
+	{
+		.band_start = 902000,
+		.start_freq = 920000,
+		.end_freq = 928000,
+		.max_bw_khz = MHZ_TO_KHZ(16),
+		.align_to_end = 0,
+		.supported_chan = NULL,
+		.n_supported_chan = 0,
+	},
+	{
+		.band_start = 902000,
+		.start_freq = 904000,
+		.end_freq = 920000,
+		.max_bw_khz = MHZ_TO_KHZ(16),
+		.align_to_end = 0,
+		.supported_chan = NULL,
+		.n_supported_chan = 0,
+	}
+	},
+};
+
+static const struct s1g_oper_class country_class_sg = {
+	.cc = "SG",
+	.class_count = 2,
+	.class = {
+	{
+		.band_start = 863000,
+		.start_freq = 866000,
+		.end_freq = 869000,
+		.max_bw_khz = MHZ_TO_KHZ(2),
+		.align_to_end = 1,
+		.supported_chan = sg_supported_channels_863,
+		.n_supported_chan = sizeof(sg_supported_channels_863),
+	},
+	{
+		.band_start = 902000,
+		.start_freq = 920000,
+		.end_freq = 925000,
+		.max_bw_khz = MHZ_TO_KHZ(4),
+		.align_to_end = 0,
+		.supported_chan = sg_supported_channels_902,
+		.n_supported_chan = sizeof(sg_supported_channels_902),
+	},
+	},
+};
+
+static const struct s1g_oper_class country_class_kr = {
+	.cc = "KR",
+	.class_count = 1,
+	.class = {
+	{
+		.band_start = 917500,
+		.start_freq = 917500,
+		.end_freq = 923500,
+		.max_bw_khz = MHZ_TO_KHZ(4),
+		.align_to_end = 1,
+		.supported_chan = kr_supported_channels,
+		.n_supported_chan = sizeof(kr_supported_channels),
+	}
+	},
+};
+
+static const struct s1g_oper_class country_class_eu = {
+	.cc = "EU",
+	.class_count = 1,
+	.class = {
+	{
+		.band_start = 863000,
+		.start_freq = 863000,
+		.end_freq = 868000,
+		.max_bw_khz = MHZ_TO_KHZ(1),
+		.align_to_end = 0,
+		.supported_chan = eu_supported_channels_863,
+		.n_supported_chan = sizeof(eu_supported_channels_863),
+	},
+	{
+		.band_start = 901400,
+		.start_freq = 917400,
+		.end_freq = 919400,
+		.max_bw_khz = MHZ_TO_KHZ(1),
+		.align_to_end = 0,
+		.supported_chan = eu_supported_channels_901_4,
+		.n_supported_chan = sizeof(eu_supported_channels_901_4),
+	}
+	},
+};
+
+static const struct s1g_oper_class country_class_jp = {
+	.cc = "JP",
+	.class_count = 1,
+	.class = {
+	{
+		.band_start = 916500,
+		.start_freq = 916500,
+		.end_freq = 927500,
+		.max_bw_khz = MHZ_TO_KHZ(1),
+		.supported_chan = jp_supported_channels,
+		.n_supported_chan = sizeof(jp_supported_channels),
+	}
+	},
+};
+
+static const struct s1g_oper_class *reg_s1g_get_oper_class(const char *cc)
+{
+	if (!strcmp(cc, "EU"))
+		return &country_class_eu;
+	if (!strcmp(cc, "SG"))
+		return &country_class_sg;
+	if (!strcmp(cc, "US"))
+		return &country_class_us;
+	if (!strcmp(cc, "AU"))
+		return &country_class_au;
+	if (!strcmp(cc, "KR"))
+		return &country_class_kr;
+	if (!strcmp(cc, "JP"))
+		return &country_class_jp;
+	if (!strcmp(cc, "NZ"))
+		return &country_class_nz;
+	return &country_class_us;
+}
+
+#endif /*__NET_WIRELESS_REG_S1G_H */
diff --git a/net/wireless/util.c b/net/wireless/util.c
index b7257862e0fe..412403d29c22 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -22,6 +22,7 @@
 #include <linux/nospec.h>
 #include "core.h"
 #include "rdev-ops.h"
+#include "reg_s1g.h"
 
 
 const struct ieee80211_rate *
@@ -72,6 +73,23 @@ u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband,
 }
 EXPORT_SYMBOL(ieee80211_mandatory_rates);
 
+static u32 ieee80211_s1g_base_freq(int chan)
+{
+	const struct ieee80211_regdomain *regd  = rtnl_dereference(cfg80211_regdomain);
+	const struct s1g_oper_class *oper = reg_s1g_get_oper_class(regd->alpha2);
+	u8 i, j, index = 0;
+
+	if (oper->class_count > 1)
+		for (i = 0; i < oper->class_count; i++)
+			for (j = 0; j < oper->class[i].n_supported_chan; j++)
+				if (oper->class[i].supported_chan[j] == chan) {
+					index = i;
+					goto out;
+				}
+out:
+	return oper->class[index].band_start;
+}
+
 u32 ieee80211_channel_to_freq_khz(int chan, enum nl80211_band band)
 {
 	/* see 802.11 17.3.8.3.2 and Annex J
@@ -104,7 +122,7 @@ u32 ieee80211_channel_to_freq_khz(int chan, enum nl80211_band band)
 			return MHZ_TO_KHZ(56160 + chan * 2160);
 		break;
 	case NL80211_BAND_S1GHZ:
-		return 902000 + chan * 500;
+		return ieee80211_s1g_base_freq(chan) + chan * 500;
 	default:
 		;
 	}
@@ -112,6 +130,17 @@ u32 ieee80211_channel_to_freq_khz(int chan, enum nl80211_band band)
 }
 EXPORT_SYMBOL(ieee80211_channel_to_freq_khz);
 
+u32 ieee80211_s1g_channel_to_freq_khz(int chan)
+{
+	u32 base = ieee80211_s1g_base_freq(chan);
+
+	if (!base)
+		return 0;
+
+	return (base + chan * 500);
+}
+EXPORT_SYMBOL(ieee80211_s1g_channel_to_freq_khz);
+
 enum nl80211_chan_width
 ieee80211_s1g_channel_width(const struct ieee80211_channel *chan)
 {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 02/12] mac80211: update TIM for S1G specification changes
  2022-07-11  1:08 [PATCH 00/12] Additional support for 802.11ah (S1G) Kieran Frewen
  2022-07-11  1:08 ` [PATCH 01/12] cfg80211: regulatory: extend regulatory support for S1G Kieran Frewen
@ 2022-07-11  1:08 ` Kieran Frewen
  2022-07-11  1:08 ` [PATCH 03/12] mac80211: S1G beacon/short beacon support Kieran Frewen
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Kieran Frewen @ 2022-07-11  1:08 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Kieran Frewen, Bassem Dawood

Updates to the TIM information element to match changes made in the
IEEE Std 802.11-2020.

Signed-off-by: Kieran Frewen <kieran.frewen@morsemicro.com>
Signed-off-by: Bassem Dawood <bassem@morsemicro.com>
---
 net/mac80211/tx.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index c3e14ef20c05..3d83f838d728 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4710,9 +4710,9 @@ static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
 			ps->dtim_count--;
 	}
 
-	tim = pos = skb_put(skb, 6);
+	tim = pos = skb_put(skb, 5);
 	*pos++ = WLAN_EID_TIM;
-	*pos++ = 4;
+	*pos++ = 3;
 	*pos++ = ps->dtim_count;
 	*pos++ = link_conf->dtim_period;
 
@@ -4743,13 +4743,18 @@ static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
 		/* Bitmap control */
 		*pos++ = n1 | aid0;
 		/* Part Virt Bitmap */
-		skb_put(skb, n2 - n1);
+		skb_put(skb, n2 - n1 + 1);
 		memcpy(pos, ps->tim + n1, n2 - n1 + 1);
 
 		tim[1] = n2 - n1 + 4;
 	} else {
 		*pos++ = aid0; /* Bitmap control */
-		*pos++ = 0; /* Part Virt Bitmap */
+
+		if (ieee80211_get_sband(sdata)->band != NL80211_BAND_S1GHZ) {
+			skb_put(skb, 1);
+			tim[1] = 4;
+			*pos++ = 0; /* Part Virt Bitmap */
+		}
 	}
 }
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 03/12] mac80211: S1G beacon/short beacon support
  2022-07-11  1:08 [PATCH 00/12] Additional support for 802.11ah (S1G) Kieran Frewen
  2022-07-11  1:08 ` [PATCH 01/12] cfg80211: regulatory: extend regulatory support for S1G Kieran Frewen
  2022-07-11  1:08 ` [PATCH 02/12] mac80211: update TIM for S1G specification changes Kieran Frewen
@ 2022-07-11  1:08 ` Kieran Frewen
  2022-07-11  1:08 ` [PATCH 04/12] nl80211: support setting S1G short beacon period Kieran Frewen
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Kieran Frewen @ 2022-07-11  1:08 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Kieran Frewen, Bassem Dawood

If configured, use the S1G short beacon format. The S1G short beacon
format includes a limited set of information elements.

Signed-off-by: Kieran Frewen <kieran.frewen@morsemicro.com>
Signed-off-by: Bassem Dawood <bassem@morsemicro.com>
---
 include/net/cfg80211.h     |  2 +-
 include/net/mac80211.h     |  1 +
 net/mac80211/cfg.c         |  1 +
 net/mac80211/ieee80211_i.h |  1 +
 net/mac80211/tx.c          | 14 +++++++++++++-
 5 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 996782c44838..7859b8b11968 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1310,7 +1310,7 @@ struct cfg80211_ap_settings {
 
 	struct cfg80211_beacon_data beacon;
 
-	int beacon_interval, dtim_period;
+	int beacon_interval, dtim_period, short_beacon_period;
 	const u8 *ssid;
 	size_t ssid_len;
 	enum nl80211_hidden_ssid hidden_ssid;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 27f24ac0426d..1fd461ed746d 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -656,6 +656,7 @@ struct ieee80211_bss_conf {
 	bool enable_beacon;
 	u8 dtim_period;
 	u16 beacon_int;
+	u8 short_beacon_period;
 	u16 assoc_capability;
 	u64 sync_tsf;
 	u32 sync_device_ts;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b387f5f4fef0..b4c2f4e9083e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1227,6 +1227,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
 	}
 
 	link_conf->dtim_period = params->dtim_period;
+	link_conf->short_beacon_period = params->short_beacon_period;
 	link_conf->enable_beacon = true;
 	link_conf->allow_p2p_go_ps = sdata->vif.p2p;
 	link_conf->twt_responder = params->twt_responder;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 2190d08f4e34..19fa3f830abc 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -257,6 +257,7 @@ struct beacon_data {
 	struct ieee80211_meshconf_ie *meshconf;
 	u16 cntdwn_counter_offsets[IEEE80211_MAX_CNTDWN_COUNTERS_NUM];
 	u8 cntdwn_current_counter;
+	u8 long_beacon_count;
 	struct cfg80211_mbssid_elems *mbssid_ies;
 	struct rcu_head rcu_head;
 };
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 3d83f838d728..632df040f07f 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -5065,6 +5065,18 @@ ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
 	struct sk_buff *skb = NULL;
 	u16 csa_off_base = 0;
 	int mbssid_len;
+	bool is_short = false;
+
+	if (vif->cfg.s1g) {
+		if (beacon->long_beacon_count == 0) {
+			is_short = false;
+			beacon->long_beacon_count =
+				vif->bss_conf.short_beacon_period - 1;
+		} else {
+			is_short = true;
+			beacon->long_beacon_count--;
+		}
+	}
 
 	if (beacon->cntdwn_counter_offsets[0]) {
 		if (!is_template)
@@ -5102,7 +5114,7 @@ ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
 		csa_off_base = skb->len;
 	}
 
-	if (beacon->tail)
+	if (beacon->tail && !is_short)
 		skb_put_data(skb, beacon->tail, beacon->tail_len);
 
 	if (ieee80211_beacon_protect(skb, local, sdata, link_id) < 0)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 04/12] nl80211: support setting S1G short beacon period
  2022-07-11  1:08 [PATCH 00/12] Additional support for 802.11ah (S1G) Kieran Frewen
                   ` (2 preceding siblings ...)
  2022-07-11  1:08 ` [PATCH 03/12] mac80211: S1G beacon/short beacon support Kieran Frewen
@ 2022-07-11  1:08 ` Kieran Frewen
  2022-07-12 22:08   ` Jeff Johnson
  2022-07-11  1:08 ` [PATCH 05/12] nl80211: support advertising S1G capabilities Kieran Frewen
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 19+ messages in thread
From: Kieran Frewen @ 2022-07-11  1:08 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Kieran Frewen, Bassem Dawood

With the kernel able to send both short and long S1G beacons, include
the ability for setting the short beacon period.

Signed-off-by: Kieran Frewen <kieran.frewen@morsemicro.com>
Signed-off-by: Bassem Dawood <bassem@morsemicro.com>
---
 include/uapi/linux/nl80211.h | 6 ++++++
 net/wireless/nl80211.c       | 4 ++++
 2 files changed, 10 insertions(+)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 89f64f46b98d..bd6e2cae1dd3 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2694,6 +2694,8 @@ enum nl80211_commands {
  *	connection. Used with %NL80211_CMD_CONNECT. If this attribute is not
  *	included in NL80211_CMD_CONNECT drivers must not perform MLO connection.
  *
+ * @NL80211_ATTR_SHORT_BEACON_PERIOD: S1G short beacon period in TUs.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3214,6 +3216,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_MLO_SUPPORT,
 
+	NL80211_ATTR_SHORT_BEACON_PERIOD,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -4890,6 +4894,7 @@ enum nl80211_bss_scan_width {
  *	Contains a nested array of signal strength attributes (u8, dBm),
  *	using the nesting index as the antenna number.
  * @NL80211_BSS_FREQUENCY_OFFSET: frequency offset in KHz
+ * @NL80211_BSS_SHORT_BEACON_PERIOD: S1G short beacon period in TUs
  * @__NL80211_BSS_AFTER_LAST: internal
  * @NL80211_BSS_MAX: highest BSS attribute
  */
@@ -4915,6 +4920,7 @@ enum nl80211_bss {
 	NL80211_BSS_PARENT_BSSID,
 	NL80211_BSS_CHAIN_SIGNAL,
 	NL80211_BSS_FREQUENCY_OFFSET,
+	NL80211_BSS_SHORT_BEACON_PERIOD,
 
 	/* keep last */
 	__NL80211_BSS_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 6a45801c783c..ab47e4130141 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -798,6 +798,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
 		NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS),
 	[NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
 	[NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
+	[NL80211_ATTR_SHORT_BEACON_PERIOD] = { .type = NLA_U32 },
 };
 
 /* policy for the key attributes */
@@ -5654,6 +5655,9 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 		nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
 	params->dtim_period =
 		nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
+	if (info->attrs[NL80211_ATTR_SHORT_BEACON_PERIOD])
+		params->short_beacon_period =
+			nla_get_u32(info->attrs[NL80211_ATTR_SHORT_BEACON_PERIOD]);
 
 	err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
 					   params->beacon_interval);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 05/12] nl80211: support advertising S1G capabilities
  2022-07-11  1:08 [PATCH 00/12] Additional support for 802.11ah (S1G) Kieran Frewen
                   ` (3 preceding siblings ...)
  2022-07-11  1:08 ` [PATCH 04/12] nl80211: support setting S1G short beacon period Kieran Frewen
@ 2022-07-11  1:08 ` Kieran Frewen
  2022-07-11  1:08 ` [PATCH 06/12] mac80211: support ieee80211_ext format Kieran Frewen
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Kieran Frewen @ 2022-07-11  1:08 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Kieran Frewen, Bassem Dawood

Include S1G capabilities in netlink band info messages.

Signed-off-by: Kieran Frewen <kieran.frewen@morsemicro.com>
Signed-off-by: Bassem Dawood <bassem@morsemicro.com>
---
 include/uapi/linux/nl80211.h |  7 +++++++
 net/wireless/nl80211.c       | 10 ++++++++++
 2 files changed, 17 insertions(+)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index bd6e2cae1dd3..71074332ccc5 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3933,6 +3933,10 @@ enum nl80211_band_iftype_attr {
  * @NL80211_BAND_ATTR_EDMG_BW_CONFIG: Channel BW Configuration subfield encodes
  *	the allowed channel bandwidth configurations.
  *	Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13.
+ * @NL80211_BAND_ATTR_S1G_MCS_NSS_SET: S1G capabilities, supported S1G-MCS and NSS
+ *	set subfield, as in the S1G information IE, 5 bytes
+ * @NL80211_BAND_ATTR_S1G_CAPA: S1G capabilities information subfield as in the
+ *	S1G information IE, 10 bytes
  * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined
  * @__NL80211_BAND_ATTR_AFTER_LAST: internal use
  */
@@ -3953,6 +3957,9 @@ enum nl80211_band_attr {
 	NL80211_BAND_ATTR_EDMG_CHANNELS,
 	NL80211_BAND_ATTR_EDMG_BW_CONFIG,
 
+	NL80211_BAND_ATTR_S1G_MCS_NSS_SET,
+	NL80211_BAND_ATTR_S1G_CAPA,
+
 	/* keep last */
 	__NL80211_BAND_ATTR_AFTER_LAST,
 	NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index ab47e4130141..077dc2938551 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1942,6 +1942,16 @@ static int nl80211_send_band_rateinfo(struct sk_buff *msg,
 
 	nla_nest_end(msg, nl_rates);
 
+	/* S1G capabilities */
+	if (sband->band == NL80211_BAND_S1GHZ && sband->s1g_cap.s1g &&
+	    (nla_put(msg, NL80211_BAND_ATTR_S1G_CAPA,
+		     sizeof(sband->s1g_cap.cap),
+		     sband->s1g_cap.cap) ||
+	     nla_put(msg, NL80211_BAND_ATTR_S1G_MCS_NSS_SET,
+		     sizeof(sband->s1g_cap.nss_mcs),
+		     sband->s1g_cap.nss_mcs)))
+		return -ENOBUFS;
+
 	return 0;
 }
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 06/12] mac80211: support ieee80211_ext format
  2022-07-11  1:08 [PATCH 00/12] Additional support for 802.11ah (S1G) Kieran Frewen
                   ` (4 preceding siblings ...)
  2022-07-11  1:08 ` [PATCH 05/12] nl80211: support advertising S1G capabilities Kieran Frewen
@ 2022-07-11  1:08 ` Kieran Frewen
  2022-07-12 22:18   ` Jeff Johnson
  2022-07-11  1:08 ` [PATCH 07/12] mac80211: S1G capabilities information element in probe request Kieran Frewen
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 19+ messages in thread
From: Kieran Frewen @ 2022-07-11  1:08 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Kieran Frewen, Bassem Dawood

Ensure S1G beacons use the new ieee80211_ext format when required.

Signed-off-by: Kieran Frewen <kieran.frewen@morsemicro.com>
Signed-off-by: Bassem Dawood <bassem@morsemicro.com>
---
 net/mac80211/rx.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index d017ad14d7db..feab1d58e932 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -4772,6 +4772,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 	struct ieee80211_local *local = hw_to_local(hw);
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_hdr *hdr;
+	struct ieee80211_ext *ext_hdr;
 	__le16 fc;
 	struct ieee80211_rx_data rx;
 	struct ieee80211_sub_if_data *prev;
@@ -4787,7 +4788,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 	if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
 		I802_DEBUG_INC(local->dot11ReceivedFragmentCount);
 
-	if (ieee80211_is_mgmt(fc)) {
+	if (ieee80211_is_mgmt(fc) || ieee80211_is_s1g_beacon(fc)) {
 		/* drop frame if too short for header */
 		if (skb->len < ieee80211_hdrlen(fc))
 			err = -ENOBUFS;
@@ -4802,13 +4803,16 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 		return;
 	}
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	if (ieee80211_is_s1g_beacon(fc))
+		ext_hdr = (struct ieee80211_ext *)skb->data;
+	else
+		hdr = (struct ieee80211_hdr *)skb->data;
 	ieee80211_parse_qos(&rx);
 	ieee80211_verify_alignment(&rx);
 
-	if (unlikely(ieee80211_is_probe_resp(hdr->frame_control) ||
-		     ieee80211_is_beacon(hdr->frame_control) ||
-		     ieee80211_is_s1g_beacon(hdr->frame_control)))
+	if (unlikely(ieee80211_is_probe_resp(fc) ||
+		     ieee80211_is_beacon(fc) ||
+		     ieee80211_is_s1g_beacon(fc)))
 		ieee80211_scan_rx(local, skb);
 
 	if (ieee80211_is_data(fc)) {
@@ -4868,7 +4872,10 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 			continue;
 		}
 
-		rx.sta = sta_info_get_bss(prev, hdr->addr2);
+		if (ieee80211_is_s1g_beacon(fc))
+			rx.sta = sta_info_get_bss(prev, ext_hdr->u.s1g_beacon.sa);
+		else
+			rx.sta = sta_info_get_bss(prev, hdr->addr2);
 		rx.sdata = prev;
 		ieee80211_prepare_and_rx_handle(&rx, skb, false);
 
@@ -4876,7 +4883,10 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 	}
 
 	if (prev) {
-		rx.sta = sta_info_get_bss(prev, hdr->addr2);
+		if (ieee80211_is_s1g_beacon(fc))
+			rx.sta = sta_info_get_bss(prev, ext_hdr->u.s1g_beacon.sa);
+		else
+			rx.sta = sta_info_get_bss(prev, hdr->addr2);
 		rx.sdata = prev;
 
 		if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 07/12] mac80211: S1G capabilities information element in probe request
  2022-07-11  1:08 [PATCH 00/12] Additional support for 802.11ah (S1G) Kieran Frewen
                   ` (5 preceding siblings ...)
  2022-07-11  1:08 ` [PATCH 06/12] mac80211: support ieee80211_ext format Kieran Frewen
@ 2022-07-11  1:08 ` Kieran Frewen
  2022-07-12 22:23   ` Jeff Johnson
  2022-07-11  1:08 ` [PATCH 08/12] cfg80211: S1G rate flags Kieran Frewen
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 19+ messages in thread
From: Kieran Frewen @ 2022-07-11  1:08 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Kieran Frewen, Bassem Dawood

Add the missing S1G capabilities information element to probe requests.

Signed-off-by: Kieran Frewen <kieran.frewen@morsemicro.com>
Signed-off-by: Bassem Dawood <bassem@morsemicro.com>
---
 net/mac80211/util.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index bccc3a309ed0..51a2c1dee360 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1832,6 +1832,43 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_sub_if_data *sdata,
 	rate_flags = ieee80211_chandef_rate_flags(chandef);
 	shift = ieee80211_chandef_get_shift(chandef);
 
+	/* For direct mac80211 scan (probe request), add S1G IE and consider its override bits */
+	if (band == NL80211_BAND_S1GHZ) {
+		struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+		struct ieee80211_s1g_cap s1g_capab;
+
+		*pos++ = WLAN_EID_S1G_CAPABILITIES;
+		*pos++ = sizeof(s1g_capab);
+
+		memcpy(s1g_capab.capab_info,
+		       sband->s1g_cap.cap,
+		       sizeof(sband->s1g_cap.cap));
+		memcpy(s1g_capab.supp_mcs_nss,
+		       sband->s1g_cap.nss_mcs,
+		       sizeof(sband->s1g_cap.nss_mcs));
+
+		/* override the capability info */
+		for (i = 0; i < sizeof(ifmgd->s1g_capa.capab_info); i++) {
+			u8 mask = ifmgd->s1g_capa_mask.capab_info[i];
+
+			s1g_capab.capab_info[i] &= ~mask;
+			s1g_capab.capab_info[i] |= ifmgd->s1g_capa.capab_info[i] & mask;
+		}
+
+		/* then MCS and NSS set */
+		for (i = 0; i < sizeof(ifmgd->s1g_capa.supp_mcs_nss); i++) {
+			u8 mask = ifmgd->s1g_capa_mask.supp_mcs_nss[i];
+
+			s1g_capab.supp_mcs_nss[i] &= ~mask;
+			s1g_capab.supp_mcs_nss[i] |= ifmgd->s1g_capa.supp_mcs_nss[i] & mask;
+		}
+
+		memcpy(pos, &s1g_capab, sizeof(s1g_capab));
+		pos += sizeof(s1g_capab);
+		/* No more IEs relevant for S1G */
+		goto done;
+	}
+
 	num_rates = 0;
 	for (i = 0; i < sband->n_bitrates; i++) {
 		if ((BIT(i) & rate_mask) == 0)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 08/12] cfg80211: S1G rate flags
  2022-07-11  1:08 [PATCH 00/12] Additional support for 802.11ah (S1G) Kieran Frewen
                   ` (6 preceding siblings ...)
  2022-07-11  1:08 ` [PATCH 07/12] mac80211: S1G capabilities information element in probe request Kieran Frewen
@ 2022-07-11  1:08 ` Kieran Frewen
  2022-07-12 22:36   ` Jeff Johnson
  2022-07-11  1:08 ` [PATCH 09/12] nl80211: support advertising S1G rate information Kieran Frewen
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 19+ messages in thread
From: Kieran Frewen @ 2022-07-11  1:08 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Kieran Frewen, Bassem Dawood

Increase the size of S1G rate_info flags to support S1G. Add flags for new
S1G bandwidths and S1G MCS.

Signed-off-by: Kieran Frewen <kieran.frewen@morsemicro.com>
Signed-off-by: Bassem Dawood <bassem@morsemicro.com>
---
 include/net/cfg80211.h | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7859b8b11968..47f71fb5d07a 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1608,6 +1608,7 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
  * @RATE_INFO_FLAGS_EDMG: 60GHz MCS in EDMG mode
  * @RATE_INFO_FLAGS_EXTENDED_SC_DMG: 60GHz extended SC MCS
  * @RATE_INFO_FLAGS_EHT_MCS: EHT MCS information
+ * @RATE_INFO_FLAGS_S1G_MCS: mcs field filled with S1G MCS
  */
 enum rate_info_flags {
 	RATE_INFO_FLAGS_MCS			= BIT(0),
@@ -1618,6 +1619,7 @@ enum rate_info_flags {
 	RATE_INFO_FLAGS_EDMG			= BIT(5),
 	RATE_INFO_FLAGS_EXTENDED_SC_DMG		= BIT(6),
 	RATE_INFO_FLAGS_EHT_MCS			= BIT(7),
+	RATE_INFO_FLAGS_S1G_MCS                 = BIT(8),
 };
 
 /**
@@ -1634,6 +1636,11 @@ enum rate_info_flags {
  * @RATE_INFO_BW_HE_RU: bandwidth determined by HE RU allocation
  * @RATE_INFO_BW_320: 320 MHz bandwidth
  * @RATE_INFO_BW_EHT_RU: bandwidth determined by EHT RU allocation
+ * @RATE_INFO_BW_1: 1 MHz bandwidth
+ * @RATE_INFO_BW_2: 2 MHz bandwidth
+ * @RATE_INFO_BW_4: 4 MHz bandwidth
+ * @RATE_INFO_BW_8: 8 MHz bandwidth
+ * @RATE_INFO_BW_16: 16 MHz bandwidth
  */
 enum rate_info_bw {
 	RATE_INFO_BW_20 = 0,
@@ -1645,6 +1652,11 @@ enum rate_info_bw {
 	RATE_INFO_BW_HE_RU,
 	RATE_INFO_BW_320,
 	RATE_INFO_BW_EHT_RU,
+	RATE_INFO_BW_1,
+	RATE_INFO_BW_2,
+	RATE_INFO_BW_4,
+	RATE_INFO_BW_8,
+	RATE_INFO_BW_16,
 };
 
 /**
@@ -1667,7 +1679,7 @@ enum rate_info_bw {
  *	only valid if bw is %RATE_INFO_BW_EHT_RU)
  */
 struct rate_info {
-	u8 flags;
+	u16 flags;
 	u8 mcs;
 	u16 legacy;
 	u8 nss;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 09/12] nl80211: support advertising S1G rate information
  2022-07-11  1:08 [PATCH 00/12] Additional support for 802.11ah (S1G) Kieran Frewen
                   ` (7 preceding siblings ...)
  2022-07-11  1:08 ` [PATCH 08/12] cfg80211: S1G rate flags Kieran Frewen
@ 2022-07-11  1:08 ` Kieran Frewen
  2022-07-13  0:48   ` Jeff Johnson
  2022-07-11  1:08 ` [PATCH 10/12] mac80211: support S1G rate encoding Kieran Frewen
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 19+ messages in thread
From: Kieran Frewen @ 2022-07-11  1:08 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Kieran Frewen, Bassem Dawood

Add S1G rate information to netlink STA rate message.

Signed-off-by: Kieran Frewen <kieran.frewen@morsemicro.com>
Signed-off-by: Bassem Dawood <bassem@morsemicro.com>
---
 include/uapi/linux/nl80211.h | 14 ++++++++++++++
 net/wireless/nl80211.c       | 23 +++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 71074332ccc5..19cf030004e9 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3539,6 +3539,13 @@ enum nl80211_eht_ru_alloc {
  *	(u8, see &enum nl80211_eht_gi)
  * @NL80211_RATE_INFO_EHT_RU_ALLOC: EHT RU allocation, if not present then
  *	non-OFDMA was used (u8, see &enum nl80211_eht_ru_alloc)
+ * @NL80211_RATE_INFO_S1G_MCS: S1G MCS index (u8, 0-10)
+ * @NL80211_RATE_INFO_S1G_nss: S1G NSS value (u8, 1-4)
+ * @NL80211_RATE_INFO_1_MHZ_WIDTH: 1 MHz S1G rate
+ * @NL80211_RATE_INFO_2_MHZ_WIDTH: 2 MHz S1G rate
+ * @NL80211_RATE_INFO_4_MHZ_WIDTH: 4 MHz S1G rate
+ * @NL80211_RATE_INFO_8_MHZ_WIDTH: 8 MHz S1G rate
+ * @NL80211_RATE_INFO_16_MHZ_WIDTH: 16 MHz S1G rate
  * @__NL80211_RATE_INFO_AFTER_LAST: internal use
  */
 enum nl80211_rate_info {
@@ -3565,6 +3572,13 @@ enum nl80211_rate_info {
 	NL80211_RATE_INFO_EHT_NSS,
 	NL80211_RATE_INFO_EHT_GI,
 	NL80211_RATE_INFO_EHT_RU_ALLOC,
+	NL80211_RATE_INFO_S1G_MCS,
+	NL80211_RATE_INFO_S1G_NSS,
+	NL80211_RATE_INFO_1_MHZ_WIDTH,
+	NL80211_RATE_INFO_2_MHZ_WIDTH,
+	NL80211_RATE_INFO_4_MHZ_WIDTH,
+	NL80211_RATE_INFO_8_MHZ_WIDTH,
+	NL80211_RATE_INFO_16_MHZ_WIDTH,
 
 	/* keep last */
 	__NL80211_RATE_INFO_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 077dc2938551..70efed2b5899 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6073,6 +6073,21 @@ bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
 		return false;
 
 	switch (info->bw) {
+	case RATE_INFO_BW_1:
+		rate_flg = NL80211_RATE_INFO_1_MHZ_WIDTH;
+		break;
+	case RATE_INFO_BW_2:
+		rate_flg = NL80211_RATE_INFO_2_MHZ_WIDTH;
+		break;
+	case RATE_INFO_BW_4:
+		rate_flg = NL80211_RATE_INFO_4_MHZ_WIDTH;
+		break;
+	case RATE_INFO_BW_8:
+		rate_flg = NL80211_RATE_INFO_8_MHZ_WIDTH;
+		break;
+	case RATE_INFO_BW_16:
+		rate_flg = NL80211_RATE_INFO_16_MHZ_WIDTH;
+		break;
 	case RATE_INFO_BW_5:
 		rate_flg = NL80211_RATE_INFO_5_MHZ_WIDTH;
 		break;
@@ -6137,6 +6152,14 @@ bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
 		    nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC,
 			       info->he_ru_alloc))
 			return false;
+	} else if (info->flags & RATE_INFO_FLAGS_S1G_MCS) {
+		if (nla_put_u8(msg, NL80211_RATE_INFO_S1G_MCS, info->mcs))
+			return false;
+		if (nla_put_u8(msg, NL80211_RATE_INFO_S1G_NSS, info->nss))
+			return false;
+		if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
+		    nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
+			return false;
 	} else if (info->flags & RATE_INFO_FLAGS_EHT_MCS) {
 		if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_MCS, info->mcs))
 			return false;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 10/12] mac80211: support S1G rate encoding.
  2022-07-11  1:08 [PATCH 00/12] Additional support for 802.11ah (S1G) Kieran Frewen
                   ` (8 preceding siblings ...)
  2022-07-11  1:08 ` [PATCH 09/12] nl80211: support advertising S1G rate information Kieran Frewen
@ 2022-07-11  1:08 ` Kieran Frewen
  2022-07-11  1:08 ` [PATCH 11/12] cfg80211: support for calculating S1G bitrates Kieran Frewen
  2022-07-11  1:08 ` [PATCH 12/12] mac80211_hwsim: support for S1G rate information Kieran Frewen
  11 siblings, 0 replies; 19+ messages in thread
From: Kieran Frewen @ 2022-07-11  1:08 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Kieran Frewen, Bassem Dawood

Add support for receiving and transmitting S1G frames.

Signed-off-by: Kieran Frewen <kieran.frewen@morsemicro.com>
Signed-off-by: Bassem Dawood <bassem@morsemicro.com>
---
 drivers/net/wireless/mac80211_hwsim.c |  2 +-
 include/net/mac80211.h                | 32 ++++++++++++++++----
 net/mac80211/cfg.c                    | 42 ++++++++++++++++++++-------
 net/mac80211/rx.c                     |  8 +++++
 net/mac80211/sta_info.c               |  7 +++++
 net/mac80211/sta_info.h               |  7 +++++
 net/mac80211/util.c                   | 30 ++++++++++++++++++-
 7 files changed, 110 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index c5bb97b381cf..304249038ac6 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1547,7 +1547,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
 	memset(&rx_status, 0, sizeof(rx_status));
 	rx_status.flag |= RX_FLAG_MACTIME_START;
 	rx_status.freq = chan->center_freq;
-	rx_status.freq_offset = chan->freq_offset ? 1 : 0;
+	rx_status.freq_offset = chan->freq_offset;
 	rx_status.band = chan->band;
 	if (info->control.rates[0].flags & IEEE80211_TX_RC_VHT_MCS) {
 		rx_status.rate_idx =
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 1fd461ed746d..93fe4b98017c 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -848,6 +848,10 @@ enum mac80211_tx_info_flags {
 #define IEEE80211_TX_CTL_STBC_SHIFT		23
 
 #define IEEE80211_TX_RC_S1G_MCS IEEE80211_TX_RC_VHT_MCS
+#define IEEE80211_TX_RC_2_MHZ_WIDTH IEEE80211_TX_RC_MCS
+#define IEEE80211_TX_RC_4_MHZ_WIDTH IEEE80211_TX_RC_40_MHZ_WIDTH
+#define IEEE80211_TX_RC_8_MHZ_WIDTH IEEE80211_TX_RC_80_MHZ_WIDTH
+#define IEEE80211_TX_RC_16_MHZ_WIDTH IEEE80211_TX_RC_160_MHZ_WIDTH
 
 /**
  * enum mac80211_tx_control_flags - flags to describe transmit control
@@ -1028,6 +1032,20 @@ ieee80211_rate_get_vht_nss(const struct ieee80211_tx_rate *rate)
 	return (rate->idx >> 4) + 1;
 }
 
+static inline u8
+ieee80211_rate_get_s1g_mcs(const struct ieee80211_tx_rate *rate)
+{
+	/* S1G uses the same MCS encoding as VHT */
+	return ieee80211_rate_get_vht_mcs(rate);
+}
+
+static inline u8
+ieee80211_rate_get_s1g_nss(const struct ieee80211_tx_rate *rate)
+{
+	/* S1G uses the same NSS encoding as VHT */
+	return ieee80211_rate_get_vht_nss(rate);
+}
+
 /**
  * struct ieee80211_tx_info - skb transmit information
  *
@@ -1408,6 +1426,7 @@ enum mac80211_rx_encoding {
 	RX_ENC_HT,
 	RX_ENC_VHT,
 	RX_ENC_HE,
+	RX_ENC_S1G,
 };
 
 /**
@@ -1458,10 +1477,11 @@ struct ieee80211_rx_status {
 	u32 device_timestamp;
 	u32 ampdu_reference;
 	u32 flag;
-	u16 freq: 13, freq_offset: 1;
+	u16 freq;
+	u16 freq_offset;
 	u8 enc_flags;
-	u8 encoding:2, bw:3, he_ru:3;
-	u8 he_gi:2, he_dcm:1;
+	u8 encoding:3, bw:5;
+	u8 he_ru:3, he_gi:2, he_dcm:1;
 	u8 rate_idx;
 	u8 nss;
 	u8 rx_flags;
@@ -1477,8 +1497,7 @@ struct ieee80211_rx_status {
 static inline u32
 ieee80211_rx_status_to_khz(struct ieee80211_rx_status *rx_status)
 {
-	return MHZ_TO_KHZ(rx_status->freq) +
-	       (rx_status->freq_offset ? 500 : 0);
+	return MHZ_TO_KHZ(rx_status->freq) + rx_status->freq_offset;
 }
 
 /**
@@ -6506,6 +6525,9 @@ bool rate_usable_index_exists(struct ieee80211_supported_band *sband,
 {
 	unsigned int i;
 
+	if (sband->band == NL80211_BAND_S1GHZ)
+		return true;
+
 	for (i = 0; i < sband->n_bitrates; i++)
 		if (rate_supported(sta, sband->band, i))
 			return true;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b4c2f4e9083e..a5511eb56dd9 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -743,8 +743,16 @@ void sta_set_rate_info_tx(struct sta_info *sta,
 			  const struct ieee80211_tx_rate *rate,
 			  struct rate_info *rinfo)
 {
+	struct ieee80211_supported_band *sband;
+
+	sband = ieee80211_get_sband(sta->sdata);
 	rinfo->flags = 0;
-	if (rate->flags & IEEE80211_TX_RC_MCS) {
+	if (rate->flags & IEEE80211_TX_RC_S1G_MCS &&
+	    sband->band == NL80211_BAND_S1GHZ) {
+		rinfo->flags |= RATE_INFO_FLAGS_S1G_MCS;
+		rinfo->mcs = ieee80211_rate_get_s1g_mcs(rate);
+		rinfo->nss = ieee80211_rate_get_s1g_nss(rate);
+	} else if (rate->flags & IEEE80211_TX_RC_MCS) {
 		rinfo->flags |= RATE_INFO_FLAGS_MCS;
 		rinfo->mcs = rate->idx;
 	} else if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
@@ -752,25 +760,37 @@ void sta_set_rate_info_tx(struct sta_info *sta,
 		rinfo->mcs = ieee80211_rate_get_vht_mcs(rate);
 		rinfo->nss = ieee80211_rate_get_vht_nss(rate);
 	} else {
-		struct ieee80211_supported_band *sband;
 		int shift = ieee80211_vif_get_shift(&sta->sdata->vif);
 		u16 brate;
 
-		sband = ieee80211_get_sband(sta->sdata);
 		WARN_ON_ONCE(sband && !sband->bitrates);
 		if (sband && sband->bitrates) {
 			brate = sband->bitrates[rate->idx].bitrate;
 			rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift);
 		}
 	}
-	if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-		rinfo->bw = RATE_INFO_BW_40;
-	else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
-		rinfo->bw = RATE_INFO_BW_80;
-	else if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
-		rinfo->bw = RATE_INFO_BW_160;
-	else
-		rinfo->bw = RATE_INFO_BW_20;
+	if (sband->band == NL80211_BAND_S1GHZ) {
+		if (rate->flags & IEEE80211_TX_RC_2_MHZ_WIDTH)
+			rinfo->bw = RATE_INFO_BW_2;
+		else if (rate->flags & IEEE80211_TX_RC_4_MHZ_WIDTH)
+			rinfo->bw = RATE_INFO_BW_4;
+		else if (rate->flags & IEEE80211_TX_RC_8_MHZ_WIDTH)
+			rinfo->bw = RATE_INFO_BW_8;
+		else if (rate->flags & IEEE80211_TX_RC_16_MHZ_WIDTH)
+			rinfo->bw = RATE_INFO_BW_16;
+		else
+			rinfo->bw = RATE_INFO_BW_1;
+	} else {
+		if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+			rinfo->bw = RATE_INFO_BW_40;
+		else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
+			rinfo->bw = RATE_INFO_BW_80;
+		else if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
+			rinfo->bw = RATE_INFO_BW_160;
+		else
+			rinfo->bw = RATE_INFO_BW_20;
+	}
+
 	if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
 		rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
 }
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index feab1d58e932..e0a2975d0959 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -4982,6 +4982,14 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
 				      status->rate_idx, status->nss))
 				goto drop;
 			break;
+		case RX_ENC_S1G:
+			if (WARN_ONCE(status->rate_idx > 10 ||
+				      !status->nss ||
+				      status->nss > 8,
+				      "Rate marked as a S1G rate but data is invalid: MCS: %d, NSS: %d\n",
+				      status->rate_idx, status->nss))
+				goto drop;
+			break;
 		default:
 			WARN_ON_ONCE(1);
 			fallthrough;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 014032369994..da03d4eef321 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2297,6 +2297,13 @@ static void sta_stats_decode_rate(struct ieee80211_local *local, u32 rate,
 		rinfo->he_ru_alloc = STA_STATS_GET(HE_RU, rate);
 		rinfo->he_dcm = STA_STATS_GET(HE_DCM, rate);
 		break;
+	case STA_STATS_RATE_TYPE_S1G:
+		rinfo->flags = RATE_INFO_FLAGS_S1G_MCS;
+		rinfo->mcs = STA_STATS_GET(S1G_MCS, rate);
+		rinfo->nss = STA_STATS_GET(S1G_NSS, rate);
+		if (STA_STATS_GET(SGI, rate))
+			rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
+		break;
 	}
 }
 
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 218430790660..d2173a191da4 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -931,6 +931,8 @@ enum sta_stats_type {
 #define STA_STATS_FIELD_VHT_NSS		GENMASK( 7,  4)
 #define STA_STATS_FIELD_HE_MCS		GENMASK( 3,  0)
 #define STA_STATS_FIELD_HE_NSS		GENMASK( 7,  4)
+#define STA_STATS_FIELD_S1G_MCS		GENMASK( 3,  0)
+#define STA_STATS_FIELD_S1G_NSS		GENMASK( 7,  4)
 #define STA_STATS_FIELD_BW		GENMASK(11,  8)
 #define STA_STATS_FIELD_SGI		GENMASK(12, 12)
 #define STA_STATS_FIELD_TYPE		GENMASK(15, 13)
@@ -975,6 +977,11 @@ static inline u32 sta_stats_encode_rate(struct ieee80211_rx_status *s)
 		r |= STA_STATS_FIELD(HE_RU, s->he_ru);
 		r |= STA_STATS_FIELD(HE_DCM, s->he_dcm);
 		break;
+	case RX_ENC_S1G:
+		r |= STA_STATS_FIELD(TYPE, STA_STATS_RATE_TYPE_S1G);
+		r |= STA_STATS_FIELD(S1G_NSS, s->nss);
+		r |= STA_STATS_FIELD(S1G_MCS, s->rate_idx);
+		break;
 	default:
 		WARN_ON(1);
 		return STA_STATS_RATE_INVALID;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 51a2c1dee360..8b896aec5f8c 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3861,7 +3861,7 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
 	u64 ts = status->mactime;
 	struct rate_info ri;
 	u16 rate;
-	u8 n_ltf;
+	u8 n_ltf, guard_factor;
 
 	if (WARN_ON(!ieee80211_have_rx_timestamp(status)))
 		return 0;
@@ -3948,6 +3948,34 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
 			ts += 4 * n_ltf;
 		}
 
+		break;
+	case RX_ENC_S1G:
+		/* Set to duration of S1G OFDM symbol with normal GI */
+		guard_factor = 40;
+		ri.flags |= RATE_INFO_FLAGS_S1G_MCS;
+		ri.mcs = status->rate_idx;
+		ri.nss = status->nss;
+		if (status->enc_flags & RX_ENC_FLAG_SHORT_GI) {
+			ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
+			guard_factor = 36;
+		}
+
+		/*
+		 * See 80211-2020, section 23.3.2 for S1G PPDU
+		 * format and 23.3.6 for timing-related parameters.
+		 * Here using the general structure for S1G_1M as
+		 * in figure 23-3.
+		 */
+		if (status->flag & RX_FLAG_MACTIME_PLCP_START) {
+			mpdu_offset += 2;
+			ts += (14 * guard_factor);
+
+			/* Add S1G-LTFs per streams */
+			n_ltf = (ri.nss != 1) && (ri.nss % 2) ?
+				ri.nss + 1 : ri.nss;
+			ts += (guard_factor * n_ltf);
+		}
+
 		break;
 	default:
 		WARN_ON(1);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 11/12] cfg80211: support for calculating S1G bitrates
  2022-07-11  1:08 [PATCH 00/12] Additional support for 802.11ah (S1G) Kieran Frewen
                   ` (9 preceding siblings ...)
  2022-07-11  1:08 ` [PATCH 10/12] mac80211: support S1G rate encoding Kieran Frewen
@ 2022-07-11  1:08 ` Kieran Frewen
  2022-07-11  1:08 ` [PATCH 12/12] mac80211_hwsim: support for S1G rate information Kieran Frewen
  11 siblings, 0 replies; 19+ messages in thread
From: Kieran Frewen @ 2022-07-11  1:08 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Kieran Frewen, Bassem Dawood

Support for reporting and calculating S1G MCS bitrates.

Signed-off-by: Kieran Frewen <kieran.frewen@morsemicro.com>
Signed-off-by: Bassem Dawood <bassem@morsemicro.com>
---
 net/wireless/util.c | 113 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 113 insertions(+)

diff --git a/net/wireless/util.c b/net/wireless/util.c
index 412403d29c22..1bc604ec66dc 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1380,6 +1380,117 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate)
 	return 0;
 }
 
+static u32 cfg80211_calculate_bitrate_s1g(struct rate_info *rate)
+{
+	/* For 1, 2, 4, 8 and 16 MHz channels */
+	static const u32 base[5][12] = {
+		{  300000,
+		   600000,
+		   900000,
+		  1200000,
+		  1800000,
+		  2400000,
+		  2700000,
+		  3000000,
+		  3600000,
+		  4000000,
+		  /* MCS 10 supported in 1 MHz only */
+		  150000,
+		},
+		{  650000,
+		  1300000,
+		  1950000,
+		  2600000,
+		  3900000,
+		  5200000,
+		  5850000,
+		  6500000,
+		  7800000,
+		  /* MCS 9 not valid */
+		},
+		{  1350000,
+		   2700000,
+		   4050000,
+		   5400000,
+		   8100000,
+		  10800000,
+		  12150000,
+		  13500000,
+		  16200000,
+		  18000000,
+		},
+		{  2925000,
+		   5850000,
+		   8775000,
+		  11700000,
+		  17550000,
+		  23400000,
+		  26325000,
+		  29250000,
+		  35100000,
+		  39000000,
+		},
+		{  8580000,
+		  11700000,
+		  17550000,
+		  23400000,
+		  35100000,
+		  46800000,
+		  52650000,
+		  58500000,
+		  70200000,
+		  78000000,
+		},
+	};
+	u32 bitrate;
+	/* default is 1 MHz index */
+	int idx = 0;
+
+	if (rate->mcs > 11)
+		goto warn;
+
+	switch (rate->bw) {
+	case RATE_INFO_BW_16:
+		idx = 4;
+		break;
+	case RATE_INFO_BW_8:
+		idx = 3;
+		break;
+	case RATE_INFO_BW_4:
+		idx = 2;
+		break;
+	case RATE_INFO_BW_2:
+		idx = 1;
+		break;
+	case RATE_INFO_BW_1:
+		idx = 0;
+		break;
+	case RATE_INFO_BW_5:
+	case RATE_INFO_BW_10:
+	case RATE_INFO_BW_20:
+	case RATE_INFO_BW_40:
+	case RATE_INFO_BW_80:
+	case RATE_INFO_BW_160:
+	default:
+		goto warn;
+	}
+
+	bitrate = base[idx][rate->mcs];
+	bitrate *= rate->nss;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate / 9) * 10;
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+warn:
+	if (!rate->bw && !rate->mcs && !rate->nss)
+		pr_debug("%s: rx status was not received yet!", __func__);
+	else
+		WARN_ONCE(1, "invalid rate bw=%d, mcs=%d, nss=%d\n",
+			  rate->bw, rate->mcs, rate->nss);
+	return 0;
+}
+
 static u32 cfg80211_calculate_bitrate_he(struct rate_info *rate)
 {
 #define SCALE 6144
@@ -1608,6 +1719,8 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate)
 		return cfg80211_calculate_bitrate_he(rate);
 	if (rate->flags & RATE_INFO_FLAGS_EHT_MCS)
 		return cfg80211_calculate_bitrate_eht(rate);
+	if (rate->flags & RATE_INFO_FLAGS_S1G_MCS)
+		return cfg80211_calculate_bitrate_s1g(rate);
 
 	return rate->legacy;
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 12/12] mac80211_hwsim: support for S1G rate information
  2022-07-11  1:08 [PATCH 00/12] Additional support for 802.11ah (S1G) Kieran Frewen
                   ` (10 preceding siblings ...)
  2022-07-11  1:08 ` [PATCH 11/12] cfg80211: support for calculating S1G bitrates Kieran Frewen
@ 2022-07-11  1:08 ` Kieran Frewen
  11 siblings, 0 replies; 19+ messages in thread
From: Kieran Frewen @ 2022-07-11  1:08 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Kieran Frewen, Bassem Dawood

Include S1G rate information in S1G frames.

Signed-off-by: Kieran Frewen<kieran.frewen@morsemicro.com>
Signed-off-by: Bassem Dawood <bassem@morsemicro.com>
---
 drivers/net/wireless/mac80211_hwsim.c | 38 ++++++++++++++++++++-------
 1 file changed, 29 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 304249038ac6..c4c0796a610d 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1549,7 +1549,14 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
 	rx_status.freq = chan->center_freq;
 	rx_status.freq_offset = chan->freq_offset;
 	rx_status.band = chan->band;
-	if (info->control.rates[0].flags & IEEE80211_TX_RC_VHT_MCS) {
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_S1G_MCS &&
+	    rx_status.band == NL80211_BAND_S1GHZ) {
+		rx_status.rate_idx =
+			ieee80211_rate_get_s1g_mcs(&info->control.rates[0]);
+		rx_status.nss =
+			ieee80211_rate_get_s1g_nss(&info->control.rates[0]);
+		rx_status.encoding = RX_ENC_S1G;
+	} else if (info->control.rates[0].flags & IEEE80211_TX_RC_VHT_MCS) {
 		rx_status.rate_idx =
 			ieee80211_rate_get_vht_mcs(&info->control.rates[0]);
 		rx_status.nss =
@@ -1560,14 +1567,27 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
 		if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
 			rx_status.encoding = RX_ENC_HT;
 	}
-	if (info->control.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-		rx_status.bw = RATE_INFO_BW_40;
-	else if (info->control.rates[0].flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
-		rx_status.bw = RATE_INFO_BW_80;
-	else if (info->control.rates[0].flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
-		rx_status.bw = RATE_INFO_BW_160;
-	else
-		rx_status.bw = RATE_INFO_BW_20;
+	if (rx_status.band == NL80211_BAND_S1GHZ) {
+		if (info->control.rates[0].flags & IEEE80211_TX_RC_2_MHZ_WIDTH)
+			rx_status.bw = RATE_INFO_BW_2;
+		else if (info->control.rates[0].flags & IEEE80211_TX_RC_4_MHZ_WIDTH)
+			rx_status.bw = RATE_INFO_BW_4;
+		else if (info->control.rates[0].flags & IEEE80211_TX_RC_8_MHZ_WIDTH)
+			rx_status.bw = RATE_INFO_BW_8;
+		else if (info->control.rates[0].flags & IEEE80211_TX_RC_16_MHZ_WIDTH)
+			rx_status.bw = RATE_INFO_BW_16;
+		else
+			rx_status.bw = RATE_INFO_BW_1;
+	} else {
+		if (info->control.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+			rx_status.bw = RATE_INFO_BW_40;
+		else if (info->control.rates[0].flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
+			rx_status.bw = RATE_INFO_BW_80;
+		else if (info->control.rates[0].flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
+			rx_status.bw = RATE_INFO_BW_160;
+		else
+			rx_status.bw = RATE_INFO_BW_20;
+	}
 	if (info->control.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
 		rx_status.enc_flags |= RX_ENC_FLAG_SHORT_GI;
 	/* TODO: simulate optional packet loss */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH 01/12] cfg80211: regulatory: extend regulatory support for S1G
  2022-07-11  1:08 ` [PATCH 01/12] cfg80211: regulatory: extend regulatory support for S1G Kieran Frewen
@ 2022-07-11 17:47   ` Jeff Johnson
  0 siblings, 0 replies; 19+ messages in thread
From: Jeff Johnson @ 2022-07-11 17:47 UTC (permalink / raw)
  To: Kieran Frewen, johannes; +Cc: linux-wireless, Bassem Dawood

On 7/10/2022 6:08 PM, Kieran Frewen wrote:
> Extend the S1G regulatory information to support all regulatory
> domains. An reg_s1g.h file is included containing structs with key
> regulatory class information. These structs were required to ensure
> the right combination of information was available to a series of
> functions which support the mapping between frequencies, bandwidths,
> and channels.
> 
> Signed-off-by: Kieran Frewen <kieran.frewen@morsemicro.com>
> Signed-off-by: Bassem Dawood <bassem@morsemicro.com>

I would expect the S-O-B for the person posting the patches to be last.
And it is not clear what is Bassem's contributionsince he's not listed 
as the patch author or as a Co-developed-by

> ---
>   net/wireless/reg.c     |  50 ++++++--
>   net/wireless/reg_s1g.h | 281 +++++++++++++++++++++++++++++++++++++++++
>   net/wireless/util.c    |  31 ++++-
>   3 files changed, 349 insertions(+), 13 deletions(-)
>   create mode 100644 net/wireless/reg_s1g.h
> 
> diff --git a/net/wireless/reg.c b/net/wireless/reg.c
> index c7383ede794f..d9ed6b619164 100644
> --- a/net/wireless/reg.c
> +++ b/net/wireless/reg.c
> @@ -62,6 +62,7 @@
>   #include "reg.h"
>   #include "rdev-ops.h"
>   #include "nl80211.h"
> +#include "reg_s1g.h"
>   
>   /*
>    * Grace period we give before making sure all current interfaces reside on
> @@ -1737,26 +1738,44 @@ static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd
>   		 * the largest bandwidth which cleanly divides the freq_range.
>   		 */
>   		int edge_offset;
> -		int ch_bw = max_bandwidth_khz;
> +		int ch_bw, freq_end, freq_start, class_idx;
> +		unsigned int i;
> +		const struct s1g_oper_class *oper = reg_s1g_get_oper_class(regd->alpha2);
> +
> +		for (i = 0; i < oper->class_count; i++) {
> +			if (center_freq_khz >= oper->class[i].start_freq &&
> +			    center_freq_khz <= oper->class[i].end_freq) {
> +				class_idx = i;
> +				break;
> +			}
> +		}

is the for loop above *guaranteed* to find a matching class?
the logic below uses class_idx without verifying that it has actually 
been initialized

> +
> +		ch_bw = oper->class[class_idx].max_bw_khz;
> +		freq_start = oper->class[class_idx].start_freq;
> +		freq_end = oper->class[class_idx].end_freq;
>   
>   		while (ch_bw) {
> -			edge_offset = (center_freq_khz - ch_bw / 2) -
> -				      freq_range->start_freq_khz;
> -			if (edge_offset % ch_bw == 0) {
> -				switch (KHZ_TO_MHZ(ch_bw)) {
> -				case 1:
> +			if (oper->class[class_idx].align_to_end)
> +				edge_offset = freq_end -
> +					(center_freq_khz - (ch_bw) / 2);
> +			else
> +				edge_offset = (center_freq_khz - (ch_bw) / 2) -
> +					freq_start;
> +			if (edge_offset % (ch_bw) == 0) {
> +				switch (ch_bw) {
> +				case MHZ_TO_KHZ(1):
>   					bw_flags |= IEEE80211_CHAN_1MHZ;
>   					break;
> -				case 2:
> +				case MHZ_TO_KHZ(2):
>   					bw_flags |= IEEE80211_CHAN_2MHZ;
>   					break;
> -				case 4:
> +				case MHZ_TO_KHZ(4):
>   					bw_flags |= IEEE80211_CHAN_4MHZ;
>   					break;
> -				case 8:
> +				case MHZ_TO_KHZ(8):
>   					bw_flags |= IEEE80211_CHAN_8MHZ;
>   					break;
> -				case 16:
> +				case MHZ_TO_KHZ(16):
>   					bw_flags |= IEEE80211_CHAN_16MHZ;
>   					break;
>   				default:
> @@ -2555,9 +2574,16 @@ static void handle_channel_custom(struct wiphy *wiphy,
>   	const struct ieee80211_reg_rule *reg_rule = NULL;
>   	const struct ieee80211_power_rule *power_rule = NULL;
>   	u32 bw, center_freq_khz;
> +	bool is_s1g = chan->band == NL80211_BAND_S1GHZ;
>   
> -	center_freq_khz = ieee80211_channel_to_khz(chan);
> -	for (bw = MHZ_TO_KHZ(20); bw >= min_bw; bw = bw / 2) {
> +	if (is_s1g) {
> +		bw = MHZ_TO_KHZ(16);
> +		min_bw = MHZ_TO_KHZ(1);
> +	} else {
> +		bw = MHZ_TO_KHZ(20);
> +	}
> +
> +	for (; bw >= min_bw; bw = bw / 2) {
>   		reg_rule = freq_reg_info_regd(center_freq_khz, regd, bw);
>   		if (!IS_ERR(reg_rule))
>   			break;
> diff --git a/net/wireless/reg_s1g.h b/net/wireless/reg_s1g.h
> new file mode 100644
> index 000000000000..69dd4e2cd4d3
> --- /dev/null
> +++ b/net/wireless/reg_s1g.h
> @@ -0,0 +1,281 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __NET_WIRELESS_REG_S1G_H
> +#define __NET_WIRELESS_REG_S1G_H
> +
> +#include "reg.h"
> +
> +/**
> + * Struct cca_class
> + *
> + * The specifics of a cca level classification used to validate bw/frequency
> + *	combinations in a regulatory domain
> + * @band_start: The channel starting frequency for that CCA classification

would be nice to given units for frequency

> + * @start_freq: The start of the valid frequency range for the CCA
> + *	classification
> + * @end_freq: The end of the valid frequency range for the CCA classification
> + * @max_bw_khz: The maximum valid bw for the CCA classification
> + * @align_to_end: True if the maximum valid BW for the range is aligned to the
> + *	end_freq
> + * @supported_chan: A list of supported channel indexes
> + * @n_supported_chan: A count of the supported channels for this CCA
> + *	classification
> + */
> +struct s1g_cca_classification {
> +	u32 band_start;
> +	u32 start_freq;
> +	u32 end_freq;
> +	u32 max_bw_khz;
> +	u8 align_to_end;

bool?

> +	const u8 *supported_chan;
> +	u8 n_supported_chan;
> +};
> +
> +
> +/**
> +
> + * Struct s1g_oper_class
> + *
> + * An aggregated view of the operating classes for a single regulatory
> + * domain
> + * @cc: country code

based upon usage suggest you clarify this is a 2-character code

> + * @class_count: The number of CCA level classifications that exist
> + *	within that country
> + * @class: The specifics of a CCA level classification within a regulatory
> + *	domain.
> + */
> +struct s1g_oper_class {
> +	char *cc;

why a pointer and not an array (a cc[3] array padded to 4 bytes would 
consume less space than a pointer on 64-bit architecture)

> +	int class_count;
> +	struct s1g_cca_classification class[];
> +};
> +

i'm surprise the rest of the patch for this file isn't in a .c file.

won't the contents below be replicated into every compilation unit that 
includes this header file?

> +/* The following channel lists have been retrieved from
> + * IEEE Std 802.11-2020 Table E-5
> + */
> +static const u8 us_supported_channels[] = {
> +	1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13,
> +	14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
> +	24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
> +	34, 35, 37, 38, 39, 40, 41, 42, 43, 44,
> +	45, 46, 47, 48, 49, 50, 51
> +};
> +
> +static const u8 eu_supported_channels_863[] = {
> +	1, 3, 5, 7, 9
> +};
> +
> +static const u8 eu_supported_channels_901_4[] = {
> +	33, 35
> +};
> +
> +static const u8 jp_supported_channels[] = {
> +	1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21
> +};
> +
> +static const u8 kr_supported_channels[] = {
> +	1, 2, 3, 5, 6, 7, 8, 9, 10, 11
> +};
> +
> +static const u8 sg_supported_channels_863[] = {
> +	7, 9, 10, 11
> +};
> +
> +static const u8 sg_supported_channels_902[] = {
> +	37, 38, 39, 40, 41, 42, 43, 45
> +};
> +
> +static const u8 au_nz_supported_channels[] = {
> +	27, 29, 30, 31, 32, 33, 34, 35, 37, 38, 39,
> +	40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
> +	51
> +};
> +
> +
> +/* The following s1g_oper_class structs are taken from
> + * IEEE Std 802.11-2020 Table E-5
> + */
> +static const struct s1g_oper_class country_class_au = {
> +	.cc = "AU",
> +	.class_count = 2,
> +	.class = {
> +	{
> +		.band_start = 902000,
> +		.start_freq = 915000,
> +		.end_freq = 920000,
> +		.max_bw_khz = MHZ_TO_KHZ(4),
> +		.align_to_end = 0,
> +		.supported_chan = au_nz_supported_channels,
> +		.n_supported_chan = sizeof(au_nz_supported_channels),
> +	},
> +	{
> +		.band_start = 902000,
> +		.start_freq = 920000,
> +		.end_freq = 928000,
> +		.max_bw_khz = MHZ_TO_KHZ(8),
> +		.align_to_end = 1,
> +		.supported_chan = NULL,
> +		.n_supported_chan = 0,
> +	}
> +	},
> +};
> +
> +static const struct s1g_oper_class country_class_nz = {
> +	.cc = "NZ",
> +	.class_count = 2,
> +	.class = {
> +	{
> +		.band_start = 902000,
> +		.start_freq = 915000,
> +		.end_freq = 924000,
> +		.max_bw_khz = MHZ_TO_KHZ(8),
> +		.align_to_end = 0,
> +		.supported_chan = au_nz_supported_channels,
> +		.n_supported_chan = sizeof(au_nz_supported_channels),
> +	},
> +	{
> +		.band_start = 902000,
> +		.start_freq = 924000,
> +		.end_freq = 928000,
> +		.max_bw_khz = MHZ_TO_KHZ(8),
> +		.align_to_end = 0,
> +		.supported_chan = NULL,
> +		.n_supported_chan = 0,
> +	}
> +	},
> +};
> +
> +static const struct s1g_oper_class country_class_us = {
> +	.cc = "US",
> +	.class_count = 3,
> +	.class = {
> +	{
> +		.band_start = 902000,
> +		.start_freq = 902000,
> +		.end_freq = 904000,
> +		.max_bw_khz = MHZ_TO_KHZ(16),
> +		.align_to_end = 0,
> +		.supported_chan = us_supported_channels,
> +		.n_supported_chan = sizeof(us_supported_channels),
> +	},
> +	{
> +		.band_start = 902000,
> +		.start_freq = 920000,
> +		.end_freq = 928000,
> +		.max_bw_khz = MHZ_TO_KHZ(16),
> +		.align_to_end = 0,
> +		.supported_chan = NULL,
> +		.n_supported_chan = 0,
> +	},
> +	{
> +		.band_start = 902000,
> +		.start_freq = 904000,
> +		.end_freq = 920000,
> +		.max_bw_khz = MHZ_TO_KHZ(16),
> +		.align_to_end = 0,
> +		.supported_chan = NULL,
> +		.n_supported_chan = 0,
> +	}
> +	},
> +};
> +
> +static const struct s1g_oper_class country_class_sg = {
> +	.cc = "SG",
> +	.class_count = 2,
> +	.class = {
> +	{
> +		.band_start = 863000,
> +		.start_freq = 866000,
> +		.end_freq = 869000,
> +		.max_bw_khz = MHZ_TO_KHZ(2),
> +		.align_to_end = 1,
> +		.supported_chan = sg_supported_channels_863,
> +		.n_supported_chan = sizeof(sg_supported_channels_863),
> +	},
> +	{
> +		.band_start = 902000,
> +		.start_freq = 920000,
> +		.end_freq = 925000,
> +		.max_bw_khz = MHZ_TO_KHZ(4),
> +		.align_to_end = 0,
> +		.supported_chan = sg_supported_channels_902,
> +		.n_supported_chan = sizeof(sg_supported_channels_902),
> +	},
> +	},
> +};
> +
> +static const struct s1g_oper_class country_class_kr = {
> +	.cc = "KR",
> +	.class_count = 1,
> +	.class = {
> +	{
> +		.band_start = 917500,
> +		.start_freq = 917500,
> +		.end_freq = 923500,
> +		.max_bw_khz = MHZ_TO_KHZ(4),
> +		.align_to_end = 1,
> +		.supported_chan = kr_supported_channels,
> +		.n_supported_chan = sizeof(kr_supported_channels),
> +	}
> +	},
> +};
> +
> +static const struct s1g_oper_class country_class_eu = {
> +	.cc = "EU",
> +	.class_count = 1,
> +	.class = {
> +	{
> +		.band_start = 863000,
> +		.start_freq = 863000,
> +		.end_freq = 868000,
> +		.max_bw_khz = MHZ_TO_KHZ(1),
> +		.align_to_end = 0,
> +		.supported_chan = eu_supported_channels_863,
> +		.n_supported_chan = sizeof(eu_supported_channels_863),
> +	},
> +	{
> +		.band_start = 901400,
> +		.start_freq = 917400,
> +		.end_freq = 919400,
> +		.max_bw_khz = MHZ_TO_KHZ(1),
> +		.align_to_end = 0,
> +		.supported_chan = eu_supported_channels_901_4,
> +		.n_supported_chan = sizeof(eu_supported_channels_901_4),
> +	}
> +	},
> +};
> +
> +static const struct s1g_oper_class country_class_jp = {
> +	.cc = "JP",
> +	.class_count = 1,
> +	.class = {
> +	{
> +		.band_start = 916500,
> +		.start_freq = 916500,
> +		.end_freq = 927500,
> +		.max_bw_khz = MHZ_TO_KHZ(1),
> +		.supported_chan = jp_supported_channels,
> +		.n_supported_chan = sizeof(jp_supported_channels),
> +	}
> +	},
> +};
> +
> +static const struct s1g_oper_class *reg_s1g_get_oper_class(const char *cc)
> +{
> +	if (!strcmp(cc, "EU"))
> +		return &country_class_eu;
> +	if (!strcmp(cc, "SG"))
> +		return &country_class_sg;
> +	if (!strcmp(cc, "US"))
> +		return &country_class_us;
> +	if (!strcmp(cc, "AU"))
> +		return &country_class_au;
> +	if (!strcmp(cc, "KR"))
> +		return &country_class_kr;
> +	if (!strcmp(cc, "JP"))
> +		return &country_class_jp;
> +	if (!strcmp(cc, "NZ"))
> +		return &country_class_nz;
> +	return &country_class_us;
> +}
> +
> +#endif /*__NET_WIRELESS_REG_S1G_H */
> diff --git a/net/wireless/util.c b/net/wireless/util.c
> index b7257862e0fe..412403d29c22 100644
> --- a/net/wireless/util.c
> +++ b/net/wireless/util.c
> @@ -22,6 +22,7 @@
>   #include <linux/nospec.h>
>   #include "core.h"
>   #include "rdev-ops.h"
> +#include "reg_s1g.h"
>   
>   
>   const struct ieee80211_rate *
> @@ -72,6 +73,23 @@ u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband,
>   }
>   EXPORT_SYMBOL(ieee80211_mandatory_rates);
>   
> +static u32 ieee80211_s1g_base_freq(int chan)
> +{
> +	const struct ieee80211_regdomain *regd  = rtnl_dereference(cfg80211_regdomain);
> +	const struct s1g_oper_class *oper = reg_s1g_get_oper_class(regd->alpha2);
> +	u8 i, j, index = 0;
> +
> +	if (oper->class_count > 1)
> +		for (i = 0; i < oper->class_count; i++)
> +			for (j = 0; j < oper->class[i].n_supported_chan; j++)
> +				if (oper->class[i].supported_chan[j] == chan) {
> +					index = i;
> +					goto out;
> +				}
> +out:
> +	return oper->class[index].band_start;
> +}
> +
>   u32 ieee80211_channel_to_freq_khz(int chan, enum nl80211_band band)
>   {
>   	/* see 802.11 17.3.8.3.2 and Annex J
> @@ -104,7 +122,7 @@ u32 ieee80211_channel_to_freq_khz(int chan, enum nl80211_band band)
>   			return MHZ_TO_KHZ(56160 + chan * 2160);
>   		break;
>   	case NL80211_BAND_S1GHZ:
> -		return 902000 + chan * 500;
> +		return ieee80211_s1g_base_freq(chan) + chan * 500;
>   	default:
>   		;
>   	}
> @@ -112,6 +130,17 @@ u32 ieee80211_channel_to_freq_khz(int chan, enum nl80211_band band)
>   }
>   EXPORT_SYMBOL(ieee80211_channel_to_freq_khz);
>   
> +u32 ieee80211_s1g_channel_to_freq_khz(int chan)
> +{
> +	u32 base = ieee80211_s1g_base_freq(chan);
> +
> +	if (!base)

how can this be 0 since ieee80211_s1g_base_freq() always returns 
oper->class[index].band_start and none of the entries has 0 as a band_start?

> +		return 0;
> +
> +	return (base + chan * 500);
> +}
> +EXPORT_SYMBOL(ieee80211_s1g_channel_to_freq_khz);
> +
>   enum nl80211_chan_width
>   ieee80211_s1g_channel_width(const struct ieee80211_channel *chan)
>   {


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 04/12] nl80211: support setting S1G short beacon period
  2022-07-11  1:08 ` [PATCH 04/12] nl80211: support setting S1G short beacon period Kieran Frewen
@ 2022-07-12 22:08   ` Jeff Johnson
  0 siblings, 0 replies; 19+ messages in thread
From: Jeff Johnson @ 2022-07-12 22:08 UTC (permalink / raw)
  To: Kieran Frewen, johannes; +Cc: linux-wireless, Bassem Dawood

On 7/10/2022 6:08 PM, Kieran Frewen wrote:
> With the kernel able to send both short and long S1G beacons, include
> the ability for setting the short beacon period.
> 
> Signed-off-by: Kieran Frewen <kieran.frewen@morsemicro.com>
> Signed-off-by: Bassem Dawood <bassem@morsemicro.com>
> ---
>   include/uapi/linux/nl80211.h | 6 ++++++
>   net/wireless/nl80211.c       | 4 ++++
>   2 files changed, 10 insertions(+)
> 
> diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
> index 89f64f46b98d..bd6e2cae1dd3 100644
> --- a/include/uapi/linux/nl80211.h
> +++ b/include/uapi/linux/nl80211.h
> @@ -2694,6 +2694,8 @@ enum nl80211_commands {
>    *	connection. Used with %NL80211_CMD_CONNECT. If this attribute is not
>    *	included in NL80211_CMD_CONNECT drivers must not perform MLO connection.
>    *
> + * @NL80211_ATTR_SHORT_BEACON_PERIOD: S1G short beacon period in TUs.
> + *
>    * @NUM_NL80211_ATTR: total number of nl80211_attrs available
>    * @NL80211_ATTR_MAX: highest attribute number currently defined
>    * @__NL80211_ATTR_AFTER_LAST: internal use
> @@ -3214,6 +3216,8 @@ enum nl80211_attrs {
>   
>   	NL80211_ATTR_MLO_SUPPORT,
>   
> +	NL80211_ATTR_SHORT_BEACON_PERIOD,
> +
>   	/* add attributes here, update the policy in nl80211.c */
>   
>   	__NL80211_ATTR_AFTER_LAST,
> @@ -4890,6 +4894,7 @@ enum nl80211_bss_scan_width {
>    *	Contains a nested array of signal strength attributes (u8, dBm),
>    *	using the nesting index as the antenna number.
>    * @NL80211_BSS_FREQUENCY_OFFSET: frequency offset in KHz
> + * @NL80211_BSS_SHORT_BEACON_PERIOD: S1G short beacon period in TUs
>    * @__NL80211_BSS_AFTER_LAST: internal
>    * @NL80211_BSS_MAX: highest BSS attribute
>    */
> @@ -4915,6 +4920,7 @@ enum nl80211_bss {
>   	NL80211_BSS_PARENT_BSSID,
>   	NL80211_BSS_CHAIN_SIGNAL,
>   	NL80211_BSS_FREQUENCY_OFFSET,
> +	NL80211_BSS_SHORT_BEACON_PERIOD,

please rebase against latest wireless-next since a new attribute 
NL80211_BSS_MLO_LINK_ID was very recently added

>   
>   	/* keep last */
>   	__NL80211_BSS_AFTER_LAST,
> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index 6a45801c783c..ab47e4130141 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -798,6 +798,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
>   		NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS),
>   	[NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
>   	[NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
> +	[NL80211_ATTR_SHORT_BEACON_PERIOD] = { .type = NLA_U32 },

entire range of u32 values are valid?

IEEE Std 802.11-2020 Figure 9-684—Short Beacon Interval element format 
indicates a 2 octet field, so consider either changing the type to U16 
or use NLA_POLICY_RANGE() to align with the MIB definition:
dot11ShortBeaconPeriod OBJECT-TYPE
SYNTAX Unsigned32 (1..65535)


>   };
>   
>   /* policy for the key attributes */
> @@ -5654,6 +5655,9 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
>   		nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
>   	params->dtim_period =
>   		nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
> +	if (info->attrs[NL80211_ATTR_SHORT_BEACON_PERIOD])
> +		params->short_beacon_period =
> +			nla_get_u32(info->attrs[NL80211_ATTR_SHORT_BEACON_PERIOD]);
>   
>   	err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
>   					   params->beacon_interval);


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 06/12] mac80211: support ieee80211_ext format
  2022-07-11  1:08 ` [PATCH 06/12] mac80211: support ieee80211_ext format Kieran Frewen
@ 2022-07-12 22:18   ` Jeff Johnson
  0 siblings, 0 replies; 19+ messages in thread
From: Jeff Johnson @ 2022-07-12 22:18 UTC (permalink / raw)
  To: Kieran Frewen, johannes; +Cc: linux-wireless, Bassem Dawood

On 7/10/2022 6:08 PM, Kieran Frewen wrote:
> Ensure S1G beacons use the new ieee80211_ext format when required.
> 
> Signed-off-by: Kieran Frewen <kieran.frewen@morsemicro.com>
> Signed-off-by: Bassem Dawood <bassem@morsemicro.com>
> ---
>   net/mac80211/rx.c | 24 +++++++++++++++++-------
>   1 file changed, 17 insertions(+), 7 deletions(-)
> 
> diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
> index d017ad14d7db..feab1d58e932 100644
> --- a/net/mac80211/rx.c
> +++ b/net/mac80211/rx.c
> @@ -4772,6 +4772,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
>   	struct ieee80211_local *local = hw_to_local(hw);
>   	struct ieee80211_sub_if_data *sdata;
>   	struct ieee80211_hdr *hdr;
> +	struct ieee80211_ext *ext_hdr;
>   	__le16 fc;
>   	struct ieee80211_rx_data rx;
>   	struct ieee80211_sub_if_data *prev;
> @@ -4787,7 +4788,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
>   	if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
>   		I802_DEBUG_INC(local->dot11ReceivedFragmentCount);
>   
> -	if (ieee80211_is_mgmt(fc)) {
> +	if (ieee80211_is_mgmt(fc) || ieee80211_is_s1g_beacon(fc)) {
>   		/* drop frame if too short for header */
>   		if (skb->len < ieee80211_hdrlen(fc))
>   			err = -ENOBUFS;
> @@ -4802,13 +4803,16 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
>   		return;
>   	}
>   
> -	hdr = (struct ieee80211_hdr *)skb->data;
> +	if (ieee80211_is_s1g_beacon(fc))
> +		ext_hdr = (struct ieee80211_ext *)skb->data;
> +	else
> +		hdr = (struct ieee80211_hdr *)skb->data;

consider extracting the SA here instead of having conditional code in 
two places later?

>   	ieee80211_parse_qos(&rx);
>   	ieee80211_verify_alignment(&rx);
>   
> -	if (unlikely(ieee80211_is_probe_resp(hdr->frame_control) ||
> -		     ieee80211_is_beacon(hdr->frame_control) ||
> -		     ieee80211_is_s1g_beacon(hdr->frame_control)))
> +	if (unlikely(ieee80211_is_probe_resp(fc) ||
> +		     ieee80211_is_beacon(fc) ||
> +		     ieee80211_is_s1g_beacon(fc)))
>   		ieee80211_scan_rx(local, skb);
>   
>   	if (ieee80211_is_data(fc)) {
> @@ -4868,7 +4872,10 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
>   			continue;
>   		}
>   
> -		rx.sta = sta_info_get_bss(prev, hdr->addr2);
> +		if (ieee80211_is_s1g_beacon(fc))
> +			rx.sta = sta_info_get_bss(prev, ext_hdr->u.s1g_beacon.sa);
> +		else
> +			rx.sta = sta_info_get_bss(prev, hdr->addr2);
>   		rx.sdata = prev;
>   		ieee80211_prepare_and_rx_handle(&rx, skb, false);
>   
> @@ -4876,7 +4883,10 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
>   	}
>   
>   	if (prev) {
> -		rx.sta = sta_info_get_bss(prev, hdr->addr2);
> +		if (ieee80211_is_s1g_beacon(fc))
> +			rx.sta = sta_info_get_bss(prev, ext_hdr->u.s1g_beacon.sa);
> +		else
> +			rx.sta = sta_info_get_bss(prev, hdr->addr2);
>   		rx.sdata = prev;
>   
>   		if (ieee80211_prepare_and_rx_handle(&rx, skb, true))


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 07/12] mac80211: S1G capabilities information element in probe request
  2022-07-11  1:08 ` [PATCH 07/12] mac80211: S1G capabilities information element in probe request Kieran Frewen
@ 2022-07-12 22:23   ` Jeff Johnson
  0 siblings, 0 replies; 19+ messages in thread
From: Jeff Johnson @ 2022-07-12 22:23 UTC (permalink / raw)
  To: Kieran Frewen, johannes; +Cc: linux-wireless, Bassem Dawood

On 7/10/2022 6:08 PM, Kieran Frewen wrote:
> Add the missing S1G capabilities information element to probe requests.
> 
> Signed-off-by: Kieran Frewen <kieran.frewen@morsemicro.com>
> Signed-off-by: Bassem Dawood <bassem@morsemicro.com>
> ---
>   net/mac80211/util.c | 37 +++++++++++++++++++++++++++++++++++++
>   1 file changed, 37 insertions(+)
> 
> diff --git a/net/mac80211/util.c b/net/mac80211/util.c
> index bccc3a309ed0..51a2c1dee360 100644
> --- a/net/mac80211/util.c
> +++ b/net/mac80211/util.c
> @@ -1832,6 +1832,43 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_sub_if_data *sdata,
>   	rate_flags = ieee80211_chandef_rate_flags(chandef);
>   	shift = ieee80211_chandef_get_shift(chandef);
>   
> +	/* For direct mac80211 scan (probe request), add S1G IE and consider its override bits */
> +	if (band == NL80211_BAND_S1GHZ) {
> +		struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
> +		struct ieee80211_s1g_cap s1g_capab;
> +
> +		*pos++ = WLAN_EID_S1G_CAPABILITIES;
> +		*pos++ = sizeof(s1g_capab);
> +

why create s1g_capab on the stack and then copy into place?
why not create it directly in place and avoid the copy?

> +		memcpy(s1g_capab.capab_info,
> +		       sband->s1g_cap.cap,
> +		       sizeof(sband->s1g_cap.cap));
> +		memcpy(s1g_capab.supp_mcs_nss,
> +		       sband->s1g_cap.nss_mcs,
> +		       sizeof(sband->s1g_cap.nss_mcs));
> +
> +		/* override the capability info */
> +		for (i = 0; i < sizeof(ifmgd->s1g_capa.capab_info); i++) {
> +			u8 mask = ifmgd->s1g_capa_mask.capab_info[i];
> +
> +			s1g_capab.capab_info[i] &= ~mask;
> +			s1g_capab.capab_info[i] |= ifmgd->s1g_capa.capab_info[i] & mask;
> +		}
> +
> +		/* then MCS and NSS set */
> +		for (i = 0; i < sizeof(ifmgd->s1g_capa.supp_mcs_nss); i++) {
> +			u8 mask = ifmgd->s1g_capa_mask.supp_mcs_nss[i];
> +
> +			s1g_capab.supp_mcs_nss[i] &= ~mask;
> +			s1g_capab.supp_mcs_nss[i] |= ifmgd->s1g_capa.supp_mcs_nss[i] & mask;
> +		}
> +
> +		memcpy(pos, &s1g_capab, sizeof(s1g_capab));
> +		pos += sizeof(s1g_capab);
> +		/* No more IEs relevant for S1G */
> +		goto done;
> +	}
> +
>   	num_rates = 0;
>   	for (i = 0; i < sband->n_bitrates; i++) {
>   		if ((BIT(i) & rate_mask) == 0)


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 08/12] cfg80211: S1G rate flags
  2022-07-11  1:08 ` [PATCH 08/12] cfg80211: S1G rate flags Kieran Frewen
@ 2022-07-12 22:36   ` Jeff Johnson
  0 siblings, 0 replies; 19+ messages in thread
From: Jeff Johnson @ 2022-07-12 22:36 UTC (permalink / raw)
  To: Kieran Frewen, johannes; +Cc: linux-wireless, Bassem Dawood

On 7/10/2022 6:08 PM, Kieran Frewen wrote:
> Increase the size of S1G rate_info flags to support S1G. Add flags for new
> S1G bandwidths and S1G MCS.
> 
> Signed-off-by: Kieran Frewen <kieran.frewen@morsemicro.com>
> Signed-off-by: Bassem Dawood <bassem@morsemicro.com>
> ---
>   include/net/cfg80211.h | 14 +++++++++++++-
>   1 file changed, 13 insertions(+), 1 deletion(-)
> 
> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> index 7859b8b11968..47f71fb5d07a 100644
> --- a/include/net/cfg80211.h
> +++ b/include/net/cfg80211.h
> @@ -1608,6 +1608,7 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
>    * @RATE_INFO_FLAGS_EDMG: 60GHz MCS in EDMG mode
>    * @RATE_INFO_FLAGS_EXTENDED_SC_DMG: 60GHz extended SC MCS
>    * @RATE_INFO_FLAGS_EHT_MCS: EHT MCS information
> + * @RATE_INFO_FLAGS_S1G_MCS: mcs field filled with S1G MCS

nit: s/mcs/MCS/

>    */
>   enum rate_info_flags {
>   	RATE_INFO_FLAGS_MCS			= BIT(0),
> @@ -1618,6 +1619,7 @@ enum rate_info_flags {
>   	RATE_INFO_FLAGS_EDMG			= BIT(5),
>   	RATE_INFO_FLAGS_EXTENDED_SC_DMG		= BIT(6),
>   	RATE_INFO_FLAGS_EHT_MCS			= BIT(7),
> +	RATE_INFO_FLAGS_S1G_MCS                 = BIT(8),
>   };
>   
>   /**
> @@ -1634,6 +1636,11 @@ enum rate_info_flags {
>    * @RATE_INFO_BW_HE_RU: bandwidth determined by HE RU allocation
>    * @RATE_INFO_BW_320: 320 MHz bandwidth
>    * @RATE_INFO_BW_EHT_RU: bandwidth determined by EHT RU allocation
> + * @RATE_INFO_BW_1: 1 MHz bandwidth
> + * @RATE_INFO_BW_2: 2 MHz bandwidth
> + * @RATE_INFO_BW_4: 4 MHz bandwidth
> + * @RATE_INFO_BW_8: 8 MHz bandwidth
> + * @RATE_INFO_BW_16: 16 MHz bandwidth
>    */
>   enum rate_info_bw {
>   	RATE_INFO_BW_20 = 0,
> @@ -1645,6 +1652,11 @@ enum rate_info_bw {
>   	RATE_INFO_BW_HE_RU,
>   	RATE_INFO_BW_320,
>   	RATE_INFO_BW_EHT_RU,
> +	RATE_INFO_BW_1,
> +	RATE_INFO_BW_2,
> +	RATE_INFO_BW_4,
> +	RATE_INFO_BW_8,
> +	RATE_INFO_BW_16,
>   };
>   
>   /**
> @@ -1667,7 +1679,7 @@ enum rate_info_bw {
>    *	only valid if bw is %RATE_INFO_BW_EHT_RU)
>    */
>   struct rate_info {
> -	u8 flags;
> +	u16 flags;
>   	u8 mcs;
>   	u16 legacy;
>   	u8 nss;

should we group legacy with flags so that the two u16s are adjacent?
note unfortunately we can't avoid padding


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 09/12] nl80211: support advertising S1G rate information
  2022-07-11  1:08 ` [PATCH 09/12] nl80211: support advertising S1G rate information Kieran Frewen
@ 2022-07-13  0:48   ` Jeff Johnson
  0 siblings, 0 replies; 19+ messages in thread
From: Jeff Johnson @ 2022-07-13  0:48 UTC (permalink / raw)
  To: Kieran Frewen, johannes; +Cc: linux-wireless, Bassem Dawood

On 7/10/2022 6:08 PM, Kieran Frewen wrote:
> Add S1G rate information to netlink STA rate message.
> 
> Signed-off-by: Kieran Frewen <kieran.frewen@morsemicro.com>
> Signed-off-by: Bassem Dawood <bassem@morsemicro.com>
> ---
>   include/uapi/linux/nl80211.h | 14 ++++++++++++++
>   net/wireless/nl80211.c       | 23 +++++++++++++++++++++++
>   2 files changed, 37 insertions(+)
> 
> diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
> index 71074332ccc5..19cf030004e9 100644
> --- a/include/uapi/linux/nl80211.h
> +++ b/include/uapi/linux/nl80211.h
> @@ -3539,6 +3539,13 @@ enum nl80211_eht_ru_alloc {
>    *	(u8, see &enum nl80211_eht_gi)
>    * @NL80211_RATE_INFO_EHT_RU_ALLOC: EHT RU allocation, if not present then
>    *	non-OFDMA was used (u8, see &enum nl80211_eht_ru_alloc)
> + * @NL80211_RATE_INFO_S1G_MCS: S1G MCS index (u8, 0-10)
> + * @NL80211_RATE_INFO_S1G_nss: S1G NSS value (u8, 1-4)

nit: s/nss/NSS/

> + * @NL80211_RATE_INFO_1_MHZ_WIDTH: 1 MHz S1G rate
> + * @NL80211_RATE_INFO_2_MHZ_WIDTH: 2 MHz S1G rate
> + * @NL80211_RATE_INFO_4_MHZ_WIDTH: 4 MHz S1G rate
> + * @NL80211_RATE_INFO_8_MHZ_WIDTH: 8 MHz S1G rate
> + * @NL80211_RATE_INFO_16_MHZ_WIDTH: 16 MHz S1G rate
>    * @__NL80211_RATE_INFO_AFTER_LAST: internal use
>    */
>   enum nl80211_rate_info {
> @@ -3565,6 +3572,13 @@ enum nl80211_rate_info {
>   	NL80211_RATE_INFO_EHT_NSS,
>   	NL80211_RATE_INFO_EHT_GI,
>   	NL80211_RATE_INFO_EHT_RU_ALLOC,
> +	NL80211_RATE_INFO_S1G_MCS,
> +	NL80211_RATE_INFO_S1G_NSS,
> +	NL80211_RATE_INFO_1_MHZ_WIDTH,
> +	NL80211_RATE_INFO_2_MHZ_WIDTH,
> +	NL80211_RATE_INFO_4_MHZ_WIDTH,
> +	NL80211_RATE_INFO_8_MHZ_WIDTH,
> +	NL80211_RATE_INFO_16_MHZ_WIDTH,
>   
>   	/* keep last */
>   	__NL80211_RATE_INFO_AFTER_LAST,
> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index 077dc2938551..70efed2b5899 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -6073,6 +6073,21 @@ bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
>   		return false;
>   
>   	switch (info->bw) {
> +	case RATE_INFO_BW_1:
> +		rate_flg = NL80211_RATE_INFO_1_MHZ_WIDTH;
> +		break;
> +	case RATE_INFO_BW_2:
> +		rate_flg = NL80211_RATE_INFO_2_MHZ_WIDTH;
> +		break;
> +	case RATE_INFO_BW_4:
> +		rate_flg = NL80211_RATE_INFO_4_MHZ_WIDTH;
> +		break;
> +	case RATE_INFO_BW_8:
> +		rate_flg = NL80211_RATE_INFO_8_MHZ_WIDTH;
> +		break;
> +	case RATE_INFO_BW_16:
> +		rate_flg = NL80211_RATE_INFO_16_MHZ_WIDTH;
> +		break;

does it make sense to order these 1 2 4 5 8 10 16 20...

>   	case RATE_INFO_BW_5:
>   		rate_flg = NL80211_RATE_INFO_5_MHZ_WIDTH;
>   		break;
> @@ -6137,6 +6152,14 @@ bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
>   		    nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC,
>   			       info->he_ru_alloc))
>   			return false;
> +	} else if (info->flags & RATE_INFO_FLAGS_S1G_MCS) {
> +		if (nla_put_u8(msg, NL80211_RATE_INFO_S1G_MCS, info->mcs))
> +			return false;
> +		if (nla_put_u8(msg, NL80211_RATE_INFO_S1G_NSS, info->nss))
> +			return false;
> +		if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
> +		    nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
> +			return false;
>   	} else if (info->flags & RATE_INFO_FLAGS_EHT_MCS) {
>   		if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_MCS, info->mcs))
>   			return false;


^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2022-07-13  0:48 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-11  1:08 [PATCH 00/12] Additional support for 802.11ah (S1G) Kieran Frewen
2022-07-11  1:08 ` [PATCH 01/12] cfg80211: regulatory: extend regulatory support for S1G Kieran Frewen
2022-07-11 17:47   ` Jeff Johnson
2022-07-11  1:08 ` [PATCH 02/12] mac80211: update TIM for S1G specification changes Kieran Frewen
2022-07-11  1:08 ` [PATCH 03/12] mac80211: S1G beacon/short beacon support Kieran Frewen
2022-07-11  1:08 ` [PATCH 04/12] nl80211: support setting S1G short beacon period Kieran Frewen
2022-07-12 22:08   ` Jeff Johnson
2022-07-11  1:08 ` [PATCH 05/12] nl80211: support advertising S1G capabilities Kieran Frewen
2022-07-11  1:08 ` [PATCH 06/12] mac80211: support ieee80211_ext format Kieran Frewen
2022-07-12 22:18   ` Jeff Johnson
2022-07-11  1:08 ` [PATCH 07/12] mac80211: S1G capabilities information element in probe request Kieran Frewen
2022-07-12 22:23   ` Jeff Johnson
2022-07-11  1:08 ` [PATCH 08/12] cfg80211: S1G rate flags Kieran Frewen
2022-07-12 22:36   ` Jeff Johnson
2022-07-11  1:08 ` [PATCH 09/12] nl80211: support advertising S1G rate information Kieran Frewen
2022-07-13  0:48   ` Jeff Johnson
2022-07-11  1:08 ` [PATCH 10/12] mac80211: support S1G rate encoding Kieran Frewen
2022-07-11  1:08 ` [PATCH 11/12] cfg80211: support for calculating S1G bitrates Kieran Frewen
2022-07-11  1:08 ` [PATCH 12/12] mac80211_hwsim: support for S1G rate information Kieran Frewen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).