From 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 10 May 2024 07:44:59 +0000
Subject: [PATCH] gmac get mac form eeprom
---
kernel/net/wireless/util.c | 382 ++++++++++++++++++++++++++++++++++++++++++------------
1 files changed, 294 insertions(+), 88 deletions(-)
diff --git a/kernel/net/wireless/util.c b/kernel/net/wireless/util.c
index 1178128..423fc9e 100644
--- a/kernel/net/wireless/util.c
+++ b/kernel/net/wireless/util.c
@@ -5,17 +5,21 @@
* Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018-2020 Intel Corporation
*/
#include <linux/export.h>
#include <linux/bitops.h>
#include <linux/etherdevice.h>
#include <linux/slab.h>
+#include <linux/ieee80211.h>
#include <net/cfg80211.h>
#include <net/ip.h>
#include <net/dsfield.h>
#include <linux/if_vlan.h>
#include <linux/mpls.h>
#include <linux/gcd.h>
+#include <linux/bitfield.h>
+#include <linux/nospec.h>
#include "core.h"
#include "rdev-ops.h"
@@ -68,7 +72,7 @@
}
EXPORT_SYMBOL(ieee80211_mandatory_rates);
-int ieee80211_channel_to_frequency(int chan, enum nl80211_band band)
+u32 ieee80211_channel_to_freq_khz(int chan, enum nl80211_band band)
{
/* see 802.11 17.3.8.3.2 and Annex J
* there are overlapping channel numbers in 5GHz and 2GHz bands */
@@ -77,29 +81,68 @@
switch (band) {
case NL80211_BAND_2GHZ:
if (chan == 14)
- return 2484;
+ return MHZ_TO_KHZ(2484);
else if (chan < 14)
- return 2407 + chan * 5;
+ return MHZ_TO_KHZ(2407 + chan * 5);
break;
case NL80211_BAND_5GHZ:
if (chan >= 182 && chan <= 196)
- return 4000 + chan * 5;
+ return MHZ_TO_KHZ(4000 + chan * 5);
else
- return 5000 + chan * 5;
+ return MHZ_TO_KHZ(5000 + chan * 5);
+ break;
+ case NL80211_BAND_6GHZ:
+ /* see 802.11ax D6.1 27.3.23.2 */
+ if (chan == 2)
+ return MHZ_TO_KHZ(5935);
+ if (chan <= 233)
+ return MHZ_TO_KHZ(5950 + chan * 5);
break;
case NL80211_BAND_60GHZ:
- if (chan < 5)
- return 56160 + chan * 2160;
+ if (chan < 7)
+ return MHZ_TO_KHZ(56160 + chan * 2160);
break;
+ case NL80211_BAND_S1GHZ:
+ return 902000 + chan * 500;
default:
;
}
return 0; /* not supported */
}
-EXPORT_SYMBOL(ieee80211_channel_to_frequency);
+EXPORT_SYMBOL(ieee80211_channel_to_freq_khz);
-int ieee80211_frequency_to_channel(int freq)
+enum nl80211_chan_width
+ieee80211_s1g_channel_width(const struct ieee80211_channel *chan)
{
+ if (WARN_ON(!chan || chan->band != NL80211_BAND_S1GHZ))
+ return NL80211_CHAN_WIDTH_20_NOHT;
+
+ /*S1G defines a single allowed channel width per channel.
+ * Extract that width here.
+ */
+ if (chan->flags & IEEE80211_CHAN_1MHZ)
+ return NL80211_CHAN_WIDTH_1;
+ else if (chan->flags & IEEE80211_CHAN_2MHZ)
+ return NL80211_CHAN_WIDTH_2;
+ else if (chan->flags & IEEE80211_CHAN_4MHZ)
+ return NL80211_CHAN_WIDTH_4;
+ else if (chan->flags & IEEE80211_CHAN_8MHZ)
+ return NL80211_CHAN_WIDTH_8;
+ else if (chan->flags & IEEE80211_CHAN_16MHZ)
+ return NL80211_CHAN_WIDTH_16;
+
+ pr_err("unknown channel width for channel at %dKHz?\n",
+ ieee80211_channel_to_khz(chan));
+
+ return NL80211_CHAN_WIDTH_1;
+}
+EXPORT_SYMBOL(ieee80211_s1g_channel_width);
+
+int ieee80211_freq_khz_to_channel(u32 freq)
+{
+ /* TODO: just handle MHz for now */
+ freq = KHZ_TO_MHZ(freq);
+
/* see 802.11 17.3.8.3.2 and Annex J */
if (freq == 2484)
return 14;
@@ -107,16 +150,22 @@
return (freq - 2407) / 5;
else if (freq >= 4910 && freq <= 4980)
return (freq - 4000) / 5;
- else if (freq <= 45000) /* DMG band lower limit */
+ else if (freq < 5925)
return (freq - 5000) / 5;
- else if (freq >= 58320 && freq <= 64800)
+ else if (freq == 5935)
+ return 2;
+ else if (freq <= 45000) /* DMG band lower limit */
+ /* see 802.11ax D6.1 27.3.22.2 */
+ return (freq - 5950) / 5;
+ else if (freq >= 58320 && freq <= 70200)
return (freq - 56160) / 2160;
else
return 0;
}
-EXPORT_SYMBOL(ieee80211_frequency_to_channel);
+EXPORT_SYMBOL(ieee80211_freq_khz_to_channel);
-struct ieee80211_channel *ieee80211_get_channel(struct wiphy *wiphy, int freq)
+struct ieee80211_channel *ieee80211_get_channel_khz(struct wiphy *wiphy,
+ u32 freq)
{
enum nl80211_band band;
struct ieee80211_supported_band *sband;
@@ -129,14 +178,16 @@
continue;
for (i = 0; i < sband->n_channels; i++) {
- if (sband->channels[i].center_freq == freq)
- return &sband->channels[i];
+ struct ieee80211_channel *chan = &sband->channels[i];
+
+ if (ieee80211_channel_to_khz(chan) == freq)
+ return chan;
}
}
return NULL;
}
-EXPORT_SYMBOL(ieee80211_get_channel);
+EXPORT_SYMBOL(ieee80211_get_channel_khz);
static void set_mandatory_flags_band(struct ieee80211_supported_band *sband)
{
@@ -144,6 +195,7 @@
switch (sband->band) {
case NL80211_BAND_5GHZ:
+ case NL80211_BAND_6GHZ:
want = 3;
for (i = 0; i < sband->n_bitrates; i++) {
if (sband->bitrates[i].bitrate == 60 ||
@@ -175,7 +227,7 @@
sband->bitrates[i].flags |=
IEEE80211_RATE_MANDATORY_G;
want--;
- /* fall through */
+ fallthrough;
default:
sband->bitrates[i].flags |=
IEEE80211_RATE_ERP_G;
@@ -188,6 +240,12 @@
/* check for mandatory HT MCS 1..4 */
WARN_ON(!sband->ht_cap.ht_supported);
WARN_ON((sband->ht_cap.mcs.rx_mask[0] & 0x1e) != 0x1e);
+ break;
+ case NL80211_BAND_S1GHZ:
+ /* Figure 9-589bd: 3 means unsupported, so != 3 means at least
+ * mandatory is ok.
+ */
+ WARN_ON((sband->s1g_cap.nss_mcs[0] & 0x3) == 0x3);
break;
case NUM_NL80211_BANDS:
default:
@@ -241,7 +299,9 @@
if (pairwise)
max_key_idx = 3;
else if (wiphy_ext_feature_isset(&rdev->wiphy,
- NL80211_EXT_FEATURE_BEACON_PROTECTION))
+ NL80211_EXT_FEATURE_BEACON_PROTECTION) ||
+ wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
max_key_idx = 7;
else if (cfg80211_igtk_cipher_supported(rdev))
max_key_idx = 5;
@@ -269,18 +329,32 @@
switch (params->cipher) {
case WLAN_CIPHER_SUITE_TKIP:
+ /* Extended Key ID can only be used with CCMP/GCMP ciphers */
+ if ((pairwise && key_idx) ||
+ params->mode != NL80211_KEY_RX_TX)
+ return -EINVAL;
+ break;
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_CCMP_256:
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
- /* Disallow pairwise keys with non-zero index unless it's WEP
- * or a vendor specific cipher (because current deployments use
- * pairwise WEP keys with non-zero indices and for vendor
- * specific ciphers this should be validated in the driver or
- * hardware level - but 802.11i clearly specifies to use zero)
+ /* IEEE802.11-2016 allows only 0 and - when supporting
+ * Extended Key ID - 1 as index for pairwise keys.
+ * @NL80211_KEY_NO_TX is only allowed for pairwise keys when
+ * the driver supports Extended Key ID.
+ * @NL80211_KEY_SET_TX can't be set when installing and
+ * validating a key.
*/
- if (pairwise && key_idx)
+ if ((params->mode == NL80211_KEY_NO_TX && !pairwise) ||
+ params->mode == NL80211_KEY_SET_TX)
return -EINVAL;
+ if (wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_EXT_KEY_ID)) {
+ if (pairwise && (key_idx < 0 || key_idx > 1))
+ return -EINVAL;
+ } else if (pairwise && key_idx) {
+ return -EINVAL;
+ }
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
@@ -386,6 +460,11 @@
unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc)
{
unsigned int hdrlen = 24;
+
+ if (ieee80211_is_ext(fc)) {
+ hdrlen = 4;
+ goto out;
+ }
if (ieee80211_is_data(fc)) {
if (ieee80211_has_a4(fc))
@@ -755,20 +834,25 @@
{
unsigned int dscp;
unsigned char vlan_priority;
+ unsigned int ret;
/* skb->priority values from 256->263 are magic values to
* directly indicate a specific 802.1d priority. This is used
* to allow 802.1d priority to be passed directly in from VLAN
* tags, etc.
*/
- if (skb->priority >= 256 && skb->priority <= 263)
- return skb->priority - 256;
+ if (skb->priority >= 256 && skb->priority <= 263) {
+ ret = skb->priority - 256;
+ goto out;
+ }
if (skb_vlan_tag_present(skb)) {
vlan_priority = (skb_vlan_tag_get(skb) & VLAN_PRIO_MASK)
>> VLAN_PRIO_SHIFT;
- if (vlan_priority > 0)
- return vlan_priority;
+ if (vlan_priority > 0) {
+ ret = vlan_priority;
+ goto out;
+ }
}
switch (skb->protocol) {
@@ -787,8 +871,9 @@
if (!mpls)
return 0;
- return (ntohl(mpls->entry) & MPLS_LS_TC_MASK)
+ ret = (ntohl(mpls->entry) & MPLS_LS_TC_MASK)
>> MPLS_LS_TC_SHIFT;
+ goto out;
}
case htons(ETH_P_80221):
/* 802.21 is always network control traffic */
@@ -801,22 +886,28 @@
unsigned int i, tmp_dscp = dscp >> 2;
for (i = 0; i < qos_map->num_des; i++) {
- if (tmp_dscp == qos_map->dscp_exception[i].dscp)
- return qos_map->dscp_exception[i].up;
+ if (tmp_dscp == qos_map->dscp_exception[i].dscp) {
+ ret = qos_map->dscp_exception[i].up;
+ goto out;
+ }
}
for (i = 0; i < 8; i++) {
if (tmp_dscp >= qos_map->up[i].low &&
- tmp_dscp <= qos_map->up[i].high)
- return i;
+ tmp_dscp <= qos_map->up[i].high) {
+ ret = i;
+ goto out;
+ }
}
}
- return dscp >> 5;
+ ret = dscp >> 5;
+out:
+ return array_index_nospec(ret, IEEE80211_NUM_TIDS);
}
EXPORT_SYMBOL(cfg80211_classify8021d);
-const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie)
+const struct element *ieee80211_bss_get_elem(struct cfg80211_bss *bss, u8 id)
{
const struct cfg80211_bss_ies *ies;
@@ -824,9 +915,9 @@
if (!ies)
return NULL;
- return cfg80211_find_ie(ie, ies->data, ies->len);
+ return cfg80211_find_elem(id, ies->data, ies->len);
}
-EXPORT_SYMBOL(ieee80211_bss_get_ie);
+EXPORT_SYMBOL(ieee80211_bss_get_elem);
void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
{
@@ -852,7 +943,7 @@
}
}
- kzfree(wdev->connect_keys);
+ kfree_sensitive(wdev->connect_keys);
wdev->connect_keys = NULL;
}
@@ -937,14 +1028,14 @@
!(rdev->wiphy.interface_modes & (1 << ntype)))
return -EOPNOTSUPP;
- /* if it's part of a bridge, reject changing type to station/ibss */
- if ((dev->priv_flags & IFF_BRIDGE_PORT) &&
- (ntype == NL80211_IFTYPE_ADHOC ||
- ntype == NL80211_IFTYPE_STATION ||
- ntype == NL80211_IFTYPE_P2P_CLIENT))
- return -EBUSY;
-
if (ntype != otype) {
+ /* if it's part of a bridge, reject changing type to station/ibss */
+ if (netif_is_bridge_port(dev) &&
+ (ntype == NL80211_IFTYPE_ADHOC ||
+ ntype == NL80211_IFTYPE_STATION ||
+ ntype == NL80211_IFTYPE_P2P_CLIENT))
+ return -EBUSY;
+
dev->ieee80211_ptr->use_4addr = false;
dev->ieee80211_ptr->mesh_id_up_len = 0;
wdev_lock(dev->ieee80211_ptr);
@@ -993,7 +1084,7 @@
case NL80211_IFTYPE_STATION:
if (dev->ieee80211_ptr->use_4addr)
break;
- /* fall through */
+ fallthrough;
case NL80211_IFTYPE_OCB:
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_ADHOC:
@@ -1227,20 +1318,22 @@
static u32 cfg80211_calculate_bitrate_he(struct rate_info *rate)
{
-#define SCALE 2048
- u16 mcs_divisors[12] = {
- 34133, /* 16.666666... */
- 17067, /* 8.333333... */
- 11378, /* 5.555555... */
- 8533, /* 4.166666... */
- 5689, /* 2.777777... */
- 4267, /* 2.083333... */
- 3923, /* 1.851851... */
- 3413, /* 1.666666... */
- 2844, /* 1.388888... */
- 2560, /* 1.250000... */
- 2276, /* 1.111111... */
- 2048, /* 1.000000... */
+#define SCALE 6144
+ u32 mcs_divisors[14] = {
+ 102399, /* 16.666666... */
+ 51201, /* 8.333333... */
+ 34134, /* 5.555555... */
+ 25599, /* 4.166666... */
+ 17067, /* 2.777777... */
+ 12801, /* 2.083333... */
+ 11769, /* 1.851851... */
+ 10239, /* 1.666666... */
+ 8532, /* 1.388888... */
+ 7680, /* 1.250000... */
+ 6828, /* 1.111111... */
+ 6144, /* 1.000000... */
+ 5690, /* 0.926106... */
+ 5120, /* 0.833333... */
};
u32 rates_160M[3] = { 960777777, 907400000, 816666666 };
u32 rates_969[3] = { 480388888, 453700000, 408333333 };
@@ -1252,7 +1345,7 @@
u64 tmp;
u32 result;
- if (WARN_ON_ONCE(rate->mcs > 11))
+ if (WARN_ON_ONCE(rate->mcs > 13))
return 0;
if (WARN_ON_ONCE(rate->he_gi > NL80211_RATE_INFO_HE_GI_3_2))
@@ -1286,9 +1379,11 @@
else if (rate->bw == RATE_INFO_BW_HE_RU &&
rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_26)
result = rates_26[rate->he_gi];
- else if (WARN(1, "invalid HE MCS: bw:%d, ru:%d\n",
- rate->bw, rate->he_ru_alloc))
+ else {
+ WARN(1, "invalid HE MCS: bw:%d, ru:%d\n",
+ rate->bw, rate->he_ru_alloc);
return 0;
+ }
/* now scale to the appropriate MCS */
tmp = result;
@@ -1523,6 +1618,9 @@
case 128 ... 130:
*band = NL80211_BAND_5GHZ;
return true;
+ case 131 ... 135:
+ *band = NL80211_BAND_6GHZ;
+ return true;
case 81:
case 82:
case 83:
@@ -1562,7 +1660,8 @@
}
if (freq == 2484) {
- if (chandef->width > NL80211_CHAN_WIDTH_40)
+ /* channel 14 is only for IEEE 802.11b */
+ if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT)
return false;
*op_class = 82; /* channel 14 */
@@ -1654,7 +1753,7 @@
}
/* 56.16 GHz, channel 1..4 */
- if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) {
+ if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 6) {
if (chandef->width >= NL80211_CHAN_WIDTH_40)
return false;
@@ -1980,29 +2079,6 @@
{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
EXPORT_SYMBOL(bridge_tunnel_header);
-bool cfg80211_iftype_allowed(struct wiphy *wiphy, enum nl80211_iftype iftype,
- bool is_4addr, u8 check_swif)
-
-{
- bool is_vlan = iftype == NL80211_IFTYPE_AP_VLAN;
-
- switch (check_swif) {
- case 0:
- if (is_vlan && is_4addr)
- return wiphy->flags & WIPHY_FLAG_4ADDR_AP;
- return wiphy->interface_modes & BIT(iftype);
- case 1:
- if (!(wiphy->software_iftypes & BIT(iftype)) && is_vlan)
- return wiphy->flags & WIPHY_FLAG_4ADDR_AP;
- return wiphy->software_iftypes & BIT(iftype);
- default:
- break;
- }
-
- return false;
-}
-EXPORT_SYMBOL(cfg80211_iftype_allowed);
-
/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
struct iapp_layer2_update {
u8 da[ETH_ALEN]; /* broadcast */
@@ -2047,3 +2123,133 @@
netif_rx_ni(skb);
}
EXPORT_SYMBOL(cfg80211_send_layer2_update);
+
+int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
+ enum ieee80211_vht_chanwidth bw,
+ int mcs, bool ext_nss_bw_capable,
+ unsigned int max_vht_nss)
+{
+ u16 map = le16_to_cpu(cap->supp_mcs.rx_mcs_map);
+ int ext_nss_bw;
+ int supp_width;
+ int i, mcs_encoding;
+
+ if (map == 0xffff)
+ return 0;
+
+ if (WARN_ON(mcs > 9 || max_vht_nss > 8))
+ return 0;
+ if (mcs <= 7)
+ mcs_encoding = 0;
+ else if (mcs == 8)
+ mcs_encoding = 1;
+ else
+ mcs_encoding = 2;
+
+ if (!max_vht_nss) {
+ /* find max_vht_nss for the given MCS */
+ for (i = 7; i >= 0; i--) {
+ int supp = (map >> (2 * i)) & 3;
+
+ if (supp == 3)
+ continue;
+
+ if (supp >= mcs_encoding) {
+ max_vht_nss = i + 1;
+ break;
+ }
+ }
+ }
+
+ if (!(cap->supp_mcs.tx_mcs_map &
+ cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE)))
+ return max_vht_nss;
+
+ ext_nss_bw = le32_get_bits(cap->vht_cap_info,
+ IEEE80211_VHT_CAP_EXT_NSS_BW_MASK);
+ supp_width = le32_get_bits(cap->vht_cap_info,
+ IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK);
+
+ /* if not capable, treat ext_nss_bw as 0 */
+ if (!ext_nss_bw_capable)
+ ext_nss_bw = 0;
+
+ /* This is invalid */
+ if (supp_width == 3)
+ return 0;
+
+ /* This is an invalid combination so pretend nothing is supported */
+ if (supp_width == 2 && (ext_nss_bw == 1 || ext_nss_bw == 2))
+ return 0;
+
+ /*
+ * Cover all the special cases according to IEEE 802.11-2016
+ * Table 9-250. All other cases are either factor of 1 or not
+ * valid/supported.
+ */
+ switch (bw) {
+ case IEEE80211_VHT_CHANWIDTH_USE_HT:
+ case IEEE80211_VHT_CHANWIDTH_80MHZ:
+ if ((supp_width == 1 || supp_width == 2) &&
+ ext_nss_bw == 3)
+ return 2 * max_vht_nss;
+ break;
+ case IEEE80211_VHT_CHANWIDTH_160MHZ:
+ if (supp_width == 0 &&
+ (ext_nss_bw == 1 || ext_nss_bw == 2))
+ return max_vht_nss / 2;
+ if (supp_width == 0 &&
+ ext_nss_bw == 3)
+ return (3 * max_vht_nss) / 4;
+ if (supp_width == 1 &&
+ ext_nss_bw == 3)
+ return 2 * max_vht_nss;
+ break;
+ case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
+ if (supp_width == 0 && ext_nss_bw == 1)
+ return 0; /* not possible */
+ if (supp_width == 0 &&
+ ext_nss_bw == 2)
+ return max_vht_nss / 2;
+ if (supp_width == 0 &&
+ ext_nss_bw == 3)
+ return (3 * max_vht_nss) / 4;
+ if (supp_width == 1 &&
+ ext_nss_bw == 0)
+ return 0; /* not possible */
+ if (supp_width == 1 &&
+ ext_nss_bw == 1)
+ return max_vht_nss / 2;
+ if (supp_width == 1 &&
+ ext_nss_bw == 2)
+ return (3 * max_vht_nss) / 4;
+ break;
+ }
+
+ /* not covered or invalid combination received */
+ return max_vht_nss;
+}
+EXPORT_SYMBOL(ieee80211_get_vht_max_nss);
+
+bool cfg80211_iftype_allowed(struct wiphy *wiphy, enum nl80211_iftype iftype,
+ bool is_4addr, u8 check_swif)
+
+{
+ bool is_vlan = iftype == NL80211_IFTYPE_AP_VLAN;
+
+ switch (check_swif) {
+ case 0:
+ if (is_vlan && is_4addr)
+ return wiphy->flags & WIPHY_FLAG_4ADDR_AP;
+ return wiphy->interface_modes & BIT(iftype);
+ case 1:
+ if (!(wiphy->software_iftypes & BIT(iftype)) && is_vlan)
+ return wiphy->flags & WIPHY_FLAG_4ADDR_AP;
+ return wiphy->software_iftypes & BIT(iftype);
+ default:
+ break;
+ }
+
+ return false;
+}
+EXPORT_SYMBOL(cfg80211_iftype_allowed);
--
Gitblit v1.6.2