mac80211: renumber subsys patches after update
authorFelix Fietkau <nbd@nbd.name>
Mon, 19 Aug 2019 17:15:35 +0000 (19:15 +0200)
committerFelix Fietkau <nbd@nbd.name>
Wed, 21 Aug 2019 12:59:10 +0000 (14:59 +0200)
Signed-off-by: Felix Fietkau <nbd@nbd.name>
package/kernel/mac80211/patches/subsys/300-mac80211-optimize-skb-resizing.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/357-mac80211-optimize-skb-resizing.patch [deleted file]
package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/522-mac80211_configure_antenna_gain.patch [deleted file]

diff --git a/package/kernel/mac80211/patches/subsys/300-mac80211-optimize-skb-resizing.patch b/package/kernel/mac80211/patches/subsys/300-mac80211-optimize-skb-resizing.patch
new file mode 100644 (file)
index 0000000..e2fbdc6
--- /dev/null
@@ -0,0 +1,199 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Sun, 17 Mar 2019 18:11:30 +0100
+Subject: [PATCH] mac80211: optimize skb resizing
+
+When forwarding unicast packets from ethernet to batman-adv over 802.11s
+(with forwarding disabled), the typical required headroom to transmit
+encrypted packets on mt76 is 32 (802.11) + 6 (802.11s) + 8 (CCMP) +
+2 (padding) + 6 (LLC) + 18 (batman-adv) - 14 (old ethernet header) = 58 bytes.
+
+On systems where NET_SKB_PAD is 64 this leads to a call to pskb_expand_head
+for every packet, since mac80211 also tries to allocate 16 bytes status
+headroom for radiotap headers.
+
+This patch fixes these unnecessary reallocations by only requiring the extra
+status headroom in ieee80211_tx_monitor()
+If however a reallocation happens before that call, the status headroom gets
+added there as well, in order to avoid double reallocation.
+
+The patch also cleans up the code by moving the headroom calculation to
+ieee80211_skb_resize.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1779,6 +1779,9 @@ int ieee80211_tx_control_port(struct wip
+                             const u8 *dest, __be16 proto, bool unencrypted);
+ int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
+                             const u8 *buf, size_t len);
++int ieee80211_skb_resize(struct ieee80211_local *local,
++                       struct ieee80211_sub_if_data *sdata,
++                       struct sk_buff *skb, int hdrlen, int hdr_add);
+ /* HT */
+ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -655,6 +655,11 @@ void ieee80211_tx_monitor(struct ieee802
+       struct net_device *prev_dev = NULL;
+       int rtap_len;
++      if (ieee80211_skb_resize(local, NULL, skb, 0, 0)) {
++              dev_kfree_skb(skb);
++              return;
++      }
++
+       /* send frame to monitor interfaces now */
+       rtap_len = ieee80211_tx_radiotap_len(info);
+       if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -1936,37 +1936,53 @@ static bool ieee80211_tx(struct ieee8021
+ }
+ /* device xmit handlers */
+-
+-static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
+-                              struct sk_buff *skb,
+-                              int head_need, bool may_encrypt)
++int ieee80211_skb_resize(struct ieee80211_local *local,
++                       struct ieee80211_sub_if_data *sdata,
++                       struct sk_buff *skb, int hdr_len, int hdr_extra)
+ {
+-      struct ieee80211_local *local = sdata->local;
++      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_hdr *hdr;
+-      bool enc_tailroom;
+-      int tail_need = 0;
++      int head_need, head_max;
++      int tail_need, tail_max;
++      bool enc_tailroom = false;
+-      hdr = (struct ieee80211_hdr *) skb->data;
+-      enc_tailroom = may_encrypt &&
+-                     (sdata->crypto_tx_tailroom_needed_cnt ||
+-                      ieee80211_is_mgmt(hdr->frame_control));
++      if (sdata && !hdr_len &&
++          !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) {
++              hdr = (struct ieee80211_hdr *) skb->data;
++              enc_tailroom = (sdata->crypto_tx_tailroom_needed_cnt ||
++                              ieee80211_is_mgmt(hdr->frame_control));
++              hdr_len += sdata->encrypt_headroom;
++      }
+-      if (enc_tailroom) {
+-              tail_need = IEEE80211_ENCRYPT_TAILROOM;
+-              tail_need -= skb_tailroom(skb);
+-              tail_need = max_t(int, tail_need, 0);
++      head_need = head_max = hdr_len;
++      tail_need = tail_max = 0;
++      if (!sdata) {
++              head_need = head_max = local->tx_headroom;
++      } else {
++              head_max += hdr_extra;
++              head_max += max_t(int, local->tx_headroom,
++                                local->hw.extra_tx_headroom);
++              head_need += local->hw.extra_tx_headroom;
++
++              tail_max = IEEE80211_ENCRYPT_TAILROOM;
++              if (enc_tailroom)
++                      tail_need = tail_max;
+       }
+       if (skb_cloned(skb) &&
+           (!ieee80211_hw_check(&local->hw, SUPPORTS_CLONED_SKBS) ||
+            !skb_clone_writable(skb, ETH_HLEN) || enc_tailroom))
+               I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
+-      else if (head_need || tail_need)
++      else if (head_need > skb_headroom(skb) ||
++               tail_need > skb_tailroom(skb))
+               I802_DEBUG_INC(local->tx_expand_skb_head);
+       else
+               return 0;
+-      if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) {
++      head_max = max_t(int, 0, head_max - skb_headroom(skb));
++      tail_max = max_t(int, 0, tail_max - skb_tailroom(skb));
++
++      if (pskb_expand_head(skb, head_max, tail_max, GFP_ATOMIC)) {
+               wiphy_debug(local->hw.wiphy,
+                           "failed to reallocate TX buffer\n");
+               return -ENOMEM;
+@@ -1982,18 +1998,8 @@ void ieee80211_xmit(struct ieee80211_sub
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_hdr *hdr;
+-      int headroom;
+-      bool may_encrypt;
+-
+-      may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT);
+-
+-      headroom = local->tx_headroom;
+-      if (may_encrypt)
+-              headroom += sdata->encrypt_headroom;
+-      headroom -= skb_headroom(skb);
+-      headroom = max_t(int, 0, headroom);
+-      if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
++      if (ieee80211_skb_resize(local, sdata, skb, 0, 0)) {
+               ieee80211_free_txskb(&local->hw, skb);
+               return;
+       }
+@@ -2774,29 +2780,13 @@ static struct sk_buff *ieee80211_build_h
+       }
+       skb_pull(skb, skip_header_bytes);
+-      head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
+-
+-      /*
+-       * So we need to modify the skb header and hence need a copy of
+-       * that. The head_need variable above doesn't, so far, include
+-       * the needed header space that we don't need right away. If we
+-       * can, then we don't reallocate right now but only after the
+-       * frame arrives at the master device (if it does...)
+-       *
+-       * If we cannot, however, then we will reallocate to include all
+-       * the ever needed space. Also, if we need to reallocate it anyway,
+-       * make it big enough for everything we may ever need.
+-       */
++      head_need = hdrlen + encaps_len + meshhdrlen;
+-      if (head_need > 0 || skb_cloned(skb)) {
+-              head_need += sdata->encrypt_headroom;
+-              head_need += local->tx_headroom;
+-              head_need = max_t(int, 0, head_need);
+-              if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
+-                      ieee80211_free_txskb(&local->hw, skb);
+-                      skb = NULL;
+-                      return ERR_PTR(-ENOMEM);
+-              }
++      if (ieee80211_skb_resize(local, sdata, skb, head_need,
++                               sdata->encrypt_headroom)) {
++              ieee80211_free_txskb(&local->hw, skb);
++              skb = NULL;
++              return ERR_PTR(-ENOMEM);
+       }
+       if (encaps_data)
+@@ -3411,7 +3401,6 @@ static bool ieee80211_xmit_fast(struct i
+       struct ieee80211_local *local = sdata->local;
+       u16 ethertype = (skb->data[12] << 8) | skb->data[13];
+       int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
+-      int hw_headroom = sdata->local->hw.extra_tx_headroom;
+       struct ethhdr eth;
+       struct ieee80211_tx_info *info;
+       struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
+@@ -3463,10 +3452,7 @@ static bool ieee80211_xmit_fast(struct i
+        * as the may-encrypt argument for the resize to not account for
+        * more room than we already have in 'extra_head'
+        */
+-      if (unlikely(ieee80211_skb_resize(sdata, skb,
+-                                        max_t(int, extra_head + hw_headroom -
+-                                                   skb_headroom(skb), 0),
+-                                        false))) {
++      if (unlikely(ieee80211_skb_resize(local, sdata, skb, extra_head, 0))) {
+               kfree_skb(skb);
+               return true;
+       }
diff --git a/package/kernel/mac80211/patches/subsys/357-mac80211-optimize-skb-resizing.patch b/package/kernel/mac80211/patches/subsys/357-mac80211-optimize-skb-resizing.patch
deleted file mode 100644 (file)
index e2fbdc6..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sun, 17 Mar 2019 18:11:30 +0100
-Subject: [PATCH] mac80211: optimize skb resizing
-
-When forwarding unicast packets from ethernet to batman-adv over 802.11s
-(with forwarding disabled), the typical required headroom to transmit
-encrypted packets on mt76 is 32 (802.11) + 6 (802.11s) + 8 (CCMP) +
-2 (padding) + 6 (LLC) + 18 (batman-adv) - 14 (old ethernet header) = 58 bytes.
-
-On systems where NET_SKB_PAD is 64 this leads to a call to pskb_expand_head
-for every packet, since mac80211 also tries to allocate 16 bytes status
-headroom for radiotap headers.
-
-This patch fixes these unnecessary reallocations by only requiring the extra
-status headroom in ieee80211_tx_monitor()
-If however a reallocation happens before that call, the status headroom gets
-added there as well, in order to avoid double reallocation.
-
-The patch also cleans up the code by moving the headroom calculation to
-ieee80211_skb_resize.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -1779,6 +1779,9 @@ int ieee80211_tx_control_port(struct wip
-                             const u8 *dest, __be16 proto, bool unencrypted);
- int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
-                             const u8 *buf, size_t len);
-+int ieee80211_skb_resize(struct ieee80211_local *local,
-+                       struct ieee80211_sub_if_data *sdata,
-+                       struct sk_buff *skb, int hdrlen, int hdr_add);
- /* HT */
- void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -655,6 +655,11 @@ void ieee80211_tx_monitor(struct ieee802
-       struct net_device *prev_dev = NULL;
-       int rtap_len;
-+      if (ieee80211_skb_resize(local, NULL, skb, 0, 0)) {
-+              dev_kfree_skb(skb);
-+              return;
-+      }
-+
-       /* send frame to monitor interfaces now */
-       rtap_len = ieee80211_tx_radiotap_len(info);
-       if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -1936,37 +1936,53 @@ static bool ieee80211_tx(struct ieee8021
- }
- /* device xmit handlers */
--
--static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
--                              struct sk_buff *skb,
--                              int head_need, bool may_encrypt)
-+int ieee80211_skb_resize(struct ieee80211_local *local,
-+                       struct ieee80211_sub_if_data *sdata,
-+                       struct sk_buff *skb, int hdr_len, int hdr_extra)
- {
--      struct ieee80211_local *local = sdata->local;
-+      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_hdr *hdr;
--      bool enc_tailroom;
--      int tail_need = 0;
-+      int head_need, head_max;
-+      int tail_need, tail_max;
-+      bool enc_tailroom = false;
--      hdr = (struct ieee80211_hdr *) skb->data;
--      enc_tailroom = may_encrypt &&
--                     (sdata->crypto_tx_tailroom_needed_cnt ||
--                      ieee80211_is_mgmt(hdr->frame_control));
-+      if (sdata && !hdr_len &&
-+          !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) {
-+              hdr = (struct ieee80211_hdr *) skb->data;
-+              enc_tailroom = (sdata->crypto_tx_tailroom_needed_cnt ||
-+                              ieee80211_is_mgmt(hdr->frame_control));
-+              hdr_len += sdata->encrypt_headroom;
-+      }
--      if (enc_tailroom) {
--              tail_need = IEEE80211_ENCRYPT_TAILROOM;
--              tail_need -= skb_tailroom(skb);
--              tail_need = max_t(int, tail_need, 0);
-+      head_need = head_max = hdr_len;
-+      tail_need = tail_max = 0;
-+      if (!sdata) {
-+              head_need = head_max = local->tx_headroom;
-+      } else {
-+              head_max += hdr_extra;
-+              head_max += max_t(int, local->tx_headroom,
-+                                local->hw.extra_tx_headroom);
-+              head_need += local->hw.extra_tx_headroom;
-+
-+              tail_max = IEEE80211_ENCRYPT_TAILROOM;
-+              if (enc_tailroom)
-+                      tail_need = tail_max;
-       }
-       if (skb_cloned(skb) &&
-           (!ieee80211_hw_check(&local->hw, SUPPORTS_CLONED_SKBS) ||
-            !skb_clone_writable(skb, ETH_HLEN) || enc_tailroom))
-               I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
--      else if (head_need || tail_need)
-+      else if (head_need > skb_headroom(skb) ||
-+               tail_need > skb_tailroom(skb))
-               I802_DEBUG_INC(local->tx_expand_skb_head);
-       else
-               return 0;
--      if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) {
-+      head_max = max_t(int, 0, head_max - skb_headroom(skb));
-+      tail_max = max_t(int, 0, tail_max - skb_tailroom(skb));
-+
-+      if (pskb_expand_head(skb, head_max, tail_max, GFP_ATOMIC)) {
-               wiphy_debug(local->hw.wiphy,
-                           "failed to reallocate TX buffer\n");
-               return -ENOMEM;
-@@ -1982,18 +1998,8 @@ void ieee80211_xmit(struct ieee80211_sub
-       struct ieee80211_local *local = sdata->local;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_hdr *hdr;
--      int headroom;
--      bool may_encrypt;
--
--      may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT);
--
--      headroom = local->tx_headroom;
--      if (may_encrypt)
--              headroom += sdata->encrypt_headroom;
--      headroom -= skb_headroom(skb);
--      headroom = max_t(int, 0, headroom);
--      if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
-+      if (ieee80211_skb_resize(local, sdata, skb, 0, 0)) {
-               ieee80211_free_txskb(&local->hw, skb);
-               return;
-       }
-@@ -2774,29 +2780,13 @@ static struct sk_buff *ieee80211_build_h
-       }
-       skb_pull(skb, skip_header_bytes);
--      head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
--
--      /*
--       * So we need to modify the skb header and hence need a copy of
--       * that. The head_need variable above doesn't, so far, include
--       * the needed header space that we don't need right away. If we
--       * can, then we don't reallocate right now but only after the
--       * frame arrives at the master device (if it does...)
--       *
--       * If we cannot, however, then we will reallocate to include all
--       * the ever needed space. Also, if we need to reallocate it anyway,
--       * make it big enough for everything we may ever need.
--       */
-+      head_need = hdrlen + encaps_len + meshhdrlen;
--      if (head_need > 0 || skb_cloned(skb)) {
--              head_need += sdata->encrypt_headroom;
--              head_need += local->tx_headroom;
--              head_need = max_t(int, 0, head_need);
--              if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
--                      ieee80211_free_txskb(&local->hw, skb);
--                      skb = NULL;
--                      return ERR_PTR(-ENOMEM);
--              }
-+      if (ieee80211_skb_resize(local, sdata, skb, head_need,
-+                               sdata->encrypt_headroom)) {
-+              ieee80211_free_txskb(&local->hw, skb);
-+              skb = NULL;
-+              return ERR_PTR(-ENOMEM);
-       }
-       if (encaps_data)
-@@ -3411,7 +3401,6 @@ static bool ieee80211_xmit_fast(struct i
-       struct ieee80211_local *local = sdata->local;
-       u16 ethertype = (skb->data[12] << 8) | skb->data[13];
-       int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
--      int hw_headroom = sdata->local->hw.extra_tx_headroom;
-       struct ethhdr eth;
-       struct ieee80211_tx_info *info;
-       struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
-@@ -3463,10 +3452,7 @@ static bool ieee80211_xmit_fast(struct i
-        * as the may-encrypt argument for the resize to not account for
-        * more room than we already have in 'extra_head'
-        */
--      if (unlikely(ieee80211_skb_resize(sdata, skb,
--                                        max_t(int, extra_head + hw_headroom -
--                                                   skb_headroom(skb), 0),
--                                        false))) {
-+      if (unlikely(ieee80211_skb_resize(local, sdata, skb, extra_head, 0))) {
-               kfree_skb(skb);
-               return true;
-       }
diff --git a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch
new file mode 100644 (file)
index 0000000..3ca34b7
--- /dev/null
@@ -0,0 +1,160 @@
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -3344,6 +3344,7 @@ struct cfg80211_update_owe_info {
+  *    (as advertised by the nl80211 feature flag.)
+  * @get_tx_power: store the current TX power into the dbm variable;
+  *    return 0 if successful
++ * @set_antenna_gain: set antenna gain to reduce maximum tx power if necessary
+  *
+  * @set_wds_peer: set the WDS peer for a WDS interface
+  *
+@@ -3656,6 +3657,7 @@ struct cfg80211_ops {
+                               enum nl80211_tx_power_setting type, int mbm);
+       int     (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
+                               int *dbm);
++      int     (*set_antenna_gain)(struct wiphy *wiphy, int dbi);
+       int     (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
+                               const u8 *addr);
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -1476,6 +1476,7 @@ enum ieee80211_smps_mode {
+  *
+  * @power_level: requested transmit power (in dBm), backward compatibility
+  *    value only that is set to the minimum of all interfaces
++ * @max_antenna_gain: maximum antenna gain adjusted by user config (in dBi)
+  *
+  * @chandef: the channel definition to tune to
+  * @radar_enabled: whether radar detection is enabled
+@@ -1496,6 +1497,7 @@ enum ieee80211_smps_mode {
+ struct ieee80211_conf {
+       u32 flags;
+       int power_level, dynamic_ps_timeout;
++      int max_antenna_gain;
+       u16 listen_interval;
+       u8 ps_dtim_period;
+--- a/include/uapi/linux/nl80211.h
++++ b/include/uapi/linux/nl80211.h
+@@ -2356,6 +2356,9 @@ enum nl80211_commands {
+  *
+  * @NL80211_ATTR_TWT_RESPONDER: Enable target wait time responder support.
+  *
++ * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
++ *    transmit power to stay within regulatory limits. u32, dBi.
++ *
+  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
+  * @NL80211_ATTR_MAX: highest attribute number currently defined
+  * @__NL80211_ATTR_AFTER_LAST: internal use
+@@ -2813,6 +2816,8 @@ enum nl80211_attrs {
+       NL80211_ATTR_TWT_RESPONDER,
++      NL80211_ATTR_WIPHY_ANTENNA_GAIN,
++
+       /* add attributes here, update the policy in nl80211.c */
+       __NL80211_ATTR_AFTER_LAST,
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -2584,6 +2584,19 @@ static int ieee80211_get_tx_power(struct
+       return 0;
+ }
++static int ieee80211_set_antenna_gain(struct wiphy *wiphy, int dbi)
++{
++      struct ieee80211_local *local = wiphy_priv(wiphy);
++
++      if (dbi < 0)
++              return -EINVAL;
++
++      local->user_antenna_gain = dbi;
++      ieee80211_hw_config(local, 0);
++
++      return 0;
++}
++
+ static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
+                                 const u8 *addr)
+ {
+@@ -3997,6 +4010,7 @@ const struct cfg80211_ops mac80211_confi
+       .set_wiphy_params = ieee80211_set_wiphy_params,
+       .set_tx_power = ieee80211_set_tx_power,
+       .get_tx_power = ieee80211_get_tx_power,
++      .set_antenna_gain = ieee80211_set_antenna_gain,
+       .set_wds_peer = ieee80211_set_wds_peer,
+       .rfkill_poll = ieee80211_rfkill_poll,
+       CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1372,6 +1372,7 @@ struct ieee80211_local {
+       int dynamic_ps_forced_timeout;
+       int user_power_level; /* in dBm, for all interfaces */
++      int user_antenna_gain; /* in dBi */
+       enum ieee80211_smps_mode smps_mode;
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -93,7 +93,7 @@ static u32 ieee80211_hw_conf_chan(struct
+       struct ieee80211_sub_if_data *sdata;
+       struct cfg80211_chan_def chandef = {};
+       u32 changed = 0;
+-      int power;
++      int power, max_power;
+       u32 offchannel_flag;
+       offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
+@@ -150,6 +150,12 @@ static u32 ieee80211_hw_conf_chan(struct
+       }
+       rcu_read_unlock();
++      max_power = chandef.chan->max_reg_power;
++      if (local->user_antenna_gain > 0) {
++              max_power -= local->user_antenna_gain;
++              power = min(power, max_power);
++      }
++
+       if (local->hw.conf.power_level != power) {
+               changed |= IEEE80211_CONF_CHANGE_POWER;
+               local->hw.conf.power_level = power;
+@@ -639,6 +645,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
+                                        IEEE80211_RADIOTAP_MCS_HAVE_BW;
+       local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
+                                        IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
++      local->user_antenna_gain = 0;
+       local->hw.uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
+       local->hw.uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
+       local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -574,6 +574,7 @@ const struct nla_policy nl80211_policy[N
+       [NL80211_ATTR_SAE_PASSWORD] = { .type = NLA_BINARY,
+                                       .len = SAE_PASSWORD_MAX_LEN },
+       [NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
++      [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 },
+ };
+ /* policy for the key attributes */
+@@ -2869,6 +2870,20 @@ static int nl80211_set_wiphy(struct sk_b
+               if (result)
+                       return result;
+       }
++
++      if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) {
++              int idx, dbi = 0;
++
++              if (!rdev->ops->set_antenna_gain)
++                      return -EOPNOTSUPP;
++
++              idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN;
++              dbi = nla_get_u32(info->attrs[idx]);
++
++              result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi);
++              if (result)
++                      return result;
++      }
+       if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
+           info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
diff --git a/package/kernel/mac80211/patches/subsys/522-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/subsys/522-mac80211_configure_antenna_gain.patch
deleted file mode 100644 (file)
index 3ca34b7..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -3344,6 +3344,7 @@ struct cfg80211_update_owe_info {
-  *    (as advertised by the nl80211 feature flag.)
-  * @get_tx_power: store the current TX power into the dbm variable;
-  *    return 0 if successful
-+ * @set_antenna_gain: set antenna gain to reduce maximum tx power if necessary
-  *
-  * @set_wds_peer: set the WDS peer for a WDS interface
-  *
-@@ -3656,6 +3657,7 @@ struct cfg80211_ops {
-                               enum nl80211_tx_power_setting type, int mbm);
-       int     (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
-                               int *dbm);
-+      int     (*set_antenna_gain)(struct wiphy *wiphy, int dbi);
-       int     (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
-                               const u8 *addr);
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -1476,6 +1476,7 @@ enum ieee80211_smps_mode {
-  *
-  * @power_level: requested transmit power (in dBm), backward compatibility
-  *    value only that is set to the minimum of all interfaces
-+ * @max_antenna_gain: maximum antenna gain adjusted by user config (in dBi)
-  *
-  * @chandef: the channel definition to tune to
-  * @radar_enabled: whether radar detection is enabled
-@@ -1496,6 +1497,7 @@ enum ieee80211_smps_mode {
- struct ieee80211_conf {
-       u32 flags;
-       int power_level, dynamic_ps_timeout;
-+      int max_antenna_gain;
-       u16 listen_interval;
-       u8 ps_dtim_period;
---- a/include/uapi/linux/nl80211.h
-+++ b/include/uapi/linux/nl80211.h
-@@ -2356,6 +2356,9 @@ enum nl80211_commands {
-  *
-  * @NL80211_ATTR_TWT_RESPONDER: Enable target wait time responder support.
-  *
-+ * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
-+ *    transmit power to stay within regulatory limits. u32, dBi.
-+ *
-  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
-  * @NL80211_ATTR_MAX: highest attribute number currently defined
-  * @__NL80211_ATTR_AFTER_LAST: internal use
-@@ -2813,6 +2816,8 @@ enum nl80211_attrs {
-       NL80211_ATTR_TWT_RESPONDER,
-+      NL80211_ATTR_WIPHY_ANTENNA_GAIN,
-+
-       /* add attributes here, update the policy in nl80211.c */
-       __NL80211_ATTR_AFTER_LAST,
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -2584,6 +2584,19 @@ static int ieee80211_get_tx_power(struct
-       return 0;
- }
-+static int ieee80211_set_antenna_gain(struct wiphy *wiphy, int dbi)
-+{
-+      struct ieee80211_local *local = wiphy_priv(wiphy);
-+
-+      if (dbi < 0)
-+              return -EINVAL;
-+
-+      local->user_antenna_gain = dbi;
-+      ieee80211_hw_config(local, 0);
-+
-+      return 0;
-+}
-+
- static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
-                                 const u8 *addr)
- {
-@@ -3997,6 +4010,7 @@ const struct cfg80211_ops mac80211_confi
-       .set_wiphy_params = ieee80211_set_wiphy_params,
-       .set_tx_power = ieee80211_set_tx_power,
-       .get_tx_power = ieee80211_get_tx_power,
-+      .set_antenna_gain = ieee80211_set_antenna_gain,
-       .set_wds_peer = ieee80211_set_wds_peer,
-       .rfkill_poll = ieee80211_rfkill_poll,
-       CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -1372,6 +1372,7 @@ struct ieee80211_local {
-       int dynamic_ps_forced_timeout;
-       int user_power_level; /* in dBm, for all interfaces */
-+      int user_antenna_gain; /* in dBi */
-       enum ieee80211_smps_mode smps_mode;
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -93,7 +93,7 @@ static u32 ieee80211_hw_conf_chan(struct
-       struct ieee80211_sub_if_data *sdata;
-       struct cfg80211_chan_def chandef = {};
-       u32 changed = 0;
--      int power;
-+      int power, max_power;
-       u32 offchannel_flag;
-       offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
-@@ -150,6 +150,12 @@ static u32 ieee80211_hw_conf_chan(struct
-       }
-       rcu_read_unlock();
-+      max_power = chandef.chan->max_reg_power;
-+      if (local->user_antenna_gain > 0) {
-+              max_power -= local->user_antenna_gain;
-+              power = min(power, max_power);
-+      }
-+
-       if (local->hw.conf.power_level != power) {
-               changed |= IEEE80211_CONF_CHANGE_POWER;
-               local->hw.conf.power_level = power;
-@@ -639,6 +645,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
-                                        IEEE80211_RADIOTAP_MCS_HAVE_BW;
-       local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
-                                        IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
-+      local->user_antenna_gain = 0;
-       local->hw.uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
-       local->hw.uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
-       local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -574,6 +574,7 @@ const struct nla_policy nl80211_policy[N
-       [NL80211_ATTR_SAE_PASSWORD] = { .type = NLA_BINARY,
-                                       .len = SAE_PASSWORD_MAX_LEN },
-       [NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
-+      [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 },
- };
- /* policy for the key attributes */
-@@ -2869,6 +2870,20 @@ static int nl80211_set_wiphy(struct sk_b
-               if (result)
-                       return result;
-       }
-+
-+      if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) {
-+              int idx, dbi = 0;
-+
-+              if (!rdev->ops->set_antenna_gain)
-+                      return -EOPNOTSUPP;
-+
-+              idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN;
-+              dbi = nla_get_u32(info->attrs[idx]);
-+
-+              result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi);
-+              if (result)
-+                      return result;
-+      }
-       if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
-           info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {