+/* 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)