mac80211: mark patches accepted upstream
[openwrt/openwrt.git] / package / kernel / mac80211 / patches / subsys / 316-wifi-mac80211-add-a-workaround-for-receiving-non-sta.patch
diff --git a/package/kernel/mac80211/patches/subsys/316-wifi-mac80211-add-a-workaround-for-receiving-non-sta.patch b/package/kernel/mac80211/patches/subsys/316-wifi-mac80211-add-a-workaround-for-receiving-non-sta.patch
deleted file mode 100644 (file)
index 6dc98ae..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 9 Dec 2022 21:15:04 +0100
-Subject: [PATCH] wifi: mac80211: add a workaround for receiving
- non-standard mesh A-MSDU
-
-At least ath10k and ath11k supported hardware (maybe more) does not implement
-mesh A-MSDU aggregation in a standard compliant way.
-802.11-2020 9.3.2.2.2 declares that the Mesh Control field is part of the
-A-MSDU header. As such, its length must not be included in the subframe
-length field.
-Hardware affected by this bug treats the mesh control field as part of the
-MSDU data and sets the length accordingly.
-In order to avoid packet loss, keep track of which stations are affected
-by this and take it into account when converting A-MSDU to 802.3 + mesh control
-packets.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -6194,6 +6194,19 @@ static inline int ieee80211_data_to_8023
- }
- /**
-+ * ieee80211_is_valid_amsdu - check if subframe lengths of an A-MSDU are valid
-+ *
-+ * This is used to detect non-standard A-MSDU frames, e.g. the ones generated
-+ * by ath10k and ath11k, where the subframe length includes the length of the
-+ * mesh control field.
-+ *
-+ * @skb: The input A-MSDU frame without any headers.
-+ * @mesh_hdr: use standard compliant mesh A-MSDU subframe header
-+ * Returns: true if subframe header lengths are valid for the @mesh_hdr mode
-+ */
-+bool ieee80211_is_valid_amsdu(struct sk_buff *skb, bool mesh_hdr);
-+
-+/**
-  * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame
-  *
-  * Decode an IEEE 802.11 A-MSDU and convert it to a list of 802.3 frames.
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2899,7 +2899,6 @@ __ieee80211_rx_h_amsdu(struct ieee80211_
-       static ieee80211_rx_result res;
-       struct ethhdr ethhdr;
-       const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source;
--      bool mesh = false;
-       if (unlikely(ieee80211_has_a4(hdr->frame_control))) {
-               check_da = NULL;
-@@ -2917,7 +2916,6 @@ __ieee80211_rx_h_amsdu(struct ieee80211_
-               case NL80211_IFTYPE_MESH_POINT:
-                       check_sa = NULL;
-                       check_da = NULL;
--                      mesh = true;
-                       break;
-               default:
-                       break;
-@@ -2932,10 +2930,21 @@ __ieee80211_rx_h_amsdu(struct ieee80211_
-                                         data_offset, true))
-               return RX_DROP_UNUSABLE;
-+      if (rx->sta && rx->sta->amsdu_mesh_control < 0) {
-+              bool valid_std = ieee80211_is_valid_amsdu(skb, true);
-+              bool valid_nonstd = ieee80211_is_valid_amsdu(skb, false);
-+
-+              if (valid_std && !valid_nonstd)
-+                      rx->sta->amsdu_mesh_control = 1;
-+              else if (valid_nonstd && !valid_std)
-+                      rx->sta->amsdu_mesh_control = 0;
-+      }
-+
-       ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
-                                rx->sdata->vif.type,
-                                rx->local->hw.extra_tx_headroom,
--                               check_da, check_sa, mesh);
-+                               check_da, check_sa,
-+                               rx->sta->amsdu_mesh_control);
-       while (!skb_queue_empty(&frame_list)) {
-               rx->skb = __skb_dequeue(&frame_list);
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -591,6 +591,9 @@ __sta_info_alloc(struct ieee80211_sub_if
-       sta->sta_state = IEEE80211_STA_NONE;
-+      if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
-+              sta->amsdu_mesh_control = -1;
-+
-       /* Mark TID as unreserved */
-       sta->reserved_tid = IEEE80211_TID_UNRESERVED;
---- a/net/mac80211/sta_info.h
-+++ b/net/mac80211/sta_info.h
-@@ -702,6 +702,7 @@ struct sta_info {
-       struct codel_params cparams;
-       u8 reserved_tid;
-+      s8 amsdu_mesh_control;
-       struct cfg80211_chan_def tdls_chandef;
---- a/net/wireless/util.c
-+++ b/net/wireless/util.c
-@@ -776,6 +776,38 @@ __ieee80211_amsdu_copy(struct sk_buff *s
-       return frame;
- }
-+bool ieee80211_is_valid_amsdu(struct sk_buff *skb, bool mesh_hdr)
-+{
-+      int offset = 0, remaining, subframe_len, padding;
-+
-+      for (offset = 0; offset < skb->len; offset += subframe_len + padding) {
-+              struct {
-+                  __be16 len;
-+                  u8 mesh_flags;
-+              } hdr;
-+              u16 len;
-+
-+              if (skb_copy_bits(skb, offset + 2 * ETH_ALEN, &hdr, sizeof(hdr)) < 0)
-+                      return false;
-+
-+              if (mesh_hdr)
-+                      len = le16_to_cpu(*(__le16 *)&hdr.len) +
-+                            __ieee80211_get_mesh_hdrlen(hdr.mesh_flags);
-+              else
-+                      len = ntohs(hdr.len);
-+
-+              subframe_len = sizeof(struct ethhdr) + len;
-+              padding = (4 - subframe_len) & 0x3;
-+              remaining = skb->len - offset;
-+
-+              if (subframe_len > remaining)
-+                      return false;
-+      }
-+
-+      return true;
-+}
-+EXPORT_SYMBOL(ieee80211_is_valid_amsdu);
-+
- void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
-                             const u8 *addr, enum nl80211_iftype iftype,
-                             const unsigned int extra_headroom,