mac80211: update encap offload patches to the latest version
authorFelix Fietkau <nbd@nbd.name>
Tue, 8 Sep 2020 12:22:28 +0000 (14:22 +0200)
committerFelix Fietkau <nbd@nbd.name>
Wed, 9 Sep 2020 09:51:47 +0000 (11:51 +0200)
Minor cleanup and code reorganization, along with a change to not disable
offload anymore when a tkip or sw crypto key is added

Signed-off-by: Felix Fietkau <nbd@nbd.name>
32 files changed:
package/kernel/mac80211/patches/subsys/314-mac80211-add-missing-queue-hash-initialization-to-80.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/314-mac80211-rework-tx-encapsulation-offload-API.patch [deleted file]
package/kernel/mac80211/patches/subsys/315-mac80211-check-and-refresh-aggregation-session-in-en.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/315-mac80211-reduce-duplication-in-tx-status-functions.patch [deleted file]
package/kernel/mac80211/patches/subsys/316-mac80211-remove-tx-status-call-to-ieee80211_sta_regi.patch [deleted file]
package/kernel/mac80211/patches/subsys/316-mac80211-skip-encap-offload-for-tx-multicast-control.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/317-mac80211-optimize-station-connection-monitor.patch [deleted file]
package/kernel/mac80211/patches/subsys/317-mac80211-set-info-control.hw_key-for-encap-offload-p.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/318-mac80211-rework-tx-encapsulation-offload-API.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/318-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch [deleted file]
package/kernel/mac80211/patches/subsys/319-mac80211-reduce-duplication-in-tx-status-functions.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/319-mac80211-unify-802.3-offload-and-802.11-tx-status-co.patch [deleted file]
package/kernel/mac80211/patches/subsys/320-mac80211-add-missing-queue-hash-initialization-to-80.patch [deleted file]
package/kernel/mac80211/patches/subsys/320-mac80211-remove-tx-status-call-to-ieee80211_sta_regi.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/321-mac80211-check-and-refresh-aggregation-session-in-en.patch [deleted file]
package/kernel/mac80211/patches/subsys/321-mac80211-optimize-station-connection-monitor.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/322-mac80211-support-using-ieee80211_tx_status_ext-to-fr.patch [deleted file]
package/kernel/mac80211/patches/subsys/322-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/323-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch [deleted file]
package/kernel/mac80211/patches/subsys/323-mac80211-unify-802.3-offload-and-802.11-tx-status-co.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/324-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch [deleted file]
package/kernel/mac80211/patches/subsys/324-mac80211-support-using-ieee80211_tx_status_ext-to-fr.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/325-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/325-mac80211-skip-encap-offload-for-tx-multicast-control.patch [deleted file]
package/kernel/mac80211/patches/subsys/326-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/326-mac80211-set-info-control.hw_key-for-encap-offload-p.patch [deleted file]
package/kernel/mac80211/patches/subsys/327-mac80211-extend-AQL-aggregation-estimation-to-HE-and.patch [deleted file]
package/kernel/mac80211/patches/subsys/327-mac80211-reorganize-code-to-remove-a-forward-declara.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/328-mac80211-add-AQL-support-for-VHT160-tx-rates.patch [deleted file]
package/kernel/mac80211/patches/subsys/328-mac80211-extend-AQL-aggregation-estimation-to-HE-and.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/329-mac80211-add-AQL-support-for-VHT160-tx-rates.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch

diff --git a/package/kernel/mac80211/patches/subsys/314-mac80211-add-missing-queue-hash-initialization-to-80.patch b/package/kernel/mac80211/patches/subsys/314-mac80211-add-missing-queue-hash-initialization-to-80.patch
new file mode 100644 (file)
index 0000000..eb56a2c
--- /dev/null
@@ -0,0 +1,25 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Mon, 17 Aug 2020 13:55:56 +0200
+Subject: [PATCH] mac80211: add missing queue/hash initialization to
+ 802.3 xmit
+
+Fixes AQL for encap-offloaded tx
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -4200,6 +4200,12 @@ static void ieee80211_8023_xmit(struct i
+       if (is_zero_ether_addr(ra))
+               goto out_free;
++      if (local->ops->wake_tx_queue) {
++              u16 queue = __ieee80211_select_queue(sdata, sta, skb);
++              skb_set_queue_mapping(skb, queue);
++              skb_get_hash(skb);
++      }
++
+       multicast = is_multicast_ether_addr(ra);
+       if (sta)
diff --git a/package/kernel/mac80211/patches/subsys/314-mac80211-rework-tx-encapsulation-offload-API.patch b/package/kernel/mac80211/patches/subsys/314-mac80211-rework-tx-encapsulation-offload-API.patch
deleted file mode 100644 (file)
index 4f0d264..0000000
+++ /dev/null
@@ -1,651 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Thu, 13 Aug 2020 15:37:11 +0200
-Subject: [PATCH] mac80211: rework tx encapsulation offload API
-
-The current API (which lets the driver turn on/off per vif directly) has a
-number of limitations:
-- it does not deal with AP_VLAN
-- conditions for enabling (no tkip, no monitor) are only checked at
-  add_interface time
-- no way to indicate 4-addr support
-
-In order to address this, store offload flags in struct ieee80211_vif
-(easy to extend for decap offload later). mac80211 initially sets the enable
-flag, but gives the driver a chance to modify it before its settings are
-applied. In addition to the .add_interface op, a .update_vif_offload op is
-introduced, which can be used for runtime changes.
-
-If a driver can't disable encap offload at runtime, or if it has some extra
-limitations, it can simply override the flags within those ops.
-
-Support for encap offload with 4-address mode interfaces can be enabled
-by setting a flag from .add_interface or .update_vif_offload.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/wireless/ath/ath11k/mac.c
-+++ b/drivers/net/wireless/ath/ath11k/mac.c
-@@ -4150,6 +4150,35 @@ static int ath11k_set_he_mu_sounding_mod
-       return ret;
- }
-+static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
-+                                          struct ieee80211_vif *vif)
-+{
-+      struct ath11k *ar = hw->priv;
-+      struct ath11k_base *ab = ar->ab;
-+      struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
-+      u32 param_id, param_value;
-+      int ret;
-+
-+      param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;
-+      if (ath11k_frame_mode != ATH11K_HW_TXRX_ETHERNET ||
-+          (vif->type != NL80211_IFTYPE_STATION &&
-+           vif->type != NL80211_IFTYPE_AP))
-+              vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
-+
-+      if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
-+              param_value = ATH11K_HW_TXRX_ETHERNET;
-+      else
-+              param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
-+
-+      ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
-+                                          param_id, param_value);
-+      if (ret) {
-+              ath11k_warn(ab, "failed to set vdev %d tx encap mode: %d\n",
-+                          arvif->vdev_id, ret);
-+              vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
-+      }
-+}
-+
- static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
-                                      struct ieee80211_vif *vif)
- {
-@@ -4159,7 +4188,6 @@ static int ath11k_mac_op_add_interface(s
-       struct vdev_create_params vdev_param = {0};
-       struct peer_create_params peer_param;
-       u32 param_id, param_value;
--      int hw_encap = 0;
-       u16 nss;
-       int i;
-       int ret;
-@@ -4253,30 +4281,7 @@ static int ath11k_mac_op_add_interface(s
-       list_add(&arvif->list, &ar->arvifs);
-       spin_unlock_bh(&ar->data_lock);
--      param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;
--      if (ath11k_frame_mode == ATH11K_HW_TXRX_ETHERNET)
--              switch (vif->type) {
--              case NL80211_IFTYPE_STATION:
--              case NL80211_IFTYPE_AP_VLAN:
--              case NL80211_IFTYPE_AP:
--                      hw_encap = 1;
--                      break;
--              default:
--                      break;
--              }
--
--      if (ieee80211_set_hw_80211_encap(vif, hw_encap))
--              param_value = ATH11K_HW_TXRX_ETHERNET;
--      else
--              param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
--
--      ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
--                                          param_id, param_value);
--      if (ret) {
--              ath11k_warn(ab, "failed to set vdev %d tx encap mode: %d\n",
--                          arvif->vdev_id, ret);
--              goto err_vdev_del;
--      }
-+      ath11k_mac_op_update_vif_offload(hw, vif);
-       nss = get_num_chains(ar->cfg_tx_chainmask) ? : 1;
-       ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
-@@ -5599,6 +5604,7 @@ static const struct ieee80211_ops ath11k
-       .reconfig_complete              = ath11k_mac_op_reconfig_complete,
-       .add_interface                  = ath11k_mac_op_add_interface,
-       .remove_interface               = ath11k_mac_op_remove_interface,
-+      .update_vif_offload             = ath11k_mac_op_update_vif_offload,
-       .config                         = ath11k_mac_op_config,
-       .bss_info_changed               = ath11k_mac_op_bss_info_changed,
-       .configure_filter               = ath11k_mac_op_configure_filter,
-@@ -5852,6 +5858,7 @@ static int __ath11k_mac_register(struct
-       ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
-       ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);
-       ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
-+      ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD);
-       if (ht_cap & WMI_HT_CAP_ENABLED) {
-               ieee80211_hw_set(ar->hw, AMPDU_AGGREGATION);
-               ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW);
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -1603,6 +1603,21 @@ enum ieee80211_vif_flags {
-       IEEE80211_VIF_GET_NOA_UPDATE            = BIT(3),
- };
-+
-+/**
-+ * enum ieee80211_offload_flags - virtual interface offload flags
-+ *
-+ * @IEEE80211_OFFLOAD_ENCAP_ENABLED: tx encapsulation offload is enabled
-+ *    The driver supports sending frames passed as 802.3 frames by mac80211.
-+ *    It must also support sending 802.11 packets for the same interface.
-+ * @IEEE80211_OFFLOAD_ENCAP_4ADDR: support 4-address mode encapsulation offload
-+ */
-+
-+enum ieee80211_offload_flags {
-+      IEEE80211_OFFLOAD_ENCAP_ENABLED         = BIT(0),
-+      IEEE80211_OFFLOAD_ENCAP_4ADDR           = BIT(1),
-+};
-+
- /**
-  * struct ieee80211_vif - per-interface data
-  *
-@@ -1623,6 +1638,11 @@ enum ieee80211_vif_flags {
-  *    these need to be set (or cleared) when the interface is added
-  *    or, if supported by the driver, the interface type is changed
-  *    at runtime, mac80211 will never touch this field
-+ * @offloaad_flags: hardware offload capabilities/flags for this interface.
-+ *    These are initialized by mac80211 before calling .add_interface,
-+ *    .change_interface or .update_vif_offload and updated by the driver
-+ *    within these ops, based on supported features or runtime change
-+ *    restrictions.
-  * @hw_queue: hardware queue for each AC
-  * @cab_queue: content-after-beacon (DTIM beacon really) queue, AP mode only
-  * @chanctx_conf: The channel context this interface is assigned to, or %NULL
-@@ -1659,6 +1679,7 @@ struct ieee80211_vif {
-       struct ieee80211_chanctx_conf __rcu *chanctx_conf;
-       u32 driver_flags;
-+      u32 offload_flags;
- #ifdef CPTCFG_MAC80211_DEBUGFS
-       struct dentry *debugfs_dir;
-@@ -2325,6 +2346,9 @@ struct ieee80211_txq {
-  *    aggregating MPDUs with the same keyid, allowing mac80211 to keep Tx
-  *    A-MPDU sessions active while rekeying with Extended Key ID.
-  *
-+ * @IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD: Hardware supports tx encapsulation
-+ *    offload
-+ *
-  * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
-  */
- enum ieee80211_hw_flags {
-@@ -2377,6 +2401,7 @@ enum ieee80211_hw_flags {
-       IEEE80211_HW_SUPPORTS_MULTI_BSSID,
-       IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID,
-       IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT,
-+      IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD,
-       /* keep last, obviously */
-       NUM_IEEE80211_HW_FLAGS
-@@ -3811,6 +3836,8 @@ enum ieee80211_reconfig_type {
-  * @set_tid_config: Apply TID specific configurations. This callback may sleep.
-  * @reset_tid_config: Reset TID specific configuration for the peer.
-  *    This callback may sleep.
-+ * @update_vif_config: Update virtual interface offload flags
-+ *    This callback may sleep.
-  */
- struct ieee80211_ops {
-       void (*tx)(struct ieee80211_hw *hw,
-@@ -4122,6 +4149,8 @@ struct ieee80211_ops {
-       int (*reset_tid_config)(struct ieee80211_hw *hw,
-                               struct ieee80211_vif *vif,
-                               struct ieee80211_sta *sta, u8 tids);
-+      void (*update_vif_offload)(struct ieee80211_hw *hw,
-+                                 struct ieee80211_vif *vif);
- };
- /**
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -504,6 +504,7 @@ static int ieee80211_del_key(struct wiph
-       struct ieee80211_local *local = sdata->local;
-       struct sta_info *sta;
-       struct ieee80211_key *key = NULL;
-+      bool recalc_offload = false;
-       int ret;
-       mutex_lock(&local->sta_mtx);
-@@ -528,6 +529,7 @@ static int ieee80211_del_key(struct wiph
-               goto out_unlock;
-       }
-+      recalc_offload = key->conf.cipher == WLAN_CIPHER_SUITE_TKIP;
-       ieee80211_key_free(key, sdata->vif.type == NL80211_IFTYPE_STATION);
-       ret = 0;
-@@ -535,6 +537,9 @@ static int ieee80211_del_key(struct wiph
-       mutex_unlock(&local->key_mtx);
-       mutex_unlock(&local->sta_mtx);
-+      if (recalc_offload)
-+              ieee80211_recalc_offload(local);
-+
-       return ret;
- }
---- a/net/mac80211/debugfs.c
-+++ b/net/mac80211/debugfs.c
-@@ -408,6 +408,7 @@ static const char *hw_flag_names[] = {
-       FLAG(SUPPORTS_MULTI_BSSID),
-       FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
-       FLAG(AMPDU_KEYBORDER_SUPPORT),
-+      FLAG(SUPPORTS_TX_ENCAP_OFFLOAD),
- #undef FLAG
- };
---- a/net/mac80211/driver-ops.h
-+++ b/net/mac80211/driver-ops.h
-@@ -1385,4 +1385,19 @@ static inline int drv_reset_tid_config(s
-       return ret;
- }
-+
-+static inline void drv_update_vif_offload(struct ieee80211_local *local,
-+                                        struct ieee80211_sub_if_data *sdata)
-+{
-+      might_sleep();
-+      check_sdata_in_driver(sdata);
-+
-+      if (!local->ops->update_vif_offload)
-+              return;
-+
-+      trace_drv_update_vif_offload(local, sdata);
-+      local->ops->update_vif_offload(&local->hw, &sdata->vif);
-+      trace_drv_return_void(local);
-+}
-+
- #endif /* __MAC80211_DRIVER_OPS */
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -990,8 +990,6 @@ struct ieee80211_sub_if_data {
-       } debugfs;
- #endif
--      bool hw_80211_encap;
--
-       /* must be last, dynamically sized area in this! */
-       struct ieee80211_vif vif;
- };
-@@ -1769,6 +1767,7 @@ void ieee80211_del_virtual_monitor(struc
- bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
- void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata,
-                             bool update_bss);
-+void ieee80211_recalc_offload(struct ieee80211_local *local);
- static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
- {
---- a/net/mac80211/iface.c
-+++ b/net/mac80211/iface.c
-@@ -43,6 +43,7 @@
-  */
- static void ieee80211_iface_work(struct work_struct *work);
-+static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata);
- bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
- {
-@@ -348,6 +349,99 @@ static int ieee80211_check_queues(struct
-       return 0;
- }
-+static bool ieee80211_iftype_supports_encap_offload(enum nl80211_iftype iftype)
-+{
-+      switch (iftype) {
-+      case NL80211_IFTYPE_AP:
-+      case NL80211_IFTYPE_P2P_GO:
-+      case NL80211_IFTYPE_P2P_CLIENT:
-+      case NL80211_IFTYPE_STATION:
-+              return true;
-+      default:
-+              return false;
-+      }
-+}
-+
-+static bool ieee80211_set_sdata_offload_flags(struct ieee80211_sub_if_data *sdata)
-+{
-+      struct ieee80211_local *local = sdata->local;
-+      struct ieee80211_key *key;
-+      u32 flags;
-+
-+      flags = sdata->vif.offload_flags;
-+
-+      if (ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) &&
-+          ieee80211_iftype_supports_encap_offload(sdata->vif.type)) {
-+              flags |= IEEE80211_OFFLOAD_ENCAP_ENABLED;
-+              mutex_lock(&local->key_mtx);
-+              list_for_each_entry(key, &sdata->key_list, list) {
-+                      if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
-+                          key->conf.cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
-+                          key->conf.cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 ||
-+                          key->conf.cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256)
-+                              continue;
-+                      if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP ||
-+                          !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
-+                              flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
-+              }
-+              mutex_unlock(&local->key_mtx);
-+
-+              if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) &&
-+                  local->hw.wiphy->frag_threshold != (u32)-1)
-+                      flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
-+
-+              if (local->monitors)
-+                      flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
-+      } else {
-+              flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
-+      }
-+
-+      if (sdata->vif.offload_flags == flags)
-+              return false;
-+
-+      sdata->vif.offload_flags = flags;
-+      return true;
-+}
-+
-+
-+static void ieee80211_recalc_sdata_offload(struct ieee80211_sub_if_data *sdata)
-+{
-+      struct ieee80211_local *local = sdata->local;
-+      struct ieee80211_sub_if_data *vsdata;
-+
-+      if (ieee80211_set_sdata_offload_flags(sdata)) {
-+              drv_update_vif_offload(local, sdata);
-+              ieee80211_set_vif_encap_ops(sdata);
-+      }
-+
-+      list_for_each_entry(vsdata, &local->interfaces, list) {
-+              if (vsdata->vif.type != NL80211_IFTYPE_AP_VLAN ||
-+                  vsdata->bss != &sdata->u.ap)
-+                      continue;
-+
-+              ieee80211_set_vif_encap_ops(vsdata);
-+      }
-+}
-+
-+void ieee80211_recalc_offload(struct ieee80211_local *local)
-+{
-+      struct ieee80211_sub_if_data *sdata;
-+
-+      if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD))
-+              return;
-+
-+      mutex_lock(&local->iflist_mtx);
-+
-+      list_for_each_entry(sdata, &local->interfaces, list) {
-+              if (!ieee80211_sdata_running(sdata))
-+                      continue;
-+
-+              ieee80211_recalc_sdata_offload(sdata);
-+      }
-+
-+      mutex_unlock(&local->iflist_mtx);
-+}
-+
- void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
-                                   const int offset)
- {
-@@ -587,6 +681,7 @@ int ieee80211_do_open(struct wireless_de
-               if (rtnl_dereference(sdata->bss->beacon)) {
-                       ieee80211_vif_vlan_copy_chanctx(sdata);
-                       netif_carrier_on(dev);
-+                      ieee80211_set_vif_encap_ops(sdata);
-               } else {
-                       netif_carrier_off(dev);
-               }
-@@ -616,6 +711,7 @@ int ieee80211_do_open(struct wireless_de
-               ieee80211_adjust_monitor_flags(sdata, 1);
-               ieee80211_configure_filter(local);
-+              ieee80211_recalc_offload(local);
-               mutex_lock(&local->mtx);
-               ieee80211_recalc_idle(local);
-               mutex_unlock(&local->mtx);
-@@ -625,10 +721,13 @@ int ieee80211_do_open(struct wireless_de
-       default:
-               if (coming_up) {
-                       ieee80211_del_virtual_monitor(local);
-+                      ieee80211_set_sdata_offload_flags(sdata);
-                       res = drv_add_interface(local, sdata);
-                       if (res)
-                               goto err_stop;
-+
-+                      ieee80211_set_vif_encap_ops(sdata);
-                       res = ieee80211_check_queues(sdata,
-                               ieee80211_vif_type_p2p(&sdata->vif));
-                       if (res)
-@@ -1286,61 +1385,6 @@ static const struct net_device_ops ieee8
- };
--static void __ieee80211_set_hw_80211_encap(struct ieee80211_sub_if_data *sdata,
--                                         bool enable)
--{
--      sdata->dev->netdev_ops = enable ? &ieee80211_dataif_8023_ops :
--                                        &ieee80211_dataif_ops;
--      sdata->hw_80211_encap = enable;
--}
--
--bool ieee80211_set_hw_80211_encap(struct ieee80211_vif *vif, bool enable)
--{
--      struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
--      struct ieee80211_local *local = sdata->local;
--      struct ieee80211_sub_if_data *iter;
--      struct ieee80211_key *key;
--
--      mutex_lock(&local->iflist_mtx);
--      list_for_each_entry(iter, &local->interfaces, list) {
--              struct ieee80211_sub_if_data *disable = NULL;
--
--              if (vif->type == NL80211_IFTYPE_MONITOR) {
--                      disable = iter;
--                      __ieee80211_set_hw_80211_encap(iter, false);
--              } else if (iter->vif.type == NL80211_IFTYPE_MONITOR) {
--                      disable = sdata;
--                      enable = false;
--              }
--              if (disable)
--                      sdata_dbg(disable,
--                                "disable hw 80211 encap due to mon co-exist\n");
--      }
--      mutex_unlock(&local->iflist_mtx);
--
--      if (enable == sdata->hw_80211_encap)
--              return enable;
--
--      if (!sdata->dev)
--              return false;
--
--      if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) &&
--          (local->hw.wiphy->frag_threshold != (u32)-1))
--              enable = false;
--
--      mutex_lock(&sdata->local->key_mtx);
--      list_for_each_entry(key, &sdata->key_list, list) {
--              if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
--                      enable = false;
--      }
--      mutex_unlock(&sdata->local->key_mtx);
--
--      __ieee80211_set_hw_80211_encap(sdata, enable);
--
--      return enable;
--}
--EXPORT_SYMBOL(ieee80211_set_hw_80211_encap);
--
- static void ieee80211_if_free(struct net_device *dev)
- {
-       free_percpu(netdev_tstats(dev));
-@@ -1371,6 +1415,51 @@ static void ieee80211_if_setup_no_queue(
- #endif
- }
-+static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata)
-+{
-+      struct ieee80211_local *local = sdata->local;
-+      struct ieee80211_sub_if_data *bss = sdata;
-+      struct ieee80211_key *key;
-+      bool enabled;
-+
-+      if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
-+              if (!sdata->bss)
-+                      return;
-+
-+              bss = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
-+      }
-+
-+      if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) ||
-+          !ieee80211_iftype_supports_encap_offload(bss->vif.type))
-+              return;
-+
-+      enabled = bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED;
-+      if (sdata->wdev.use_4addr &&
-+          !(bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_4ADDR))
-+              enabled = false;
-+
-+      /*
-+       * Encapsulation offload cannot be used with software crypto, and a per-VLAN
-+       * key may have been set
-+       */
-+      if (enabled && sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
-+              mutex_lock(&local->key_mtx);
-+              list_for_each_entry(key, &sdata->key_list, list) {
-+                      if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
-+                          key->conf.cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
-+                          key->conf.cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 ||
-+                          key->conf.cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256)
-+                              continue;
-+                      if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
-+                              enabled = false;
-+              }
-+              mutex_unlock(&local->key_mtx);
-+      }
-+
-+      sdata->dev->netdev_ops = enabled ? &ieee80211_dataif_8023_ops :
-+                                         &ieee80211_dataif_ops;
-+}
-+
- static void ieee80211_iface_work(struct work_struct *work)
- {
-       struct ieee80211_sub_if_data *sdata =
-@@ -1553,7 +1642,6 @@ static void ieee80211_setup_sdata(struct
-       sdata->vif.bss_conf.txpower = INT_MIN; /* unset */
-       sdata->noack_map = 0;
--      sdata->hw_80211_encap = false;
-       /* only monitor/p2p-device differ */
-       if (sdata->dev) {
-@@ -1688,6 +1776,7 @@ static int ieee80211_runtime_change_ifty
-       ieee80211_teardown_sdata(sdata);
-+      ieee80211_set_sdata_offload_flags(sdata);
-       ret = drv_change_interface(local, sdata, internal_type, p2p);
-       if (ret)
-               type = ieee80211_vif_type_p2p(&sdata->vif);
-@@ -1700,6 +1789,7 @@ static int ieee80211_runtime_change_ifty
-       ieee80211_check_queues(sdata, type);
-       ieee80211_setup_sdata(sdata, type);
-+      ieee80211_set_vif_encap_ops(sdata);
-       err = ieee80211_do_open(&sdata->wdev, false);
-       WARN(err, "type change: do_open returned %d", err);
---- a/net/mac80211/key.c
-+++ b/net/mac80211/key.c
-@@ -177,13 +177,6 @@ static int ieee80211_key_enable_hw_accel
-               }
-       }
--      /* TKIP countermeasures don't work in encap offload mode */
--      if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP &&
--          sdata->hw_80211_encap) {
--              sdata_dbg(sdata, "TKIP is not allowed in hw 80211 encap mode\n");
--              return -EINVAL;
--      }
--
-       ret = drv_set_key(key->local, SET_KEY, sdata,
-                         sta ? &sta->sta : NULL, &key->conf);
-@@ -219,14 +212,6 @@ static int ieee80211_key_enable_hw_accel
-       case WLAN_CIPHER_SUITE_CCMP_256:
-       case WLAN_CIPHER_SUITE_GCMP:
-       case WLAN_CIPHER_SUITE_GCMP_256:
--              /* We cannot do software crypto of data frames with
--               * encapsulation offload enabled. However for 802.11w to
--               * function properly we need cmac/gmac keys.
--               */
--              if (sdata->hw_80211_encap)
--                      return -EINVAL;
--              /* Fall through */
--
-       case WLAN_CIPHER_SUITE_AES_CMAC:
-       case WLAN_CIPHER_SUITE_BIP_CMAC_256:
-       case WLAN_CIPHER_SUITE_BIP_GMAC_128:
-@@ -824,6 +809,7 @@ int ieee80211_key_link(struct ieee80211_
-        */
-       bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION;
-       int ret = -EOPNOTSUPP;
-+      bool recalc_offload = false;
-       mutex_lock(&sdata->local->key_mtx);
-@@ -864,11 +850,15 @@ int ieee80211_key_link(struct ieee80211_
-       key->local = sdata->local;
-       key->sdata = sdata;
-       key->sta = sta;
-+      recalc_offload = !old_key && key->conf.cipher == WLAN_CIPHER_SUITE_TKIP;
-       increment_tailroom_need_count(sdata);
-       ret = ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
-+      if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
-+              recalc_offload = true;
-+
-       if (!ret) {
-               ieee80211_debugfs_key_add(key);
-               ieee80211_key_destroy(old_key, delay_tailroom);
-@@ -879,6 +869,9 @@ int ieee80211_key_link(struct ieee80211_
-  out:
-       mutex_unlock(&sdata->local->key_mtx);
-+      if (recalc_offload)
-+              ieee80211_recalc_offload(sdata->local);
-+
-       return ret;
- }
---- a/net/mac80211/trace.h
-+++ b/net/mac80211/trace.h
-@@ -2733,6 +2733,12 @@ TRACE_EVENT(drv_get_ftm_responder_stats,
-       )
- );
-+DEFINE_EVENT(local_sdata_addr_evt, drv_update_vif_offload,
-+      TP_PROTO(struct ieee80211_local *local,
-+               struct ieee80211_sub_if_data *sdata),
-+      TP_ARGS(local, sdata)
-+);
-+
- #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
- #undef TRACE_INCLUDE_PATH
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -4264,11 +4264,6 @@ netdev_tx_t ieee80211_subif_start_xmit_8
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       struct sta_info *sta;
--      if (WARN_ON(!sdata->hw_80211_encap)) {
--              kfree_skb(skb);
--              return NETDEV_TX_OK;
--      }
--
-       if (unlikely(skb->len < ETH_HLEN)) {
-               kfree_skb(skb);
-               return NETDEV_TX_OK;
diff --git a/package/kernel/mac80211/patches/subsys/315-mac80211-check-and-refresh-aggregation-session-in-en.patch b/package/kernel/mac80211/patches/subsys/315-mac80211-check-and-refresh-aggregation-session-in-en.patch
new file mode 100644 (file)
index 0000000..e411d59
--- /dev/null
@@ -0,0 +1,45 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Mon, 17 Aug 2020 21:11:25 +0200
+Subject: [PATCH] mac80211: check and refresh aggregation session in
+ encap offload tx
+
+Update the last_tx timestamp to avoid tearing down the aggregation session
+early. Fall back to the slow path if the session setup is still running
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -4189,6 +4189,8 @@ static void ieee80211_8023_xmit(struct i
+       bool authorized = false;
+       bool multicast;
+       unsigned char *ra = ehdr->h_dest;
++      struct tid_ampdu_tx *tid_tx;
++      u8 tid;
+       if (IS_ERR(sta) || (sta && !sta->uploaded))
+               sta = NULL;
+@@ -4226,6 +4228,22 @@ static void ieee80211_8023_xmit(struct i
+       memset(info, 0, sizeof(*info));
++      if (sta) {
++              tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
++              tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
++              if (tid_tx) {
++                      if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
++                              /* fall back to non-offload slow path */
++                              __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL);
++                              return;
++                      }
++
++                      info->flags |= IEEE80211_TX_CTL_AMPDU;
++                      if (tid_tx->timeout)
++                              tid_tx->last_tx = jiffies;
++              }
++      }
++
+       if (unlikely(!multicast && skb->sk &&
+                    skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS))
+               info->ack_frame_id = ieee80211_store_ack_skb(local, skb,
diff --git a/package/kernel/mac80211/patches/subsys/315-mac80211-reduce-duplication-in-tx-status-functions.patch b/package/kernel/mac80211/patches/subsys/315-mac80211-reduce-duplication-in-tx-status-functions.patch
deleted file mode 100644 (file)
index 8b664d6..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Mon, 17 Aug 2020 13:16:59 +0200
-Subject: [PATCH] mac80211: reduce duplication in tx status functions
-
-Move redundant functionality from __ieee80211_tx_status into
-ieee80211_tx_status_ext. Preparation for unifying with the 802.3 tx status
-codepath.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -184,18 +184,6 @@ static void ieee80211_frame_acked(struct
-       struct ieee80211_mgmt *mgmt = (void *) skb->data;
-       struct ieee80211_local *local = sta->local;
-       struct ieee80211_sub_if_data *sdata = sta->sdata;
--      struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
--
--      if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
--              sta->status_stats.last_ack = jiffies;
--              if (txinfo->status.is_valid_ack_signal) {
--                      sta->status_stats.last_ack_signal =
--                                       (s8)txinfo->status.ack_signal;
--                      sta->status_stats.ack_signal_filled = true;
--                      ewma_avg_signal_add(&sta->status_stats.avg_ack_signal,
--                                          -txinfo->status.ack_signal);
--              }
--      }
-       if (ieee80211_is_data_qos(mgmt->frame_control)) {
-               struct ieee80211_hdr *hdr = (void *) skb->data;
-@@ -899,7 +887,8 @@ void ieee80211_tx_monitor(struct ieee802
- }
- static void __ieee80211_tx_status(struct ieee80211_hw *hw,
--                                struct ieee80211_tx_status *status)
-+                                struct ieee80211_tx_status *status,
-+                                int rates_idx, int retry_count)
- {
-       struct sk_buff *skb = status->skb;
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-@@ -908,8 +897,6 @@ static void __ieee80211_tx_status(struct
-       struct sta_info *sta;
-       __le16 fc;
-       struct ieee80211_supported_band *sband;
--      int retry_count;
--      int rates_idx;
-       bool send_to_cooked;
-       bool acked;
-       bool noack_success;
-@@ -918,8 +905,6 @@ static void __ieee80211_tx_status(struct
-       int tid = IEEE80211_NUM_TIDS;
-       u16 tx_time_est;
--      rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
--
-       sband = local->hw.wiphy->bands[info->band];
-       fc = hdr->frame_control;
-@@ -996,24 +981,14 @@ static void __ieee80211_tx_status(struct
-               if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
-                       ieee80211_handle_filtered_frame(local, sta, skb);
-                       return;
--              } else {
-+              } else if (ieee80211_is_data_present(fc)) {
-                       if (!acked && !noack_success)
--                              sta->status_stats.retry_failed++;
--                      sta->status_stats.retry_count += retry_count;
--
--                      if (ieee80211_is_data_present(fc)) {
--                              if (!acked && !noack_success)
--                                      sta->status_stats.msdu_failed[tid]++;
-+                              sta->status_stats.msdu_failed[tid]++;
--                              sta->status_stats.msdu_retries[tid] +=
--                                      retry_count;
--                      }
-+                      sta->status_stats.msdu_retries[tid] +=
-+                              retry_count;
-               }
--              rate_control_tx_status(local, sband, status);
--              if (ieee80211_vif_is_mesh(&sta->sdata->vif))
--                      ieee80211s_update_metric(local, sta, status);
--
-               if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && acked)
-                       ieee80211_frame_acked(sta, skb);
-@@ -1038,20 +1013,6 @@ static void __ieee80211_tx_status(struct
-                                                            true);
-                       ieee80211_info_set_tx_time_est(info, 0);
-               }
--
--              if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
--                      if (acked) {
--                              if (sta->status_stats.lost_packets)
--                                      sta->status_stats.lost_packets = 0;
--
--                              /* Track when last TDLS packet was ACKed */
--                              sta->status_stats.last_pkt_time = jiffies;
--                      } else if (noack_success) {
--                              /* nothing to do here, do not account as lost */
--                      } else {
--                              ieee80211_lost_packet(sta, info);
--                      }
--              }
-       }
-       /* SNMP counters
-@@ -1135,7 +1096,7 @@ void ieee80211_tx_status(struct ieee8021
-       if (sta)
-               status.sta = &sta->sta;
--      __ieee80211_tx_status(hw, &status);
-+      ieee80211_tx_status_ext(hw, &status);
-       rcu_read_unlock();
- }
- EXPORT_SYMBOL(ieee80211_tx_status);
-@@ -1148,7 +1109,7 @@ void ieee80211_tx_status_ext(struct ieee
-       struct ieee80211_sta *pubsta = status->sta;
-       struct ieee80211_supported_band *sband;
-       struct sta_info *sta;
--      int retry_count;
-+      int rates_idx, retry_count;
-       bool acked, noack_success;
-       if (pubsta) {
-@@ -1158,13 +1119,7 @@ void ieee80211_tx_status_ext(struct ieee
-                       sta->tx_stats.last_rate_info = *status->rate;
-       }
--      if (status->skb)
--              return __ieee80211_tx_status(hw, status);
--
--      if (!status->sta)
--              return;
--
--      ieee80211_tx_get_rates(hw, info, &retry_count);
-+      rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
-       sband = hw->wiphy->bands[info->band];
-@@ -1176,20 +1131,30 @@ void ieee80211_tx_status_ext(struct ieee
-                       sta->status_stats.retry_failed++;
-               sta->status_stats.retry_count += retry_count;
--              if (acked) {
--                      sta->status_stats.last_ack = jiffies;
-+              if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
-+                      if (acked) {
-+                              sta->status_stats.last_ack = jiffies;
--                      if (sta->status_stats.lost_packets)
--                              sta->status_stats.lost_packets = 0;
-+                              if (sta->status_stats.lost_packets)
-+                                      sta->status_stats.lost_packets = 0;
--                      /* Track when last packet was ACKed */
--                      sta->status_stats.last_pkt_time = jiffies;
--              } else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
--                      return;
--              } else if (noack_success) {
--                      /* nothing to do here, do not account as lost */
--              } else {
--                      ieee80211_lost_packet(sta, info);
-+                              /* Track when last packet was ACKed */
-+                              sta->status_stats.last_pkt_time = jiffies;
-+
-+                              if (info->status.is_valid_ack_signal) {
-+                                      sta->status_stats.last_ack_signal =
-+                                                       (s8)info->status.ack_signal;
-+                                      sta->status_stats.ack_signal_filled = true;
-+                                      ewma_avg_signal_add(&sta->status_stats.avg_ack_signal,
-+                                                          -info->status.ack_signal);
-+                              }
-+                      } else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
-+                              return;
-+                      } else if (noack_success) {
-+                              /* nothing to do here, do not account as lost */
-+                      } else {
-+                              ieee80211_lost_packet(sta, info);
-+                      }
-               }
-               rate_control_tx_status(local, sband, status);
-@@ -1197,6 +1162,10 @@ void ieee80211_tx_status_ext(struct ieee
-                       ieee80211s_update_metric(local, sta, status);
-       }
-+      if (status->skb)
-+              return __ieee80211_tx_status(hw, status, rates_idx,
-+                                           retry_count);
-+
-       if (acked || noack_success) {
-               I802_DEBUG_INC(local->dot11TransmittedFrameCount);
-               if (!pubsta)
diff --git a/package/kernel/mac80211/patches/subsys/316-mac80211-remove-tx-status-call-to-ieee80211_sta_regi.patch b/package/kernel/mac80211/patches/subsys/316-mac80211-remove-tx-status-call-to-ieee80211_sta_regi.patch
deleted file mode 100644 (file)
index 168d645..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Mon, 17 Aug 2020 13:29:12 +0200
-Subject: [PATCH] mac80211: remove tx status call to
- ieee80211_sta_register_airtime
-
-All drivers using airtime fairness are calling ieee80211_sta_register_airtime
-directly
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -997,12 +997,6 @@ static void __ieee80211_tx_status(struct
-                       ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data,
-                                               acked, info->status.tx_time);
--              if (info->status.tx_time &&
--                  wiphy_ext_feature_isset(local->hw.wiphy,
--                                          NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
--                      ieee80211_sta_register_airtime(&sta->sta, tid,
--                                                     info->status.tx_time, 0);
--
-               if ((tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) {
-                       /* Do this here to avoid the expensive lookup of the sta
-                        * in ieee80211_report_used_skb().
diff --git a/package/kernel/mac80211/patches/subsys/316-mac80211-skip-encap-offload-for-tx-multicast-control.patch b/package/kernel/mac80211/patches/subsys/316-mac80211-skip-encap-offload-for-tx-multicast-control.patch
new file mode 100644 (file)
index 0000000..6dce21d
--- /dev/null
@@ -0,0 +1,136 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Fri, 21 Aug 2020 05:54:10 +0200
+Subject: [PATCH] mac80211: skip encap offload for tx multicast/control
+ packets
+
+This simplifies the checks in the encap offload tx handler and allows using
+it in cases where software crypto is used for multicast packets, e.g. when
+using an AP_VLAN.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -4184,88 +4184,47 @@ static void ieee80211_8023_xmit(struct i
+                               struct sk_buff *skb)
+ {
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+-      struct ethhdr *ehdr = (struct ethhdr *)skb->data;
+       struct ieee80211_local *local = sdata->local;
+-      bool authorized = false;
+-      bool multicast;
+-      unsigned char *ra = ehdr->h_dest;
+       struct tid_ampdu_tx *tid_tx;
+       u8 tid;
+-      if (IS_ERR(sta) || (sta && !sta->uploaded))
+-              sta = NULL;
+-
+-      if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+-          (!sta || !test_sta_flag(sta, WLAN_STA_TDLS_PEER)))
+-              ra = sdata->u.mgd.bssid;
+-
+-      if (is_zero_ether_addr(ra))
+-              goto out_free;
+-
+       if (local->ops->wake_tx_queue) {
+               u16 queue = __ieee80211_select_queue(sdata, sta, skb);
+               skb_set_queue_mapping(skb, queue);
+               skb_get_hash(skb);
+       }
+-      multicast = is_multicast_ether_addr(ra);
+-
+-      if (sta)
+-              authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
+-
+-      if (!multicast && !authorized &&
+-          (ehdr->h_proto != sdata->control_port_protocol ||
+-           !ether_addr_equal(sdata->vif.addr, ehdr->h_source)))
+-              goto out_free;
+-
+-      if (multicast && sdata->vif.type == NL80211_IFTYPE_AP &&
+-          !atomic_read(&sdata->u.ap.num_mcast_sta))
+-              goto out_free;
+-
+       if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) &&
+           test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
+               goto out_free;
+       memset(info, 0, sizeof(*info));
+-      if (sta) {
+-              tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
+-              tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
+-              if (tid_tx) {
+-                      if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
+-                              /* fall back to non-offload slow path */
+-                              __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL);
+-                              return;
+-                      }
+-
+-                      info->flags |= IEEE80211_TX_CTL_AMPDU;
+-                      if (tid_tx->timeout)
+-                              tid_tx->last_tx = jiffies;
++      tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
++      tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
++      if (tid_tx) {
++              if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
++                      /* fall back to non-offload slow path */
++                      __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL);
++                      return;
+               }
++
++              info->flags |= IEEE80211_TX_CTL_AMPDU;
++              if (tid_tx->timeout)
++                      tid_tx->last_tx = jiffies;
+       }
+-      if (unlikely(!multicast && skb->sk &&
++      if (unlikely(skb->sk &&
+                    skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS))
+               info->ack_frame_id = ieee80211_store_ack_skb(local, skb,
+                                                            &info->flags, NULL);
+-      if (unlikely(sdata->control_port_protocol == ehdr->h_proto)) {
+-              if (sdata->control_port_no_encrypt)
+-                      info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+-              info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
+-      }
+-
+-      if (multicast)
+-              info->flags |= IEEE80211_TX_CTL_NO_ACK;
+-
+       info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
+       ieee80211_tx_stats(dev, skb->len);
+-      if (sta) {
+-              sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
+-              sta->tx_stats.packets[skb_get_queue_mapping(skb)]++;
+-      }
++      sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
++      sta->tx_stats.packets[skb_get_queue_mapping(skb)]++;
+       if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+               sdata = container_of(sdata->bss,
+@@ -4286,6 +4245,7 @@ netdev_tx_t ieee80211_subif_start_xmit_8
+                                           struct net_device *dev)
+ {
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++      struct ethhdr *ehdr = (struct ethhdr *)skb->data;
+       struct sta_info *sta;
+       if (WARN_ON(!sdata->hw_80211_encap)) {
+@@ -4302,6 +4262,10 @@ netdev_tx_t ieee80211_subif_start_xmit_8
+       if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
+               kfree_skb(skb);
++      else if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded ||
++                        !test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
++                        sdata->control_port_protocol == ehdr->h_proto))
++              ieee80211_subif_start_xmit(skb, dev);
+       else
+               ieee80211_8023_xmit(sdata, dev, sta, skb);
diff --git a/package/kernel/mac80211/patches/subsys/317-mac80211-optimize-station-connection-monitor.patch b/package/kernel/mac80211/patches/subsys/317-mac80211-optimize-station-connection-monitor.patch
deleted file mode 100644 (file)
index ed9efb2..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Mon, 17 Aug 2020 13:29:56 +0200
-Subject: [PATCH] mac80211: optimize station connection monitor
-
-Calling mod_timer for every rx/tx packet can be quite expensive.
-Instead of constantly updating the timer, we can simply let it run out
-and check the timestamp of the last ACK or rx packet to re-arm it.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -2045,8 +2045,6 @@ void ieee80211_dynamic_ps_timer(struct t
- void ieee80211_send_nullfunc(struct ieee80211_local *local,
-                            struct ieee80211_sub_if_data *sdata,
-                            bool powersave);
--void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
--                           struct ieee80211_hdr *hdr);
- void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
-                            struct ieee80211_hdr *hdr, bool ack, u16 tx_time);
---- a/net/mac80211/mlme.c
-+++ b/net/mac80211/mlme.c
-@@ -2432,23 +2432,6 @@ static void ieee80211_set_disassoc(struc
-       sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
- }
--void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
--                           struct ieee80211_hdr *hdr)
--{
--      /*
--       * We can postpone the mgd.timer whenever receiving unicast frames
--       * from AP because we know that the connection is working both ways
--       * at that time. But multicast frames (and hence also beacons) must
--       * be ignored here, because we need to trigger the timer during
--       * data idle periods for sending the periodic probe request to the
--       * AP we're connected to.
--       */
--      if (is_multicast_ether_addr(hdr->addr1))
--              return;
--
--      ieee80211_sta_reset_conn_monitor(sdata);
--}
--
- static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
- {
-       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-@@ -2521,21 +2504,13 @@ void ieee80211_sta_tx_notify(struct ieee
- {
-       ieee80211_sta_tx_wmm_ac_notify(sdata, hdr, tx_time);
--      if (!ieee80211_is_data(hdr->frame_control))
--          return;
--
--      if (ieee80211_is_any_nullfunc(hdr->frame_control) &&
--          sdata->u.mgd.probe_send_count > 0) {
--              if (ack)
--                      ieee80211_sta_reset_conn_monitor(sdata);
--              else
--                      sdata->u.mgd.nullfunc_failed = true;
--              ieee80211_queue_work(&sdata->local->hw, &sdata->work);
-+      if (!ieee80211_is_any_nullfunc(hdr->frame_control) ||
-+          !sdata->u.mgd.probe_send_count)
-               return;
--      }
--      if (ack)
--              ieee80211_sta_reset_conn_monitor(sdata);
-+      if (!ack)
-+              sdata->u.mgd.nullfunc_failed = true;
-+      ieee80211_queue_work(&sdata->local->hw, &sdata->work);
- }
- static void ieee80211_mlme_send_probe_req(struct ieee80211_sub_if_data *sdata,
-@@ -3600,8 +3575,8 @@ static bool ieee80211_assoc_success(stru
-        * Start timer to probe the connection to the AP now.
-        * Also start the timer that will detect beacon loss.
-        */
--      ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
-       ieee80211_sta_reset_beacon_monitor(sdata);
-+      ieee80211_sta_reset_conn_monitor(sdata);
-       ret = true;
-  out:
-@@ -4569,10 +4544,26 @@ static void ieee80211_sta_conn_mon_timer
-               from_timer(sdata, t, u.mgd.conn_mon_timer);
-       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-       struct ieee80211_local *local = sdata->local;
-+      struct sta_info *sta;
-+      unsigned long timeout;
-       if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn)
-               return;
-+      sta = sta_info_get(sdata, ifmgd->bssid);
-+      if (!sta)
-+              return;
-+
-+      timeout = sta->status_stats.last_ack;
-+      if (time_before(sta->status_stats.last_ack, sta->rx_stats.last_rx))
-+              timeout = sta->rx_stats.last_rx;
-+      timeout += IEEE80211_CONNECTION_IDLE_TIME;
-+
-+      if (time_is_before_jiffies(timeout)) {
-+              mod_timer(&ifmgd->conn_mon_timer, round_jiffies_up(timeout));
-+              return;
-+      }
-+
-       ieee80211_queue_work(&local->hw, &ifmgd->monitor_work);
- }
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -1811,9 +1811,6 @@ ieee80211_rx_h_sta_process(struct ieee80
-                       sta->rx_stats.last_rate = sta_stats_encode_rate(status);
-       }
--      if (rx->sdata->vif.type == NL80211_IFTYPE_STATION)
--              ieee80211_sta_rx_notify(rx->sdata, hdr);
--
-       sta->rx_stats.fragments++;
-       u64_stats_update_begin(&rx->sta->rx_stats.syncp);
-@@ -4148,7 +4145,6 @@ void ieee80211_check_fast_rx(struct sta_
-                       fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr2);
-                       fastrx.expected_ds_bits = 0;
-               } else {
--                      fastrx.sta_notify = sdata->u.mgd.probe_send_count > 0;
-                       fastrx.da_offs = offsetof(struct ieee80211_hdr, addr1);
-                       fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr3);
-                       fastrx.expected_ds_bits =
-@@ -4378,11 +4374,6 @@ static bool ieee80211_invoke_fast_rx(str
-           pskb_trim(skb, skb->len - fast_rx->icv_len))
-               goto drop;
--      if (unlikely(fast_rx->sta_notify)) {
--              ieee80211_sta_rx_notify(rx->sdata, hdr);
--              fast_rx->sta_notify = false;
--      }
--
-       /* statistics part of ieee80211_rx_h_sta_process() */
-       if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
-               stats->last_signal = status->signal;
---- a/net/mac80211/sta_info.h
-+++ b/net/mac80211/sta_info.h
-@@ -336,7 +336,6 @@ struct ieee80211_fast_tx {
-  * @expected_ds_bits: from/to DS bits expected
-  * @icv_len: length of the MIC if present
-  * @key: bool indicating encryption is expected (key is set)
-- * @sta_notify: notify the MLME code (once)
-  * @internal_forward: forward froms internally on AP/VLAN type interfaces
-  * @uses_rss: copy of USES_RSS hw flag
-  * @da_offs: offset of the DA in the header (for header conversion)
-@@ -352,7 +351,6 @@ struct ieee80211_fast_rx {
-       __le16 expected_ds_bits;
-       u8 icv_len;
-       u8 key:1,
--         sta_notify:1,
-          internal_forward:1,
-          uses_rss:1;
-       u8 da_offs, sa_offs;
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -1227,9 +1227,6 @@ void ieee80211_tx_status_8023(struct iee
-       sta->status_stats.retry_count += retry_count;
-       if (ieee80211_hw_check(hw, REPORTS_TX_ACK_STATUS)) {
--              if (acked && vif->type == NL80211_IFTYPE_STATION)
--                      ieee80211_sta_reset_conn_monitor(sdata);
--
-               sta->status_stats.last_ack = jiffies;
-               if (info->flags & IEEE80211_TX_STAT_ACK) {
-                       if (sta->status_stats.lost_packets)
diff --git a/package/kernel/mac80211/patches/subsys/317-mac80211-set-info-control.hw_key-for-encap-offload-p.patch b/package/kernel/mac80211/patches/subsys/317-mac80211-set-info-control.hw_key-for-encap-offload-p.patch
new file mode 100644 (file)
index 0000000..cb5a986
--- /dev/null
@@ -0,0 +1,31 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Fri, 21 Aug 2020 06:03:45 +0200
+Subject: [PATCH] mac80211: set info->control.hw_key for encap offload
+ packets
+
+This is needed for drivers that don't do the key lookup themselves
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -4185,6 +4185,7 @@ static void ieee80211_8023_xmit(struct i
+ {
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_local *local = sdata->local;
++      struct ieee80211_key *key;
+       struct tid_ampdu_tx *tid_tx;
+       u8 tid;
+@@ -4233,6 +4234,10 @@ static void ieee80211_8023_xmit(struct i
+       info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP;
+       info->control.vif = &sdata->vif;
++      key = rcu_dereference(sta->ptk[sta->ptk_idx]);
++      if (key)
++              info->control.hw_key = &key->conf;
++
+       ieee80211_tx_8023(sdata, skb, skb->len, sta, false);
+       return;
diff --git a/package/kernel/mac80211/patches/subsys/318-mac80211-rework-tx-encapsulation-offload-API.patch b/package/kernel/mac80211/patches/subsys/318-mac80211-rework-tx-encapsulation-offload-API.patch
new file mode 100644 (file)
index 0000000..7593c41
--- /dev/null
@@ -0,0 +1,613 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Thu, 13 Aug 2020 15:37:11 +0200
+Subject: [PATCH] mac80211: rework tx encapsulation offload API
+
+The current API (which lets the driver turn on/off per vif directly) has a
+number of limitations:
+- it does not deal with AP_VLAN
+- conditions for enabling (no tkip, no monitor) are only checked at
+  add_interface time
+- no way to indicate 4-addr support
+
+In order to address this, store offload flags in struct ieee80211_vif
+(easy to extend for decap offload later). mac80211 initially sets the enable
+flag, but gives the driver a chance to modify it before its settings are
+applied. In addition to the .add_interface op, a .update_vif_offload op is
+introduced, which can be used for runtime changes.
+
+If a driver can't disable encap offload at runtime, or if it has some extra
+limitations, it can simply override the flags within those ops.
+
+Support for encap offload with 4-address mode interfaces can be enabled
+by setting a flag from .add_interface or .update_vif_offload.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath11k/mac.c
++++ b/drivers/net/wireless/ath/ath11k/mac.c
+@@ -4150,6 +4150,35 @@ static int ath11k_set_he_mu_sounding_mod
+       return ret;
+ }
++static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
++                                          struct ieee80211_vif *vif)
++{
++      struct ath11k *ar = hw->priv;
++      struct ath11k_base *ab = ar->ab;
++      struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
++      u32 param_id, param_value;
++      int ret;
++
++      param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;
++      if (ath11k_frame_mode != ATH11K_HW_TXRX_ETHERNET ||
++          (vif->type != NL80211_IFTYPE_STATION &&
++           vif->type != NL80211_IFTYPE_AP))
++              vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
++
++      if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
++              param_value = ATH11K_HW_TXRX_ETHERNET;
++      else
++              param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
++
++      ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
++                                          param_id, param_value);
++      if (ret) {
++              ath11k_warn(ab, "failed to set vdev %d tx encap mode: %d\n",
++                          arvif->vdev_id, ret);
++              vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
++      }
++}
++
+ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
+                                      struct ieee80211_vif *vif)
+ {
+@@ -4159,7 +4188,6 @@ static int ath11k_mac_op_add_interface(s
+       struct vdev_create_params vdev_param = {0};
+       struct peer_create_params peer_param;
+       u32 param_id, param_value;
+-      int hw_encap = 0;
+       u16 nss;
+       int i;
+       int ret;
+@@ -4253,30 +4281,7 @@ static int ath11k_mac_op_add_interface(s
+       list_add(&arvif->list, &ar->arvifs);
+       spin_unlock_bh(&ar->data_lock);
+-      param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;
+-      if (ath11k_frame_mode == ATH11K_HW_TXRX_ETHERNET)
+-              switch (vif->type) {
+-              case NL80211_IFTYPE_STATION:
+-              case NL80211_IFTYPE_AP_VLAN:
+-              case NL80211_IFTYPE_AP:
+-                      hw_encap = 1;
+-                      break;
+-              default:
+-                      break;
+-              }
+-
+-      if (ieee80211_set_hw_80211_encap(vif, hw_encap))
+-              param_value = ATH11K_HW_TXRX_ETHERNET;
+-      else
+-              param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
+-
+-      ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
+-                                          param_id, param_value);
+-      if (ret) {
+-              ath11k_warn(ab, "failed to set vdev %d tx encap mode: %d\n",
+-                          arvif->vdev_id, ret);
+-              goto err_vdev_del;
+-      }
++      ath11k_mac_op_update_vif_offload(hw, vif);
+       nss = get_num_chains(ar->cfg_tx_chainmask) ? : 1;
+       ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
+@@ -5599,6 +5604,7 @@ static const struct ieee80211_ops ath11k
+       .reconfig_complete              = ath11k_mac_op_reconfig_complete,
+       .add_interface                  = ath11k_mac_op_add_interface,
+       .remove_interface               = ath11k_mac_op_remove_interface,
++      .update_vif_offload             = ath11k_mac_op_update_vif_offload,
+       .config                         = ath11k_mac_op_config,
+       .bss_info_changed               = ath11k_mac_op_bss_info_changed,
+       .configure_filter               = ath11k_mac_op_configure_filter,
+@@ -5852,6 +5858,7 @@ static int __ath11k_mac_register(struct
+       ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
+       ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);
+       ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
++      ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD);
+       if (ht_cap & WMI_HT_CAP_ENABLED) {
+               ieee80211_hw_set(ar->hw, AMPDU_AGGREGATION);
+               ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW);
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -1603,6 +1603,21 @@ enum ieee80211_vif_flags {
+       IEEE80211_VIF_GET_NOA_UPDATE            = BIT(3),
+ };
++
++/**
++ * enum ieee80211_offload_flags - virtual interface offload flags
++ *
++ * @IEEE80211_OFFLOAD_ENCAP_ENABLED: tx encapsulation offload is enabled
++ *    The driver supports sending frames passed as 802.3 frames by mac80211.
++ *    It must also support sending 802.11 packets for the same interface.
++ * @IEEE80211_OFFLOAD_ENCAP_4ADDR: support 4-address mode encapsulation offload
++ */
++
++enum ieee80211_offload_flags {
++      IEEE80211_OFFLOAD_ENCAP_ENABLED         = BIT(0),
++      IEEE80211_OFFLOAD_ENCAP_4ADDR           = BIT(1),
++};
++
+ /**
+  * struct ieee80211_vif - per-interface data
+  *
+@@ -1623,6 +1638,11 @@ enum ieee80211_vif_flags {
+  *    these need to be set (or cleared) when the interface is added
+  *    or, if supported by the driver, the interface type is changed
+  *    at runtime, mac80211 will never touch this field
++ * @offloaad_flags: hardware offload capabilities/flags for this interface.
++ *    These are initialized by mac80211 before calling .add_interface,
++ *    .change_interface or .update_vif_offload and updated by the driver
++ *    within these ops, based on supported features or runtime change
++ *    restrictions.
+  * @hw_queue: hardware queue for each AC
+  * @cab_queue: content-after-beacon (DTIM beacon really) queue, AP mode only
+  * @chanctx_conf: The channel context this interface is assigned to, or %NULL
+@@ -1659,6 +1679,7 @@ struct ieee80211_vif {
+       struct ieee80211_chanctx_conf __rcu *chanctx_conf;
+       u32 driver_flags;
++      u32 offload_flags;
+ #ifdef CPTCFG_MAC80211_DEBUGFS
+       struct dentry *debugfs_dir;
+@@ -2325,6 +2346,9 @@ struct ieee80211_txq {
+  *    aggregating MPDUs with the same keyid, allowing mac80211 to keep Tx
+  *    A-MPDU sessions active while rekeying with Extended Key ID.
+  *
++ * @IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD: Hardware supports tx encapsulation
++ *    offload
++ *
+  * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
+  */
+ enum ieee80211_hw_flags {
+@@ -2377,6 +2401,7 @@ enum ieee80211_hw_flags {
+       IEEE80211_HW_SUPPORTS_MULTI_BSSID,
+       IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID,
+       IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT,
++      IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD,
+       /* keep last, obviously */
+       NUM_IEEE80211_HW_FLAGS
+@@ -3811,6 +3836,8 @@ enum ieee80211_reconfig_type {
+  * @set_tid_config: Apply TID specific configurations. This callback may sleep.
+  * @reset_tid_config: Reset TID specific configuration for the peer.
+  *    This callback may sleep.
++ * @update_vif_config: Update virtual interface offload flags
++ *    This callback may sleep.
+  */
+ struct ieee80211_ops {
+       void (*tx)(struct ieee80211_hw *hw,
+@@ -4122,6 +4149,8 @@ struct ieee80211_ops {
+       int (*reset_tid_config)(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif,
+                               struct ieee80211_sta *sta, u8 tids);
++      void (*update_vif_offload)(struct ieee80211_hw *hw,
++                                 struct ieee80211_vif *vif);
+ };
+ /**
+--- a/net/mac80211/debugfs.c
++++ b/net/mac80211/debugfs.c
+@@ -408,6 +408,7 @@ static const char *hw_flag_names[] = {
+       FLAG(SUPPORTS_MULTI_BSSID),
+       FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
+       FLAG(AMPDU_KEYBORDER_SUPPORT),
++      FLAG(SUPPORTS_TX_ENCAP_OFFLOAD),
+ #undef FLAG
+ };
+--- a/net/mac80211/driver-ops.h
++++ b/net/mac80211/driver-ops.h
+@@ -1385,4 +1385,19 @@ static inline int drv_reset_tid_config(s
+       return ret;
+ }
++
++static inline void drv_update_vif_offload(struct ieee80211_local *local,
++                                        struct ieee80211_sub_if_data *sdata)
++{
++      might_sleep();
++      check_sdata_in_driver(sdata);
++
++      if (!local->ops->update_vif_offload)
++              return;
++
++      trace_drv_update_vif_offload(local, sdata);
++      local->ops->update_vif_offload(&local->hw, &sdata->vif);
++      trace_drv_return_void(local);
++}
++
+ #endif /* __MAC80211_DRIVER_OPS */
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -990,8 +990,6 @@ struct ieee80211_sub_if_data {
+       } debugfs;
+ #endif
+-      bool hw_80211_encap;
+-
+       /* must be last, dynamically sized area in this! */
+       struct ieee80211_vif vif;
+ };
+@@ -1769,6 +1767,7 @@ void ieee80211_del_virtual_monitor(struc
+ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
+ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata,
+                             bool update_bss);
++void ieee80211_recalc_offload(struct ieee80211_local *local);
+ static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
+ {
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -43,6 +43,7 @@
+  */
+ static void ieee80211_iface_work(struct work_struct *work);
++static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata);
+ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
+ {
+@@ -348,6 +349,85 @@ static int ieee80211_check_queues(struct
+       return 0;
+ }
++static bool ieee80211_iftype_supports_encap_offload(enum nl80211_iftype iftype)
++{
++      switch (iftype) {
++      /* P2P GO and client are mapped to AP/STATION types */
++      case NL80211_IFTYPE_AP:
++      case NL80211_IFTYPE_STATION:
++              return true;
++      default:
++              return false;
++      }
++}
++
++static bool ieee80211_set_sdata_offload_flags(struct ieee80211_sub_if_data *sdata)
++{
++      struct ieee80211_local *local = sdata->local;
++      u32 flags;
++
++      flags = sdata->vif.offload_flags;
++
++      if (ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) &&
++          ieee80211_iftype_supports_encap_offload(sdata->vif.type)) {
++              flags |= IEEE80211_OFFLOAD_ENCAP_ENABLED;
++
++              if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) &&
++                  local->hw.wiphy->frag_threshold != (u32)-1)
++                      flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
++
++              if (local->monitors)
++                      flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
++      } else {
++              flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
++      }
++
++      if (sdata->vif.offload_flags == flags)
++              return false;
++
++      sdata->vif.offload_flags = flags;
++      return true;
++}
++
++
++static void ieee80211_recalc_sdata_offload(struct ieee80211_sub_if_data *sdata)
++{
++      struct ieee80211_local *local = sdata->local;
++      struct ieee80211_sub_if_data *vsdata;
++
++      if (ieee80211_set_sdata_offload_flags(sdata)) {
++              drv_update_vif_offload(local, sdata);
++              ieee80211_set_vif_encap_ops(sdata);
++      }
++
++      list_for_each_entry(vsdata, &local->interfaces, list) {
++              if (vsdata->vif.type != NL80211_IFTYPE_AP_VLAN ||
++                  vsdata->bss != &sdata->u.ap)
++                      continue;
++
++              ieee80211_set_vif_encap_ops(vsdata);
++      }
++}
++
++void ieee80211_recalc_offload(struct ieee80211_local *local)
++{
++      struct ieee80211_sub_if_data *sdata;
++
++      if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD))
++              return;
++
++      mutex_lock(&local->iflist_mtx);
++
++      list_for_each_entry(sdata, &local->interfaces, list) {
++              if (!ieee80211_sdata_running(sdata))
++                      continue;
++
++              ieee80211_recalc_sdata_offload(sdata);
++      }
++
++      mutex_unlock(&local->iflist_mtx);
++}
++
+ void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
+                                   const int offset)
+ {
+@@ -587,6 +667,7 @@ int ieee80211_do_open(struct wireless_de
+               if (rtnl_dereference(sdata->bss->beacon)) {
+                       ieee80211_vif_vlan_copy_chanctx(sdata);
+                       netif_carrier_on(dev);
++                      ieee80211_set_vif_encap_ops(sdata);
+               } else {
+                       netif_carrier_off(dev);
+               }
+@@ -616,6 +697,7 @@ int ieee80211_do_open(struct wireless_de
+               ieee80211_adjust_monitor_flags(sdata, 1);
+               ieee80211_configure_filter(local);
++              ieee80211_recalc_offload(local);
+               mutex_lock(&local->mtx);
+               ieee80211_recalc_idle(local);
+               mutex_unlock(&local->mtx);
+@@ -625,10 +707,13 @@ int ieee80211_do_open(struct wireless_de
+       default:
+               if (coming_up) {
+                       ieee80211_del_virtual_monitor(local);
++                      ieee80211_set_sdata_offload_flags(sdata);
+                       res = drv_add_interface(local, sdata);
+                       if (res)
+                               goto err_stop;
++
++                      ieee80211_set_vif_encap_ops(sdata);
+                       res = ieee80211_check_queues(sdata,
+                               ieee80211_vif_type_p2p(&sdata->vif));
+                       if (res)
+@@ -1286,61 +1371,6 @@ static const struct net_device_ops ieee8
+ };
+-static void __ieee80211_set_hw_80211_encap(struct ieee80211_sub_if_data *sdata,
+-                                         bool enable)
+-{
+-      sdata->dev->netdev_ops = enable ? &ieee80211_dataif_8023_ops :
+-                                        &ieee80211_dataif_ops;
+-      sdata->hw_80211_encap = enable;
+-}
+-
+-bool ieee80211_set_hw_80211_encap(struct ieee80211_vif *vif, bool enable)
+-{
+-      struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+-      struct ieee80211_local *local = sdata->local;
+-      struct ieee80211_sub_if_data *iter;
+-      struct ieee80211_key *key;
+-
+-      mutex_lock(&local->iflist_mtx);
+-      list_for_each_entry(iter, &local->interfaces, list) {
+-              struct ieee80211_sub_if_data *disable = NULL;
+-
+-              if (vif->type == NL80211_IFTYPE_MONITOR) {
+-                      disable = iter;
+-                      __ieee80211_set_hw_80211_encap(iter, false);
+-              } else if (iter->vif.type == NL80211_IFTYPE_MONITOR) {
+-                      disable = sdata;
+-                      enable = false;
+-              }
+-              if (disable)
+-                      sdata_dbg(disable,
+-                                "disable hw 80211 encap due to mon co-exist\n");
+-      }
+-      mutex_unlock(&local->iflist_mtx);
+-
+-      if (enable == sdata->hw_80211_encap)
+-              return enable;
+-
+-      if (!sdata->dev)
+-              return false;
+-
+-      if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) &&
+-          (local->hw.wiphy->frag_threshold != (u32)-1))
+-              enable = false;
+-
+-      mutex_lock(&sdata->local->key_mtx);
+-      list_for_each_entry(key, &sdata->key_list, list) {
+-              if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
+-                      enable = false;
+-      }
+-      mutex_unlock(&sdata->local->key_mtx);
+-
+-      __ieee80211_set_hw_80211_encap(sdata, enable);
+-
+-      return enable;
+-}
+-EXPORT_SYMBOL(ieee80211_set_hw_80211_encap);
+-
+ static void ieee80211_if_free(struct net_device *dev)
+ {
+       free_percpu(netdev_tstats(dev));
+@@ -1371,6 +1401,32 @@ static void ieee80211_if_setup_no_queue(
+ #endif
+ }
++static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata)
++{
++      struct ieee80211_local *local = sdata->local;
++      struct ieee80211_sub_if_data *bss = sdata;
++      bool enabled;
++
++      if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
++              if (!sdata->bss)
++                      return;
++
++              bss = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
++      }
++
++      if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) ||
++          !ieee80211_iftype_supports_encap_offload(bss->vif.type))
++              return;
++
++      enabled = bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED;
++      if (sdata->wdev.use_4addr &&
++          !(bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_4ADDR))
++              enabled = false;
++
++      sdata->dev->netdev_ops = enabled ? &ieee80211_dataif_8023_ops :
++                                         &ieee80211_dataif_ops;
++}
++
+ static void ieee80211_iface_work(struct work_struct *work)
+ {
+       struct ieee80211_sub_if_data *sdata =
+@@ -1553,7 +1609,6 @@ static void ieee80211_setup_sdata(struct
+       sdata->vif.bss_conf.txpower = INT_MIN; /* unset */
+       sdata->noack_map = 0;
+-      sdata->hw_80211_encap = false;
+       /* only monitor/p2p-device differ */
+       if (sdata->dev) {
+@@ -1688,6 +1743,7 @@ static int ieee80211_runtime_change_ifty
+       ieee80211_teardown_sdata(sdata);
++      ieee80211_set_sdata_offload_flags(sdata);
+       ret = drv_change_interface(local, sdata, internal_type, p2p);
+       if (ret)
+               type = ieee80211_vif_type_p2p(&sdata->vif);
+@@ -1700,6 +1756,7 @@ static int ieee80211_runtime_change_ifty
+       ieee80211_check_queues(sdata, type);
+       ieee80211_setup_sdata(sdata, type);
++      ieee80211_set_vif_encap_ops(sdata);
+       err = ieee80211_do_open(&sdata->wdev, false);
+       WARN(err, "type change: do_open returned %d", err);
+--- a/net/mac80211/key.c
++++ b/net/mac80211/key.c
+@@ -177,13 +177,6 @@ static int ieee80211_key_enable_hw_accel
+               }
+       }
+-      /* TKIP countermeasures don't work in encap offload mode */
+-      if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP &&
+-          sdata->hw_80211_encap) {
+-              sdata_dbg(sdata, "TKIP is not allowed in hw 80211 encap mode\n");
+-              return -EINVAL;
+-      }
+-
+       ret = drv_set_key(key->local, SET_KEY, sdata,
+                         sta ? &sta->sta : NULL, &key->conf);
+@@ -219,14 +212,6 @@ static int ieee80211_key_enable_hw_accel
+       case WLAN_CIPHER_SUITE_CCMP_256:
+       case WLAN_CIPHER_SUITE_GCMP:
+       case WLAN_CIPHER_SUITE_GCMP_256:
+-              /* We cannot do software crypto of data frames with
+-               * encapsulation offload enabled. However for 802.11w to
+-               * function properly we need cmac/gmac keys.
+-               */
+-              if (sdata->hw_80211_encap)
+-                      return -EINVAL;
+-              /* Fall through */
+-
+       case WLAN_CIPHER_SUITE_AES_CMAC:
+       case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+       case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+--- a/net/mac80211/trace.h
++++ b/net/mac80211/trace.h
+@@ -2733,6 +2733,12 @@ TRACE_EVENT(drv_get_ftm_responder_stats,
+       )
+ );
++DEFINE_EVENT(local_sdata_addr_evt, drv_update_vif_offload,
++      TP_PROTO(struct ieee80211_local *local,
++               struct ieee80211_sub_if_data *sdata),
++      TP_ARGS(local, sdata)
++);
++
+ #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
+ #undef TRACE_INCLUDE_PATH
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -4181,11 +4181,10 @@ static bool ieee80211_tx_8023(struct iee
+ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
+                               struct net_device *dev, struct sta_info *sta,
+-                              struct sk_buff *skb)
++                              struct ieee80211_key *key, struct sk_buff *skb)
+ {
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_local *local = sdata->local;
+-      struct ieee80211_key *key;
+       struct tid_ampdu_tx *tid_tx;
+       u8 tid;
+@@ -4234,7 +4233,6 @@ static void ieee80211_8023_xmit(struct i
+       info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP;
+       info->control.vif = &sdata->vif;
+-      key = rcu_dereference(sta->ptk[sta->ptk_idx]);
+       if (key)
+               info->control.hw_key = &key->conf;
+@@ -4251,12 +4249,9 @@ netdev_tx_t ieee80211_subif_start_xmit_8
+ {
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ethhdr *ehdr = (struct ethhdr *)skb->data;
++      struct ieee80211_key *key;
+       struct sta_info *sta;
+-
+-      if (WARN_ON(!sdata->hw_80211_encap)) {
+-              kfree_skb(skb);
+-              return NETDEV_TX_OK;
+-      }
++      bool offload = true;
+       if (unlikely(skb->len < ETH_HLEN)) {
+               kfree_skb(skb);
+@@ -4265,15 +4260,26 @@ netdev_tx_t ieee80211_subif_start_xmit_8
+       rcu_read_lock();
+-      if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
++      if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
+               kfree_skb(skb);
+-      else if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded ||
+-                        !test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
+-                        sdata->control_port_protocol == ehdr->h_proto))
+-              ieee80211_subif_start_xmit(skb, dev);
++              goto out;
++      }
++
++      if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded ||
++          !test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
++              sdata->control_port_protocol == ehdr->h_proto))
++              offload = false;
++      else if ((key = rcu_dereference(sta->ptk[sta->ptk_idx])) &&
++               (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ||
++                key->conf.cipher == WLAN_CIPHER_SUITE_TKIP))
++              offload = false;
++
++      if (offload)
++              ieee80211_8023_xmit(sdata, dev, sta, key, skb);
+       else
+-              ieee80211_8023_xmit(sdata, dev, sta, skb);
++              ieee80211_subif_start_xmit(skb, dev);
++out:
+       rcu_read_unlock();
+       return NETDEV_TX_OK;
diff --git a/package/kernel/mac80211/patches/subsys/318-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch b/package/kernel/mac80211/patches/subsys/318-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch
deleted file mode 100644 (file)
index 85287a6..0000000
+++ /dev/null
@@ -1,227 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Mon, 17 Aug 2020 13:35:32 +0200
-Subject: [PATCH] mac80211: swap NEED_TXPROCESSING and HW_80211_ENCAP tx
- flags
-
-In order to unify the tx status path, the hw 802.11 encapsulation flag
-needs to survive the trip to the tx status call.
-Since we don't have any free bits in info->flags, we need to move one.
-IEEE80211_TX_INTFL_NEED_TXPROCESSING is only used internally in mac80211,
-and only before the call into the driver.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/wireless/ath/ath11k/dp_tx.c
-+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
-@@ -14,7 +14,7 @@ ath11k_dp_tx_get_encap_type(struct ath11
- {
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
--      if (tx_info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
-+      if (tx_info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)
-               return HAL_TCL_ENCAP_TYPE_ETHERNET;
-       return HAL_TCL_ENCAP_TYPE_NATIVE_WIFI;
-@@ -93,7 +93,7 @@ int ath11k_dp_tx(struct ath11k *ar, stru
-       if (test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
-               return -ESHUTDOWN;
--      if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) &&
-+      if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
-           !ieee80211_is_data(hdr->frame_control))
-               return -ENOTSUPP;
---- a/drivers/net/wireless/ath/ath11k/mac.c
-+++ b/drivers/net/wireless/ath/ath11k/mac.c
-@@ -3749,7 +3749,7 @@ static int ath11k_mac_mgmt_tx_wmi(struct
-               return -ENOSPC;
-       info = IEEE80211_SKB_CB(skb);
--      if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)) {
-+      if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) {
-               if ((ieee80211_is_action(hdr->frame_control) ||
-                    ieee80211_is_deauth(hdr->frame_control) ||
-                    ieee80211_is_disassoc(hdr->frame_control)) &&
-@@ -3876,7 +3876,7 @@ static void ath11k_mac_op_tx(struct ieee
-       bool is_prb_rsp;
-       int ret;
--      if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) {
-+      if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
-               skb_cb->flags |= ATH11K_SKB_HW_80211_ENCAP;
-       } else if (ieee80211_is_mgmt(hdr->frame_control)) {
-               is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control);
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -720,9 +720,8 @@ struct ieee80211_bss_conf {
-  * @IEEE80211_TX_INTFL_OFFCHAN_TX_OK: Internal to mac80211. Used to indicate
-  *    that a frame can be transmitted while the queues are stopped for
-  *    off-channel operation.
-- * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211,
-- *    used to indicate that a pending frame requires TX processing before
-- *    it can be sent out.
-+ * @IEEE80211_TX_CTL_HW_80211_ENCAP: This frame uses hardware encapsulation
-+ *    (header conversion)
-  * @IEEE80211_TX_INTFL_RETRIED: completely internal to mac80211,
-  *    used to indicate that a frame was already retried due to PS
-  * @IEEE80211_TX_INTFL_DONT_ENCRYPT: completely internal to mac80211,
-@@ -791,7 +790,7 @@ enum mac80211_tx_info_flags {
-       IEEE80211_TX_STAT_AMPDU_NO_BACK         = BIT(11),
-       IEEE80211_TX_CTL_RATE_CTRL_PROBE        = BIT(12),
-       IEEE80211_TX_INTFL_OFFCHAN_TX_OK        = BIT(13),
--      IEEE80211_TX_INTFL_NEED_TXPROCESSING    = BIT(14),
-+      IEEE80211_TX_CTL_HW_80211_ENCAP         = BIT(14),
-       IEEE80211_TX_INTFL_RETRIED              = BIT(15),
-       IEEE80211_TX_INTFL_DONT_ENCRYPT         = BIT(16),
-       IEEE80211_TX_CTL_NO_PS_BUFFER           = BIT(17),
-@@ -823,8 +822,9 @@ enum mac80211_tx_info_flags {
-  * @IEEE80211_TX_CTRL_AMSDU: This frame is an A-MSDU frame
-  * @IEEE80211_TX_CTRL_FAST_XMIT: This frame is going through the fast_xmit path
-  * @IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP: This frame skips mesh path lookup
-- * @IEEE80211_TX_CTRL_HW_80211_ENCAP: This frame uses hardware encapsulation
-- *    (header conversion)
-+ * @IEEE80211_TX_INTCFL_NEED_TXPROCESSING: completely internal to mac80211,
-+ *    used to indicate that a pending frame requires TX processing before
-+ *    it can be sent out.
-  *
-  * These flags are used in tx_info->control.flags.
-  */
-@@ -835,7 +835,7 @@ enum mac80211_tx_control_flags {
-       IEEE80211_TX_CTRL_AMSDU                 = BIT(3),
-       IEEE80211_TX_CTRL_FAST_XMIT             = BIT(4),
-       IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP     = BIT(5),
--      IEEE80211_TX_CTRL_HW_80211_ENCAP        = BIT(6),
-+      IEEE80211_TX_INTCFL_NEED_TXPROCESSING   = BIT(6),
- };
- /*
---- a/net/mac80211/mesh_hwmp.c
-+++ b/net/mac80211/mesh_hwmp.c
-@@ -212,7 +212,7 @@ static void prepare_frame_for_deferred_t
-       skb->priority = 7;
-       info->control.vif = &sdata->vif;
--      info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
-+      info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
-       ieee80211_set_qos_hdr(sdata, skb);
-       ieee80211_mps_set_frame_flags(sdata, NULL, hdr);
- }
-@@ -1163,7 +1163,7 @@ int mesh_nexthop_resolve(struct ieee8021
-       if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN)
-               skb_to_free = skb_dequeue(&mpath->frame_queue);
--      info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
-+      info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
-       ieee80211_set_qos_hdr(sdata, skb);
-       skb_queue_tail(&mpath->frame_queue, skb);
-       if (skb_to_free)
---- a/net/mac80211/mesh_ps.c
-+++ b/net/mac80211/mesh_ps.c
-@@ -432,7 +432,7 @@ static void mpsp_qos_null_append(struct
-       info = IEEE80211_SKB_CB(new_skb);
-       info->control.vif = &sdata->vif;
--      info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
-+      info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
-       __skb_queue_tail(frames, new_skb);
- }
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2896,7 +2896,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
-       fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY);
-       info = IEEE80211_SKB_CB(fwd_skb);
-       memset(info, 0, sizeof(*info));
--      info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
-+      info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
-       info->control.vif = &rx->sdata->vif;
-       info->control.jiffies = jiffies;
-       if (is_multicast_ether_addr(fwd_hdr->addr1)) {
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -66,8 +66,8 @@ static void ieee80211_handle_filtered_fr
-       info->control.jiffies = jiffies;
-       info->control.vif = &sta->sdata->vif;
--      info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING |
--                     IEEE80211_TX_INTFL_RETRANSMISSION;
-+      info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
-+      info->flags |= IEEE80211_TX_INTFL_RETRANSMISSION;
-       info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
-       sta->status_stats.filtered++;
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -530,7 +530,7 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
-               info->control.jiffies = jiffies;
-               info->control.vif = &tx->sdata->vif;
--              info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
-+              info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
-               info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
-               skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb);
-               spin_unlock(&sta->ps_lock);
-@@ -1132,7 +1132,7 @@ static bool ieee80211_tx_prep_agg(struct
-                                      tx->sta->sta.addr, tx->sta->sta.aid);
-                       }
-                       info->control.vif = &tx->sdata->vif;
--                      info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
-+                      info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
-                       info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
-                       __skb_queue_tail(&tid_tx->pending, skb);
-                       if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER)
-@@ -1177,7 +1177,7 @@ ieee80211_tx_prepare(struct ieee80211_su
-        * we are doing the needed processing, so remove the flag
-        * now.
-        */
--      info->flags &= ~IEEE80211_TX_INTFL_NEED_TXPROCESSING;
-+      info->control.flags &= ~IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
-       hdr = (struct ieee80211_hdr *) skb->data;
-@@ -1256,7 +1256,7 @@ static struct txq_info *ieee80211_get_tx
-           (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
-               return NULL;
--      if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) &&
-+      if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
-           unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
-               if ((!ieee80211_is_mgmt(hdr->frame_control) ||
-                    ieee80211_is_bufferable_mmpdu(hdr->frame_control) ||
-@@ -3640,7 +3640,7 @@ begin:
-       else
-               info->flags &= ~IEEE80211_TX_CTL_AMPDU;
--      if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
-+      if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)
-               goto encap_out;
-       if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
-@@ -4247,7 +4247,7 @@ static void ieee80211_8023_xmit(struct i
-               sdata = container_of(sdata->bss,
-                                    struct ieee80211_sub_if_data, u.ap);
--      info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP;
-+      info->flags |= IEEE80211_TX_CTL_HW_80211_ENCAP;
-       info->control.vif = &sdata->vif;
-       ieee80211_tx_8023(sdata, skb, skb->len, sta, false);
-@@ -4351,7 +4351,7 @@ static bool ieee80211_tx_pending_skb(str
-       sdata = vif_to_sdata(info->control.vif);
--      if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) {
-+      if (info->control.flags & IEEE80211_TX_INTCFL_NEED_TXPROCESSING) {
-               chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
-               if (unlikely(!chanctx_conf)) {
-                       dev_kfree_skb(skb);
-@@ -4359,7 +4359,7 @@ static bool ieee80211_tx_pending_skb(str
-               }
-               info->band = chanctx_conf->def.chan->band;
-               result = ieee80211_tx(sdata, NULL, skb, true, 0);
--      } else if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) {
-+      } else if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
-               if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
-                       dev_kfree_skb(skb);
-                       return true;
diff --git a/package/kernel/mac80211/patches/subsys/319-mac80211-reduce-duplication-in-tx-status-functions.patch b/package/kernel/mac80211/patches/subsys/319-mac80211-reduce-duplication-in-tx-status-functions.patch
new file mode 100644 (file)
index 0000000..8b664d6
--- /dev/null
@@ -0,0 +1,197 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Mon, 17 Aug 2020 13:16:59 +0200
+Subject: [PATCH] mac80211: reduce duplication in tx status functions
+
+Move redundant functionality from __ieee80211_tx_status into
+ieee80211_tx_status_ext. Preparation for unifying with the 802.3 tx status
+codepath.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -184,18 +184,6 @@ static void ieee80211_frame_acked(struct
+       struct ieee80211_mgmt *mgmt = (void *) skb->data;
+       struct ieee80211_local *local = sta->local;
+       struct ieee80211_sub_if_data *sdata = sta->sdata;
+-      struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
+-
+-      if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
+-              sta->status_stats.last_ack = jiffies;
+-              if (txinfo->status.is_valid_ack_signal) {
+-                      sta->status_stats.last_ack_signal =
+-                                       (s8)txinfo->status.ack_signal;
+-                      sta->status_stats.ack_signal_filled = true;
+-                      ewma_avg_signal_add(&sta->status_stats.avg_ack_signal,
+-                                          -txinfo->status.ack_signal);
+-              }
+-      }
+       if (ieee80211_is_data_qos(mgmt->frame_control)) {
+               struct ieee80211_hdr *hdr = (void *) skb->data;
+@@ -899,7 +887,8 @@ void ieee80211_tx_monitor(struct ieee802
+ }
+ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
+-                                struct ieee80211_tx_status *status)
++                                struct ieee80211_tx_status *status,
++                                int rates_idx, int retry_count)
+ {
+       struct sk_buff *skb = status->skb;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+@@ -908,8 +897,6 @@ static void __ieee80211_tx_status(struct
+       struct sta_info *sta;
+       __le16 fc;
+       struct ieee80211_supported_band *sband;
+-      int retry_count;
+-      int rates_idx;
+       bool send_to_cooked;
+       bool acked;
+       bool noack_success;
+@@ -918,8 +905,6 @@ static void __ieee80211_tx_status(struct
+       int tid = IEEE80211_NUM_TIDS;
+       u16 tx_time_est;
+-      rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
+-
+       sband = local->hw.wiphy->bands[info->band];
+       fc = hdr->frame_control;
+@@ -996,24 +981,14 @@ static void __ieee80211_tx_status(struct
+               if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
+                       ieee80211_handle_filtered_frame(local, sta, skb);
+                       return;
+-              } else {
++              } else if (ieee80211_is_data_present(fc)) {
+                       if (!acked && !noack_success)
+-                              sta->status_stats.retry_failed++;
+-                      sta->status_stats.retry_count += retry_count;
+-
+-                      if (ieee80211_is_data_present(fc)) {
+-                              if (!acked && !noack_success)
+-                                      sta->status_stats.msdu_failed[tid]++;
++                              sta->status_stats.msdu_failed[tid]++;
+-                              sta->status_stats.msdu_retries[tid] +=
+-                                      retry_count;
+-                      }
++                      sta->status_stats.msdu_retries[tid] +=
++                              retry_count;
+               }
+-              rate_control_tx_status(local, sband, status);
+-              if (ieee80211_vif_is_mesh(&sta->sdata->vif))
+-                      ieee80211s_update_metric(local, sta, status);
+-
+               if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && acked)
+                       ieee80211_frame_acked(sta, skb);
+@@ -1038,20 +1013,6 @@ static void __ieee80211_tx_status(struct
+                                                            true);
+                       ieee80211_info_set_tx_time_est(info, 0);
+               }
+-
+-              if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
+-                      if (acked) {
+-                              if (sta->status_stats.lost_packets)
+-                                      sta->status_stats.lost_packets = 0;
+-
+-                              /* Track when last TDLS packet was ACKed */
+-                              sta->status_stats.last_pkt_time = jiffies;
+-                      } else if (noack_success) {
+-                              /* nothing to do here, do not account as lost */
+-                      } else {
+-                              ieee80211_lost_packet(sta, info);
+-                      }
+-              }
+       }
+       /* SNMP counters
+@@ -1135,7 +1096,7 @@ void ieee80211_tx_status(struct ieee8021
+       if (sta)
+               status.sta = &sta->sta;
+-      __ieee80211_tx_status(hw, &status);
++      ieee80211_tx_status_ext(hw, &status);
+       rcu_read_unlock();
+ }
+ EXPORT_SYMBOL(ieee80211_tx_status);
+@@ -1148,7 +1109,7 @@ void ieee80211_tx_status_ext(struct ieee
+       struct ieee80211_sta *pubsta = status->sta;
+       struct ieee80211_supported_band *sband;
+       struct sta_info *sta;
+-      int retry_count;
++      int rates_idx, retry_count;
+       bool acked, noack_success;
+       if (pubsta) {
+@@ -1158,13 +1119,7 @@ void ieee80211_tx_status_ext(struct ieee
+                       sta->tx_stats.last_rate_info = *status->rate;
+       }
+-      if (status->skb)
+-              return __ieee80211_tx_status(hw, status);
+-
+-      if (!status->sta)
+-              return;
+-
+-      ieee80211_tx_get_rates(hw, info, &retry_count);
++      rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
+       sband = hw->wiphy->bands[info->band];
+@@ -1176,20 +1131,30 @@ void ieee80211_tx_status_ext(struct ieee
+                       sta->status_stats.retry_failed++;
+               sta->status_stats.retry_count += retry_count;
+-              if (acked) {
+-                      sta->status_stats.last_ack = jiffies;
++              if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
++                      if (acked) {
++                              sta->status_stats.last_ack = jiffies;
+-                      if (sta->status_stats.lost_packets)
+-                              sta->status_stats.lost_packets = 0;
++                              if (sta->status_stats.lost_packets)
++                                      sta->status_stats.lost_packets = 0;
+-                      /* Track when last packet was ACKed */
+-                      sta->status_stats.last_pkt_time = jiffies;
+-              } else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
+-                      return;
+-              } else if (noack_success) {
+-                      /* nothing to do here, do not account as lost */
+-              } else {
+-                      ieee80211_lost_packet(sta, info);
++                              /* Track when last packet was ACKed */
++                              sta->status_stats.last_pkt_time = jiffies;
++
++                              if (info->status.is_valid_ack_signal) {
++                                      sta->status_stats.last_ack_signal =
++                                                       (s8)info->status.ack_signal;
++                                      sta->status_stats.ack_signal_filled = true;
++                                      ewma_avg_signal_add(&sta->status_stats.avg_ack_signal,
++                                                          -info->status.ack_signal);
++                              }
++                      } else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
++                              return;
++                      } else if (noack_success) {
++                              /* nothing to do here, do not account as lost */
++                      } else {
++                              ieee80211_lost_packet(sta, info);
++                      }
+               }
+               rate_control_tx_status(local, sband, status);
+@@ -1197,6 +1162,10 @@ void ieee80211_tx_status_ext(struct ieee
+                       ieee80211s_update_metric(local, sta, status);
+       }
++      if (status->skb)
++              return __ieee80211_tx_status(hw, status, rates_idx,
++                                           retry_count);
++
+       if (acked || noack_success) {
+               I802_DEBUG_INC(local->dot11TransmittedFrameCount);
+               if (!pubsta)
diff --git a/package/kernel/mac80211/patches/subsys/319-mac80211-unify-802.3-offload-and-802.11-tx-status-co.patch b/package/kernel/mac80211/patches/subsys/319-mac80211-unify-802.3-offload-and-802.11-tx-status-co.patch
deleted file mode 100644 (file)
index 7bb54f4..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Mon, 17 Aug 2020 13:54:19 +0200
-Subject: [PATCH] mac80211: unify 802.3 (offload) and 802.11 tx status
- codepath
-
-Make ieee80211_tx_status_8023 call ieee80211_tx_status_ext, similar to
-ieee80211_tx_status.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -903,7 +903,6 @@ static void __ieee80211_tx_status(struct
-       struct ieee80211_bar *bar;
-       int shift = 0;
-       int tid = IEEE80211_NUM_TIDS;
--      u16 tx_time_est;
-       sband = local->hw.wiphy->bands[info->band];
-       fc = hdr->frame_control;
-@@ -996,17 +995,6 @@ static void __ieee80211_tx_status(struct
-                   ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
-                       ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data,
-                                               acked, info->status.tx_time);
--
--              if ((tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) {
--                      /* Do this here to avoid the expensive lookup of the sta
--                       * in ieee80211_report_used_skb().
--                       */
--                      ieee80211_sta_update_pending_airtime(local, sta,
--                                                           skb_get_queue_mapping(skb),
--                                                           tx_time_est,
--                                                           true);
--                      ieee80211_info_set_tx_time_est(info, 0);
--              }
-       }
-       /* SNMP counters
-@@ -1102,9 +1090,11 @@ void ieee80211_tx_status_ext(struct ieee
-       struct ieee80211_tx_info *info = status->info;
-       struct ieee80211_sta *pubsta = status->sta;
-       struct ieee80211_supported_band *sband;
--      struct sta_info *sta;
-+      struct sk_buff *skb = status->skb;
-+      struct sta_info *sta = NULL;
-       int rates_idx, retry_count;
-       bool acked, noack_success;
-+      u16 tx_time_est;
-       if (pubsta) {
-               sta = container_of(pubsta, struct sta_info, sta);
-@@ -1156,7 +1146,18 @@ void ieee80211_tx_status_ext(struct ieee
-                       ieee80211s_update_metric(local, sta, status);
-       }
--      if (status->skb)
-+      if (skb && (tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) {
-+              /* Do this here to avoid the expensive lookup of the sta
-+               * in ieee80211_report_used_skb().
-+               */
-+              ieee80211_sta_update_pending_airtime(local, sta,
-+                                                   skb_get_queue_mapping(skb),
-+                                                   tx_time_est,
-+                                                   true);
-+              ieee80211_info_set_tx_time_est(info, 0);
-+      }
-+
-+      if (skb && !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP))
-               return __ieee80211_tx_status(hw, status, rates_idx,
-                                            retry_count);
-@@ -1171,6 +1172,12 @@ void ieee80211_tx_status_ext(struct ieee
-       } else {
-               I802_DEBUG_INC(local->dot11FailedCount);
-       }
-+
-+      if (!skb)
-+              return;
-+
-+      ieee80211_report_used_skb(local, skb, false);
-+      dev_kfree_skb(skb);
- }
- EXPORT_SYMBOL(ieee80211_tx_status_ext);
-@@ -1197,66 +1204,23 @@ void ieee80211_tx_status_8023(struct iee
-                             struct ieee80211_vif *vif,
-                             struct sk_buff *skb)
- {
--      struct ieee80211_local *local = hw_to_local(hw);
-       struct ieee80211_sub_if_data *sdata;
--      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-+      struct ieee80211_tx_status status = {
-+              .skb = skb,
-+              .info = IEEE80211_SKB_CB(skb),
-+      };
-       struct sta_info *sta;
--      int retry_count;
--      int rates_idx;
--      bool acked;
-       sdata = vif_to_sdata(vif);
--      acked = info->flags & IEEE80211_TX_STAT_ACK;
--      rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
--
-       rcu_read_lock();
--      if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
--              goto counters_update;
--
--      if (IS_ERR(sta))
--              goto counters_update;
--
--      if (!acked)
--              sta->status_stats.retry_failed++;
--
--      if (rates_idx != -1)
--              sta->tx_stats.last_rate = info->status.rates[rates_idx];
--
--      sta->status_stats.retry_count += retry_count;
--
--      if (ieee80211_hw_check(hw, REPORTS_TX_ACK_STATUS)) {
--              sta->status_stats.last_ack = jiffies;
--              if (info->flags & IEEE80211_TX_STAT_ACK) {
--                      if (sta->status_stats.lost_packets)
--                              sta->status_stats.lost_packets = 0;
-+      if (!ieee80211_lookup_ra_sta(sdata, skb, &sta) && !IS_ERR(sta))
-+              status.sta = &sta->sta;
--                      sta->status_stats.last_pkt_time = jiffies;
--              } else {
--                      ieee80211_lost_packet(sta, info);
--              }
--      }
-+      ieee80211_tx_status_ext(hw, &status);
--counters_update:
-       rcu_read_unlock();
--      ieee80211_led_tx(local);
--
--      if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
--          !(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED))
--              goto skip_stats_update;
--
--      I802_DEBUG_INC(local->dot11TransmittedFrameCount);
--      if (is_multicast_ether_addr(skb->data))
--              I802_DEBUG_INC(local->dot11MulticastTransmittedFrameCount);
--      if (retry_count > 0)
--              I802_DEBUG_INC(local->dot11RetryCount);
--      if (retry_count > 1)
--              I802_DEBUG_INC(local->dot11MultipleRetryCount);
--
--skip_stats_update:
--      ieee80211_report_used_skb(local, skb, false);
--      dev_kfree_skb(skb);
- }
- EXPORT_SYMBOL(ieee80211_tx_status_8023);
diff --git a/package/kernel/mac80211/patches/subsys/320-mac80211-add-missing-queue-hash-initialization-to-80.patch b/package/kernel/mac80211/patches/subsys/320-mac80211-add-missing-queue-hash-initialization-to-80.patch
deleted file mode 100644 (file)
index d9d3fde..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Mon, 17 Aug 2020 13:55:56 +0200
-Subject: [PATCH] mac80211: add missing queue/hash initialization to 802.3
- xmit
-
-Fixes AQL for encap-offloaded tx
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -4200,6 +4200,12 @@ static void ieee80211_8023_xmit(struct i
-       if (is_zero_ether_addr(ra))
-               goto out_free;
-+      if (local->ops->wake_tx_queue) {
-+              u16 queue = __ieee80211_select_queue(sdata, sta, skb);
-+              skb_set_queue_mapping(skb, queue);
-+              skb_get_hash(skb);
-+      }
-+
-       multicast = is_multicast_ether_addr(ra);
-       if (sta)
diff --git a/package/kernel/mac80211/patches/subsys/320-mac80211-remove-tx-status-call-to-ieee80211_sta_regi.patch b/package/kernel/mac80211/patches/subsys/320-mac80211-remove-tx-status-call-to-ieee80211_sta_regi.patch
new file mode 100644 (file)
index 0000000..168d645
--- /dev/null
@@ -0,0 +1,26 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Mon, 17 Aug 2020 13:29:12 +0200
+Subject: [PATCH] mac80211: remove tx status call to
+ ieee80211_sta_register_airtime
+
+All drivers using airtime fairness are calling ieee80211_sta_register_airtime
+directly
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -997,12 +997,6 @@ static void __ieee80211_tx_status(struct
+                       ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data,
+                                               acked, info->status.tx_time);
+-              if (info->status.tx_time &&
+-                  wiphy_ext_feature_isset(local->hw.wiphy,
+-                                          NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
+-                      ieee80211_sta_register_airtime(&sta->sta, tid,
+-                                                     info->status.tx_time, 0);
+-
+               if ((tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) {
+                       /* Do this here to avoid the expensive lookup of the sta
+                        * in ieee80211_report_used_skb().
diff --git a/package/kernel/mac80211/patches/subsys/321-mac80211-check-and-refresh-aggregation-session-in-en.patch b/package/kernel/mac80211/patches/subsys/321-mac80211-check-and-refresh-aggregation-session-in-en.patch
deleted file mode 100644 (file)
index 0188e19..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Mon, 17 Aug 2020 21:11:25 +0200
-Subject: [PATCH] mac80211: check and refresh aggregation session in encap
- offload tx
-
-Update the last_tx timestamp to avoid tearing down the aggregation session
-early. Fall back to the slow path if the session setup is still running
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -4189,6 +4189,8 @@ static void ieee80211_8023_xmit(struct i
-       bool authorized = false;
-       bool multicast;
-       unsigned char *ra = ehdr->h_dest;
-+      struct tid_ampdu_tx *tid_tx;
-+      u8 tid;
-       if (IS_ERR(sta) || (sta && !sta->uploaded))
-               sta = NULL;
-@@ -4226,6 +4228,22 @@ static void ieee80211_8023_xmit(struct i
-       memset(info, 0, sizeof(*info));
-+      if (sta) {
-+              tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
-+              tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
-+              if (tid_tx) {
-+                      if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
-+                              /* fall back to non-offload slow path */
-+                              __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL);
-+                              return;
-+                      }
-+
-+                      info->flags |= IEEE80211_TX_CTL_AMPDU;
-+                      if (tid_tx->timeout)
-+                              tid_tx->last_tx = jiffies;
-+              }
-+      }
-+
-       if (unlikely(!multicast && skb->sk &&
-                    skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS))
-               info->ack_frame_id = ieee80211_store_ack_skb(local, skb,
diff --git a/package/kernel/mac80211/patches/subsys/321-mac80211-optimize-station-connection-monitor.patch b/package/kernel/mac80211/patches/subsys/321-mac80211-optimize-station-connection-monitor.patch
new file mode 100644 (file)
index 0000000..ed9efb2
--- /dev/null
@@ -0,0 +1,174 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Mon, 17 Aug 2020 13:29:56 +0200
+Subject: [PATCH] mac80211: optimize station connection monitor
+
+Calling mod_timer for every rx/tx packet can be quite expensive.
+Instead of constantly updating the timer, we can simply let it run out
+and check the timestamp of the last ACK or rx packet to re-arm it.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -2045,8 +2045,6 @@ void ieee80211_dynamic_ps_timer(struct t
+ void ieee80211_send_nullfunc(struct ieee80211_local *local,
+                            struct ieee80211_sub_if_data *sdata,
+                            bool powersave);
+-void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
+-                           struct ieee80211_hdr *hdr);
+ void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
+                            struct ieee80211_hdr *hdr, bool ack, u16 tx_time);
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -2432,23 +2432,6 @@ static void ieee80211_set_disassoc(struc
+       sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
+ }
+-void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
+-                           struct ieee80211_hdr *hdr)
+-{
+-      /*
+-       * We can postpone the mgd.timer whenever receiving unicast frames
+-       * from AP because we know that the connection is working both ways
+-       * at that time. But multicast frames (and hence also beacons) must
+-       * be ignored here, because we need to trigger the timer during
+-       * data idle periods for sending the periodic probe request to the
+-       * AP we're connected to.
+-       */
+-      if (is_multicast_ether_addr(hdr->addr1))
+-              return;
+-
+-      ieee80211_sta_reset_conn_monitor(sdata);
+-}
+-
+ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
+ {
+       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+@@ -2521,21 +2504,13 @@ void ieee80211_sta_tx_notify(struct ieee
+ {
+       ieee80211_sta_tx_wmm_ac_notify(sdata, hdr, tx_time);
+-      if (!ieee80211_is_data(hdr->frame_control))
+-          return;
+-
+-      if (ieee80211_is_any_nullfunc(hdr->frame_control) &&
+-          sdata->u.mgd.probe_send_count > 0) {
+-              if (ack)
+-                      ieee80211_sta_reset_conn_monitor(sdata);
+-              else
+-                      sdata->u.mgd.nullfunc_failed = true;
+-              ieee80211_queue_work(&sdata->local->hw, &sdata->work);
++      if (!ieee80211_is_any_nullfunc(hdr->frame_control) ||
++          !sdata->u.mgd.probe_send_count)
+               return;
+-      }
+-      if (ack)
+-              ieee80211_sta_reset_conn_monitor(sdata);
++      if (!ack)
++              sdata->u.mgd.nullfunc_failed = true;
++      ieee80211_queue_work(&sdata->local->hw, &sdata->work);
+ }
+ static void ieee80211_mlme_send_probe_req(struct ieee80211_sub_if_data *sdata,
+@@ -3600,8 +3575,8 @@ static bool ieee80211_assoc_success(stru
+        * Start timer to probe the connection to the AP now.
+        * Also start the timer that will detect beacon loss.
+        */
+-      ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
+       ieee80211_sta_reset_beacon_monitor(sdata);
++      ieee80211_sta_reset_conn_monitor(sdata);
+       ret = true;
+  out:
+@@ -4569,10 +4544,26 @@ static void ieee80211_sta_conn_mon_timer
+               from_timer(sdata, t, u.mgd.conn_mon_timer);
+       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+       struct ieee80211_local *local = sdata->local;
++      struct sta_info *sta;
++      unsigned long timeout;
+       if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn)
+               return;
++      sta = sta_info_get(sdata, ifmgd->bssid);
++      if (!sta)
++              return;
++
++      timeout = sta->status_stats.last_ack;
++      if (time_before(sta->status_stats.last_ack, sta->rx_stats.last_rx))
++              timeout = sta->rx_stats.last_rx;
++      timeout += IEEE80211_CONNECTION_IDLE_TIME;
++
++      if (time_is_before_jiffies(timeout)) {
++              mod_timer(&ifmgd->conn_mon_timer, round_jiffies_up(timeout));
++              return;
++      }
++
+       ieee80211_queue_work(&local->hw, &ifmgd->monitor_work);
+ }
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -1811,9 +1811,6 @@ ieee80211_rx_h_sta_process(struct ieee80
+                       sta->rx_stats.last_rate = sta_stats_encode_rate(status);
+       }
+-      if (rx->sdata->vif.type == NL80211_IFTYPE_STATION)
+-              ieee80211_sta_rx_notify(rx->sdata, hdr);
+-
+       sta->rx_stats.fragments++;
+       u64_stats_update_begin(&rx->sta->rx_stats.syncp);
+@@ -4148,7 +4145,6 @@ void ieee80211_check_fast_rx(struct sta_
+                       fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr2);
+                       fastrx.expected_ds_bits = 0;
+               } else {
+-                      fastrx.sta_notify = sdata->u.mgd.probe_send_count > 0;
+                       fastrx.da_offs = offsetof(struct ieee80211_hdr, addr1);
+                       fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr3);
+                       fastrx.expected_ds_bits =
+@@ -4378,11 +4374,6 @@ static bool ieee80211_invoke_fast_rx(str
+           pskb_trim(skb, skb->len - fast_rx->icv_len))
+               goto drop;
+-      if (unlikely(fast_rx->sta_notify)) {
+-              ieee80211_sta_rx_notify(rx->sdata, hdr);
+-              fast_rx->sta_notify = false;
+-      }
+-
+       /* statistics part of ieee80211_rx_h_sta_process() */
+       if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
+               stats->last_signal = status->signal;
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -336,7 +336,6 @@ struct ieee80211_fast_tx {
+  * @expected_ds_bits: from/to DS bits expected
+  * @icv_len: length of the MIC if present
+  * @key: bool indicating encryption is expected (key is set)
+- * @sta_notify: notify the MLME code (once)
+  * @internal_forward: forward froms internally on AP/VLAN type interfaces
+  * @uses_rss: copy of USES_RSS hw flag
+  * @da_offs: offset of the DA in the header (for header conversion)
+@@ -352,7 +351,6 @@ struct ieee80211_fast_rx {
+       __le16 expected_ds_bits;
+       u8 icv_len;
+       u8 key:1,
+-         sta_notify:1,
+          internal_forward:1,
+          uses_rss:1;
+       u8 da_offs, sa_offs;
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -1227,9 +1227,6 @@ void ieee80211_tx_status_8023(struct iee
+       sta->status_stats.retry_count += retry_count;
+       if (ieee80211_hw_check(hw, REPORTS_TX_ACK_STATUS)) {
+-              if (acked && vif->type == NL80211_IFTYPE_STATION)
+-                      ieee80211_sta_reset_conn_monitor(sdata);
+-
+               sta->status_stats.last_ack = jiffies;
+               if (info->flags & IEEE80211_TX_STAT_ACK) {
+                       if (sta->status_stats.lost_packets)
diff --git a/package/kernel/mac80211/patches/subsys/322-mac80211-support-using-ieee80211_tx_status_ext-to-fr.patch b/package/kernel/mac80211/patches/subsys/322-mac80211-support-using-ieee80211_tx_status_ext-to-fr.patch
deleted file mode 100644 (file)
index 5469a41..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Thu, 20 Aug 2020 17:27:00 +0200
-Subject: [PATCH] mac80211: support using ieee80211_tx_status_ext to free
- skbs without status info
-
-For encap-offloaded packets, ieee80211_free_txskb cannot be used, since it
-does not have the vif pointer.
-Using ieee80211_tx_status_ext for this purpose has the advantage of being able
-avoid an extra station lookup for AQL
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -1103,6 +1103,21 @@ void ieee80211_tx_status_ext(struct ieee
-                       sta->tx_stats.last_rate_info = *status->rate;
-       }
-+      if (skb && (tx_time_est =
-+                  ieee80211_info_get_tx_time_est(IEEE80211_SKB_CB(skb))) > 0) {
-+              /* Do this here to avoid the expensive lookup of the sta
-+               * in ieee80211_report_used_skb().
-+               */
-+              ieee80211_sta_update_pending_airtime(local, sta,
-+                                                   skb_get_queue_mapping(skb),
-+                                                   tx_time_est,
-+                                                   true);
-+              ieee80211_info_set_tx_time_est(IEEE80211_SKB_CB(skb), 0);
-+      }
-+
-+      if (!status->info)
-+              goto free;
-+
-       rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
-       sband = hw->wiphy->bands[info->band];
-@@ -1146,17 +1161,6 @@ void ieee80211_tx_status_ext(struct ieee
-                       ieee80211s_update_metric(local, sta, status);
-       }
--      if (skb && (tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) {
--              /* Do this here to avoid the expensive lookup of the sta
--               * in ieee80211_report_used_skb().
--               */
--              ieee80211_sta_update_pending_airtime(local, sta,
--                                                   skb_get_queue_mapping(skb),
--                                                   tx_time_est,
--                                                   true);
--              ieee80211_info_set_tx_time_est(info, 0);
--      }
--
-       if (skb && !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP))
-               return __ieee80211_tx_status(hw, status, rates_idx,
-                                            retry_count);
-@@ -1173,6 +1177,7 @@ void ieee80211_tx_status_ext(struct ieee
-               I802_DEBUG_INC(local->dot11FailedCount);
-       }
-+free:
-       if (!skb)
-               return;
diff --git a/package/kernel/mac80211/patches/subsys/322-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch b/package/kernel/mac80211/patches/subsys/322-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch
new file mode 100644 (file)
index 0000000..b9069ef
--- /dev/null
@@ -0,0 +1,227 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Mon, 17 Aug 2020 13:35:32 +0200
+Subject: [PATCH] mac80211: swap NEED_TXPROCESSING and HW_80211_ENCAP tx
+ flags
+
+In order to unify the tx status path, the hw 802.11 encapsulation flag
+needs to survive the trip to the tx status call.
+Since we don't have any free bits in info->flags, we need to move one.
+IEEE80211_TX_INTFL_NEED_TXPROCESSING is only used internally in mac80211,
+and only before the call into the driver.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
++++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
+@@ -14,7 +14,7 @@ ath11k_dp_tx_get_encap_type(struct ath11
+ {
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+-      if (tx_info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
++      if (tx_info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)
+               return HAL_TCL_ENCAP_TYPE_ETHERNET;
+       return HAL_TCL_ENCAP_TYPE_NATIVE_WIFI;
+@@ -93,7 +93,7 @@ int ath11k_dp_tx(struct ath11k *ar, stru
+       if (test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
+               return -ESHUTDOWN;
+-      if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) &&
++      if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
+           !ieee80211_is_data(hdr->frame_control))
+               return -ENOTSUPP;
+--- a/drivers/net/wireless/ath/ath11k/mac.c
++++ b/drivers/net/wireless/ath/ath11k/mac.c
+@@ -3749,7 +3749,7 @@ static int ath11k_mac_mgmt_tx_wmi(struct
+               return -ENOSPC;
+       info = IEEE80211_SKB_CB(skb);
+-      if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)) {
++      if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) {
+               if ((ieee80211_is_action(hdr->frame_control) ||
+                    ieee80211_is_deauth(hdr->frame_control) ||
+                    ieee80211_is_disassoc(hdr->frame_control)) &&
+@@ -3876,7 +3876,7 @@ static void ath11k_mac_op_tx(struct ieee
+       bool is_prb_rsp;
+       int ret;
+-      if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) {
++      if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
+               skb_cb->flags |= ATH11K_SKB_HW_80211_ENCAP;
+       } else if (ieee80211_is_mgmt(hdr->frame_control)) {
+               is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control);
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -720,9 +720,8 @@ struct ieee80211_bss_conf {
+  * @IEEE80211_TX_INTFL_OFFCHAN_TX_OK: Internal to mac80211. Used to indicate
+  *    that a frame can be transmitted while the queues are stopped for
+  *    off-channel operation.
+- * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211,
+- *    used to indicate that a pending frame requires TX processing before
+- *    it can be sent out.
++ * @IEEE80211_TX_CTL_HW_80211_ENCAP: This frame uses hardware encapsulation
++ *    (header conversion)
+  * @IEEE80211_TX_INTFL_RETRIED: completely internal to mac80211,
+  *    used to indicate that a frame was already retried due to PS
+  * @IEEE80211_TX_INTFL_DONT_ENCRYPT: completely internal to mac80211,
+@@ -791,7 +790,7 @@ enum mac80211_tx_info_flags {
+       IEEE80211_TX_STAT_AMPDU_NO_BACK         = BIT(11),
+       IEEE80211_TX_CTL_RATE_CTRL_PROBE        = BIT(12),
+       IEEE80211_TX_INTFL_OFFCHAN_TX_OK        = BIT(13),
+-      IEEE80211_TX_INTFL_NEED_TXPROCESSING    = BIT(14),
++      IEEE80211_TX_CTL_HW_80211_ENCAP         = BIT(14),
+       IEEE80211_TX_INTFL_RETRIED              = BIT(15),
+       IEEE80211_TX_INTFL_DONT_ENCRYPT         = BIT(16),
+       IEEE80211_TX_CTL_NO_PS_BUFFER           = BIT(17),
+@@ -823,8 +822,9 @@ enum mac80211_tx_info_flags {
+  * @IEEE80211_TX_CTRL_AMSDU: This frame is an A-MSDU frame
+  * @IEEE80211_TX_CTRL_FAST_XMIT: This frame is going through the fast_xmit path
+  * @IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP: This frame skips mesh path lookup
+- * @IEEE80211_TX_CTRL_HW_80211_ENCAP: This frame uses hardware encapsulation
+- *    (header conversion)
++ * @IEEE80211_TX_INTCFL_NEED_TXPROCESSING: completely internal to mac80211,
++ *    used to indicate that a pending frame requires TX processing before
++ *    it can be sent out.
+  *
+  * These flags are used in tx_info->control.flags.
+  */
+@@ -835,7 +835,7 @@ enum mac80211_tx_control_flags {
+       IEEE80211_TX_CTRL_AMSDU                 = BIT(3),
+       IEEE80211_TX_CTRL_FAST_XMIT             = BIT(4),
+       IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP     = BIT(5),
+-      IEEE80211_TX_CTRL_HW_80211_ENCAP        = BIT(6),
++      IEEE80211_TX_INTCFL_NEED_TXPROCESSING   = BIT(6),
+ };
+ /*
+--- a/net/mac80211/mesh_hwmp.c
++++ b/net/mac80211/mesh_hwmp.c
+@@ -212,7 +212,7 @@ static void prepare_frame_for_deferred_t
+       skb->priority = 7;
+       info->control.vif = &sdata->vif;
+-      info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
++      info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
+       ieee80211_set_qos_hdr(sdata, skb);
+       ieee80211_mps_set_frame_flags(sdata, NULL, hdr);
+ }
+@@ -1163,7 +1163,7 @@ int mesh_nexthop_resolve(struct ieee8021
+       if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN)
+               skb_to_free = skb_dequeue(&mpath->frame_queue);
+-      info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
++      info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
+       ieee80211_set_qos_hdr(sdata, skb);
+       skb_queue_tail(&mpath->frame_queue, skb);
+       if (skb_to_free)
+--- a/net/mac80211/mesh_ps.c
++++ b/net/mac80211/mesh_ps.c
+@@ -432,7 +432,7 @@ static void mpsp_qos_null_append(struct
+       info = IEEE80211_SKB_CB(new_skb);
+       info->control.vif = &sdata->vif;
+-      info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
++      info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
+       __skb_queue_tail(frames, new_skb);
+ }
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2896,7 +2896,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
+       fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY);
+       info = IEEE80211_SKB_CB(fwd_skb);
+       memset(info, 0, sizeof(*info));
+-      info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
++      info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
+       info->control.vif = &rx->sdata->vif;
+       info->control.jiffies = jiffies;
+       if (is_multicast_ether_addr(fwd_hdr->addr1)) {
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -66,8 +66,8 @@ static void ieee80211_handle_filtered_fr
+       info->control.jiffies = jiffies;
+       info->control.vif = &sta->sdata->vif;
+-      info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING |
+-                     IEEE80211_TX_INTFL_RETRANSMISSION;
++      info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
++      info->flags |= IEEE80211_TX_INTFL_RETRANSMISSION;
+       info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
+       sta->status_stats.filtered++;
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -530,7 +530,7 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
+               info->control.jiffies = jiffies;
+               info->control.vif = &tx->sdata->vif;
+-              info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
++              info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
+               info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
+               skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb);
+               spin_unlock(&sta->ps_lock);
+@@ -1132,7 +1132,7 @@ static bool ieee80211_tx_prep_agg(struct
+                                      tx->sta->sta.addr, tx->sta->sta.aid);
+                       }
+                       info->control.vif = &tx->sdata->vif;
+-                      info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
++                      info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
+                       info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
+                       __skb_queue_tail(&tid_tx->pending, skb);
+                       if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER)
+@@ -1177,7 +1177,7 @@ ieee80211_tx_prepare(struct ieee80211_su
+        * we are doing the needed processing, so remove the flag
+        * now.
+        */
+-      info->flags &= ~IEEE80211_TX_INTFL_NEED_TXPROCESSING;
++      info->control.flags &= ~IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
+       hdr = (struct ieee80211_hdr *) skb->data;
+@@ -1256,7 +1256,7 @@ static struct txq_info *ieee80211_get_tx
+           (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
+               return NULL;
+-      if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) &&
++      if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
+           unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
+               if ((!ieee80211_is_mgmt(hdr->frame_control) ||
+                    ieee80211_is_bufferable_mmpdu(hdr->frame_control) ||
+@@ -3640,7 +3640,7 @@ begin:
+       else
+               info->flags &= ~IEEE80211_TX_CTL_AMPDU;
+-      if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
++      if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)
+               goto encap_out;
+       if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
+@@ -4230,7 +4230,7 @@ static void ieee80211_8023_xmit(struct i
+               sdata = container_of(sdata->bss,
+                                    struct ieee80211_sub_if_data, u.ap);
+-      info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP;
++      info->flags |= IEEE80211_TX_CTL_HW_80211_ENCAP;
+       info->control.vif = &sdata->vif;
+       if (key)
+@@ -4355,7 +4355,7 @@ static bool ieee80211_tx_pending_skb(str
+       sdata = vif_to_sdata(info->control.vif);
+-      if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) {
++      if (info->control.flags & IEEE80211_TX_INTCFL_NEED_TXPROCESSING) {
+               chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+               if (unlikely(!chanctx_conf)) {
+                       dev_kfree_skb(skb);
+@@ -4363,7 +4363,7 @@ static bool ieee80211_tx_pending_skb(str
+               }
+               info->band = chanctx_conf->def.chan->band;
+               result = ieee80211_tx(sdata, NULL, skb, true, 0);
+-      } else if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) {
++      } else if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
+               if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
+                       dev_kfree_skb(skb);
+                       return true;
diff --git a/package/kernel/mac80211/patches/subsys/323-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch b/package/kernel/mac80211/patches/subsys/323-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch
deleted file mode 100644 (file)
index c0f2b7b..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 21 Aug 2020 05:49:07 +0200
-Subject: [PATCH] mac80211: extend ieee80211_tx_status_ext to support bulk
- free
-
-Store processed skbs ready to be freed in a list so the driver bulk free them
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -1092,12 +1092,14 @@ ieee80211_info_get_tx_time_est(struct ie
-  * @info: Basic tx status information
-  * @skb: Packet skb (can be NULL if not provided by the driver)
-  * @rate: The TX rate that was used when sending the packet
-+ * @free_list: list where processed skbs are stored to be free'd by the driver
-  */
- struct ieee80211_tx_status {
-       struct ieee80211_sta *sta;
-       struct ieee80211_tx_info *info;
-       struct sk_buff *skb;
-       struct rate_info *rate;
-+      struct list_head *free_list;
- };
- /**
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -1053,7 +1053,10 @@ static void __ieee80211_tx_status(struct
-        * with this test...
-        */
-       if (!local->monitors && (!send_to_cooked || !local->cooked_mntrs)) {
--              dev_kfree_skb(skb);
-+              if (status->free_list)
-+                      list_add_tail(&skb->list, status->free_list);
-+              else
-+                      dev_kfree_skb(skb);
-               return;
-       }
-@@ -1182,7 +1185,10 @@ free:
-               return;
-       ieee80211_report_used_skb(local, skb, false);
--      dev_kfree_skb(skb);
-+      if (status->free_list)
-+              list_add_tail(&skb->list, status->free_list);
-+      else
-+              dev_kfree_skb(skb);
- }
- EXPORT_SYMBOL(ieee80211_tx_status_ext);
diff --git a/package/kernel/mac80211/patches/subsys/323-mac80211-unify-802.3-offload-and-802.11-tx-status-co.patch b/package/kernel/mac80211/patches/subsys/323-mac80211-unify-802.3-offload-and-802.11-tx-status-co.patch
new file mode 100644 (file)
index 0000000..7bb54f4
--- /dev/null
@@ -0,0 +1,159 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Mon, 17 Aug 2020 13:54:19 +0200
+Subject: [PATCH] mac80211: unify 802.3 (offload) and 802.11 tx status
+ codepath
+
+Make ieee80211_tx_status_8023 call ieee80211_tx_status_ext, similar to
+ieee80211_tx_status.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -903,7 +903,6 @@ static void __ieee80211_tx_status(struct
+       struct ieee80211_bar *bar;
+       int shift = 0;
+       int tid = IEEE80211_NUM_TIDS;
+-      u16 tx_time_est;
+       sband = local->hw.wiphy->bands[info->band];
+       fc = hdr->frame_control;
+@@ -996,17 +995,6 @@ static void __ieee80211_tx_status(struct
+                   ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
+                       ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data,
+                                               acked, info->status.tx_time);
+-
+-              if ((tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) {
+-                      /* Do this here to avoid the expensive lookup of the sta
+-                       * in ieee80211_report_used_skb().
+-                       */
+-                      ieee80211_sta_update_pending_airtime(local, sta,
+-                                                           skb_get_queue_mapping(skb),
+-                                                           tx_time_est,
+-                                                           true);
+-                      ieee80211_info_set_tx_time_est(info, 0);
+-              }
+       }
+       /* SNMP counters
+@@ -1102,9 +1090,11 @@ void ieee80211_tx_status_ext(struct ieee
+       struct ieee80211_tx_info *info = status->info;
+       struct ieee80211_sta *pubsta = status->sta;
+       struct ieee80211_supported_band *sband;
+-      struct sta_info *sta;
++      struct sk_buff *skb = status->skb;
++      struct sta_info *sta = NULL;
+       int rates_idx, retry_count;
+       bool acked, noack_success;
++      u16 tx_time_est;
+       if (pubsta) {
+               sta = container_of(pubsta, struct sta_info, sta);
+@@ -1156,7 +1146,18 @@ void ieee80211_tx_status_ext(struct ieee
+                       ieee80211s_update_metric(local, sta, status);
+       }
+-      if (status->skb)
++      if (skb && (tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) {
++              /* Do this here to avoid the expensive lookup of the sta
++               * in ieee80211_report_used_skb().
++               */
++              ieee80211_sta_update_pending_airtime(local, sta,
++                                                   skb_get_queue_mapping(skb),
++                                                   tx_time_est,
++                                                   true);
++              ieee80211_info_set_tx_time_est(info, 0);
++      }
++
++      if (skb && !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP))
+               return __ieee80211_tx_status(hw, status, rates_idx,
+                                            retry_count);
+@@ -1171,6 +1172,12 @@ void ieee80211_tx_status_ext(struct ieee
+       } else {
+               I802_DEBUG_INC(local->dot11FailedCount);
+       }
++
++      if (!skb)
++              return;
++
++      ieee80211_report_used_skb(local, skb, false);
++      dev_kfree_skb(skb);
+ }
+ EXPORT_SYMBOL(ieee80211_tx_status_ext);
+@@ -1197,66 +1204,23 @@ void ieee80211_tx_status_8023(struct iee
+                             struct ieee80211_vif *vif,
+                             struct sk_buff *skb)
+ {
+-      struct ieee80211_local *local = hw_to_local(hw);
+       struct ieee80211_sub_if_data *sdata;
+-      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
++      struct ieee80211_tx_status status = {
++              .skb = skb,
++              .info = IEEE80211_SKB_CB(skb),
++      };
+       struct sta_info *sta;
+-      int retry_count;
+-      int rates_idx;
+-      bool acked;
+       sdata = vif_to_sdata(vif);
+-      acked = info->flags & IEEE80211_TX_STAT_ACK;
+-      rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
+-
+       rcu_read_lock();
+-      if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
+-              goto counters_update;
+-
+-      if (IS_ERR(sta))
+-              goto counters_update;
+-
+-      if (!acked)
+-              sta->status_stats.retry_failed++;
+-
+-      if (rates_idx != -1)
+-              sta->tx_stats.last_rate = info->status.rates[rates_idx];
+-
+-      sta->status_stats.retry_count += retry_count;
+-
+-      if (ieee80211_hw_check(hw, REPORTS_TX_ACK_STATUS)) {
+-              sta->status_stats.last_ack = jiffies;
+-              if (info->flags & IEEE80211_TX_STAT_ACK) {
+-                      if (sta->status_stats.lost_packets)
+-                              sta->status_stats.lost_packets = 0;
++      if (!ieee80211_lookup_ra_sta(sdata, skb, &sta) && !IS_ERR(sta))
++              status.sta = &sta->sta;
+-                      sta->status_stats.last_pkt_time = jiffies;
+-              } else {
+-                      ieee80211_lost_packet(sta, info);
+-              }
+-      }
++      ieee80211_tx_status_ext(hw, &status);
+-counters_update:
+       rcu_read_unlock();
+-      ieee80211_led_tx(local);
+-
+-      if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
+-          !(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED))
+-              goto skip_stats_update;
+-
+-      I802_DEBUG_INC(local->dot11TransmittedFrameCount);
+-      if (is_multicast_ether_addr(skb->data))
+-              I802_DEBUG_INC(local->dot11MulticastTransmittedFrameCount);
+-      if (retry_count > 0)
+-              I802_DEBUG_INC(local->dot11RetryCount);
+-      if (retry_count > 1)
+-              I802_DEBUG_INC(local->dot11MultipleRetryCount);
+-
+-skip_stats_update:
+-      ieee80211_report_used_skb(local, skb, false);
+-      dev_kfree_skb(skb);
+ }
+ EXPORT_SYMBOL(ieee80211_tx_status_8023);
diff --git a/package/kernel/mac80211/patches/subsys/324-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch b/package/kernel/mac80211/patches/subsys/324-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch
deleted file mode 100644 (file)
index abfb5b7..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 21 Aug 2020 05:51:58 +0200
-Subject: [PATCH] mac80211: notify the driver when a sta uses 4-address
- mode
-
-This is needed for encapsulation offload of 4-address mode packets
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -3840,6 +3840,8 @@ enum ieee80211_reconfig_type {
-  *    This callback may sleep.
-  * @update_vif_config: Update virtual interface offload flags
-  *    This callback may sleep.
-+ * @sta_set_4addr: Called to notify the driver when a station starts/stops using
-+ *    4-address mode
-  */
- struct ieee80211_ops {
-       void (*tx)(struct ieee80211_hw *hw,
-@@ -4153,6 +4155,8 @@ struct ieee80211_ops {
-                               struct ieee80211_sta *sta, u8 tids);
-       void (*update_vif_offload)(struct ieee80211_hw *hw,
-                                  struct ieee80211_vif *vif);
-+      void (*sta_set_4addr)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-+                            struct ieee80211_sta *sta, bool enabled);
- };
- /**
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -1698,6 +1698,7 @@ static int ieee80211_change_station(stru
-                       rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
-                       __ieee80211_check_fast_rx_iface(vlansdata);
-+                      drv_sta_set_4addr(local, sta->sdata, &sta->sta, true);
-               }
-               if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
---- a/net/mac80211/driver-ops.h
-+++ b/net/mac80211/driver-ops.h
-@@ -1400,4 +1400,18 @@ static inline void drv_update_vif_offloa
-       trace_drv_return_void(local);
- }
-+static inline void drv_sta_set_4addr(struct ieee80211_local *local,
-+                                   struct ieee80211_sub_if_data *sdata,
-+                                   struct ieee80211_sta *sta, bool enabled)
-+{
-+      sdata = get_bss_sdata(sdata);
-+      if (!check_sdata_in_driver(sdata))
-+              return;
-+
-+      trace_drv_sta_set_4addr(local, sdata, sta, enabled);
-+      if (local->ops->sta_set_4addr)
-+              local->ops->sta_set_4addr(&local->hw, &sdata->vif, sta, enabled);
-+      trace_drv_return_void(local);
-+}
-+
- #endif /* __MAC80211_DRIVER_OPS */
---- a/net/mac80211/mlme.c
-+++ b/net/mac80211/mlme.c
-@@ -3518,6 +3518,9 @@ static bool ieee80211_assoc_success(stru
-               goto out;
-       }
-+      if (sdata->wdev.use_4addr)
-+              drv_sta_set_4addr(local, sdata, &sta->sta, true);
-+
-       mutex_unlock(&sdata->local->sta_mtx);
-       /*
---- a/net/mac80211/trace.h
-+++ b/net/mac80211/trace.h
-@@ -2739,6 +2739,33 @@ DEFINE_EVENT(local_sdata_addr_evt, drv_u
-       TP_ARGS(local, sdata)
- );
-+TRACE_EVENT(drv_sta_set_4addr,
-+      TP_PROTO(struct ieee80211_local *local,
-+               struct ieee80211_sub_if_data *sdata,
-+               struct ieee80211_sta *sta, bool enabled),
-+
-+      TP_ARGS(local, sdata, sta, enabled),
-+
-+      TP_STRUCT__entry(
-+              LOCAL_ENTRY
-+              VIF_ENTRY
-+              STA_ENTRY
-+              __field(bool, enabled)
-+      ),
-+
-+      TP_fast_assign(
-+              LOCAL_ASSIGN;
-+              VIF_ASSIGN;
-+              STA_ASSIGN;
-+              __entry->enabled = enabled;
-+      ),
-+
-+      TP_printk(
-+              LOCAL_PR_FMT  VIF_PR_FMT  STA_PR_FMT " enabled:%d",
-+              LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->enabled
-+      )
-+);
-+
- #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
- #undef TRACE_INCLUDE_PATH
diff --git a/package/kernel/mac80211/patches/subsys/324-mac80211-support-using-ieee80211_tx_status_ext-to-fr.patch b/package/kernel/mac80211/patches/subsys/324-mac80211-support-using-ieee80211_tx_status_ext-to-fr.patch
new file mode 100644 (file)
index 0000000..5469a41
--- /dev/null
@@ -0,0 +1,63 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Thu, 20 Aug 2020 17:27:00 +0200
+Subject: [PATCH] mac80211: support using ieee80211_tx_status_ext to free
+ skbs without status info
+
+For encap-offloaded packets, ieee80211_free_txskb cannot be used, since it
+does not have the vif pointer.
+Using ieee80211_tx_status_ext for this purpose has the advantage of being able
+avoid an extra station lookup for AQL
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -1103,6 +1103,21 @@ void ieee80211_tx_status_ext(struct ieee
+                       sta->tx_stats.last_rate_info = *status->rate;
+       }
++      if (skb && (tx_time_est =
++                  ieee80211_info_get_tx_time_est(IEEE80211_SKB_CB(skb))) > 0) {
++              /* Do this here to avoid the expensive lookup of the sta
++               * in ieee80211_report_used_skb().
++               */
++              ieee80211_sta_update_pending_airtime(local, sta,
++                                                   skb_get_queue_mapping(skb),
++                                                   tx_time_est,
++                                                   true);
++              ieee80211_info_set_tx_time_est(IEEE80211_SKB_CB(skb), 0);
++      }
++
++      if (!status->info)
++              goto free;
++
+       rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
+       sband = hw->wiphy->bands[info->band];
+@@ -1146,17 +1161,6 @@ void ieee80211_tx_status_ext(struct ieee
+                       ieee80211s_update_metric(local, sta, status);
+       }
+-      if (skb && (tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) {
+-              /* Do this here to avoid the expensive lookup of the sta
+-               * in ieee80211_report_used_skb().
+-               */
+-              ieee80211_sta_update_pending_airtime(local, sta,
+-                                                   skb_get_queue_mapping(skb),
+-                                                   tx_time_est,
+-                                                   true);
+-              ieee80211_info_set_tx_time_est(info, 0);
+-      }
+-
+       if (skb && !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP))
+               return __ieee80211_tx_status(hw, status, rates_idx,
+                                            retry_count);
+@@ -1173,6 +1177,7 @@ void ieee80211_tx_status_ext(struct ieee
+               I802_DEBUG_INC(local->dot11FailedCount);
+       }
++free:
+       if (!skb)
+               return;
diff --git a/package/kernel/mac80211/patches/subsys/325-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch b/package/kernel/mac80211/patches/subsys/325-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch
new file mode 100644 (file)
index 0000000..e8b29bb
--- /dev/null
@@ -0,0 +1,53 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Fri, 21 Aug 2020 05:49:07 +0200
+Subject: [PATCH] mac80211: extend ieee80211_tx_status_ext to support
+ bulk free
+
+Store processed skbs ready to be freed in a list so the driver bulk free them
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -1092,12 +1092,14 @@ ieee80211_info_get_tx_time_est(struct ie
+  * @info: Basic tx status information
+  * @skb: Packet skb (can be NULL if not provided by the driver)
+  * @rate: The TX rate that was used when sending the packet
++ * @free_list: list where processed skbs are stored to be free'd by the driver
+  */
+ struct ieee80211_tx_status {
+       struct ieee80211_sta *sta;
+       struct ieee80211_tx_info *info;
+       struct sk_buff *skb;
+       struct rate_info *rate;
++      struct list_head *free_list;
+ };
+ /**
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -1053,7 +1053,10 @@ static void __ieee80211_tx_status(struct
+        * with this test...
+        */
+       if (!local->monitors && (!send_to_cooked || !local->cooked_mntrs)) {
+-              dev_kfree_skb(skb);
++              if (status->free_list)
++                      list_add_tail(&skb->list, status->free_list);
++              else
++                      dev_kfree_skb(skb);
+               return;
+       }
+@@ -1182,7 +1185,10 @@ free:
+               return;
+       ieee80211_report_used_skb(local, skb, false);
+-      dev_kfree_skb(skb);
++      if (status->free_list)
++              list_add_tail(&skb->list, status->free_list);
++      else
++              dev_kfree_skb(skb);
+ }
+ EXPORT_SYMBOL(ieee80211_tx_status_ext);
diff --git a/package/kernel/mac80211/patches/subsys/325-mac80211-skip-encap-offload-for-tx-multicast-control.patch b/package/kernel/mac80211/patches/subsys/325-mac80211-skip-encap-offload-for-tx-multicast-control.patch
deleted file mode 100644 (file)
index a320757..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 21 Aug 2020 05:54:10 +0200
-Subject: [PATCH] mac80211: skip encap offload for tx multicast/control
- packets
-
-This simplifies the checks in the encap offload tx handler and allows using
-it in cases where software crypto is used for multicast packets, e.g. when
-using an AP_VLAN.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/iface.c
-+++ b/net/mac80211/iface.c
-@@ -378,7 +378,8 @@ static bool ieee80211_set_sdata_offload_
-                       if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
-                           key->conf.cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
-                           key->conf.cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 ||
--                          key->conf.cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256)
-+                          key->conf.cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256 ||
-+                          !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE))
-                               continue;
-                       if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP ||
-                           !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
-@@ -1448,7 +1449,8 @@ static void ieee80211_set_vif_encap_ops(
-                       if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
-                           key->conf.cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
-                           key->conf.cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 ||
--                          key->conf.cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256)
-+                          key->conf.cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256 ||
-+                          !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE))
-                               continue;
-                       if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
-                               enabled = false;
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -4184,88 +4184,47 @@ static void ieee80211_8023_xmit(struct i
-                               struct sk_buff *skb)
- {
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
--      struct ethhdr *ehdr = (struct ethhdr *)skb->data;
-       struct ieee80211_local *local = sdata->local;
--      bool authorized = false;
--      bool multicast;
--      unsigned char *ra = ehdr->h_dest;
-       struct tid_ampdu_tx *tid_tx;
-       u8 tid;
--      if (IS_ERR(sta) || (sta && !sta->uploaded))
--              sta = NULL;
--
--      if (sdata->vif.type == NL80211_IFTYPE_STATION &&
--          (!sta || !test_sta_flag(sta, WLAN_STA_TDLS_PEER)))
--              ra = sdata->u.mgd.bssid;
--
--      if (is_zero_ether_addr(ra))
--              goto out_free;
--
-       if (local->ops->wake_tx_queue) {
-               u16 queue = __ieee80211_select_queue(sdata, sta, skb);
-               skb_set_queue_mapping(skb, queue);
-               skb_get_hash(skb);
-       }
--      multicast = is_multicast_ether_addr(ra);
--
--      if (sta)
--              authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
--
--      if (!multicast && !authorized &&
--          (ehdr->h_proto != sdata->control_port_protocol ||
--           !ether_addr_equal(sdata->vif.addr, ehdr->h_source)))
--              goto out_free;
--
--      if (multicast && sdata->vif.type == NL80211_IFTYPE_AP &&
--          !atomic_read(&sdata->u.ap.num_mcast_sta))
--              goto out_free;
--
-       if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) &&
-           test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
-               goto out_free;
-       memset(info, 0, sizeof(*info));
--      if (sta) {
--              tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
--              tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
--              if (tid_tx) {
--                      if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
--                              /* fall back to non-offload slow path */
--                              __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL);
--                              return;
--                      }
--
--                      info->flags |= IEEE80211_TX_CTL_AMPDU;
--                      if (tid_tx->timeout)
--                              tid_tx->last_tx = jiffies;
-+      tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
-+      tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
-+      if (tid_tx) {
-+              if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
-+                      /* fall back to non-offload slow path */
-+                      __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL);
-+                      return;
-               }
-+
-+              info->flags |= IEEE80211_TX_CTL_AMPDU;
-+              if (tid_tx->timeout)
-+                      tid_tx->last_tx = jiffies;
-       }
--      if (unlikely(!multicast && skb->sk &&
-+      if (unlikely(skb->sk &&
-                    skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS))
-               info->ack_frame_id = ieee80211_store_ack_skb(local, skb,
-                                                            &info->flags, NULL);
--      if (unlikely(sdata->control_port_protocol == ehdr->h_proto)) {
--              if (sdata->control_port_no_encrypt)
--                      info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
--              info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
--      }
--
--      if (multicast)
--              info->flags |= IEEE80211_TX_CTL_NO_ACK;
--
-       info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
-       ieee80211_tx_stats(dev, skb->len);
--      if (sta) {
--              sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
--              sta->tx_stats.packets[skb_get_queue_mapping(skb)]++;
--      }
-+      sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
-+      sta->tx_stats.packets[skb_get_queue_mapping(skb)]++;
-       if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-               sdata = container_of(sdata->bss,
-@@ -4286,6 +4245,7 @@ netdev_tx_t ieee80211_subif_start_xmit_8
-                                           struct net_device *dev)
- {
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+      struct ethhdr *ehdr = (struct ethhdr *)skb->data;
-       struct sta_info *sta;
-       if (unlikely(skb->len < ETH_HLEN)) {
-@@ -4297,6 +4257,10 @@ netdev_tx_t ieee80211_subif_start_xmit_8
-       if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
-               kfree_skb(skb);
-+      else if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded ||
-+                        !test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
-+                        sdata->control_port_protocol == ehdr->h_proto))
-+              ieee80211_subif_start_xmit(skb, dev);
-       else
-               ieee80211_8023_xmit(sdata, dev, sta, skb);
diff --git a/package/kernel/mac80211/patches/subsys/326-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch b/package/kernel/mac80211/patches/subsys/326-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch
new file mode 100644 (file)
index 0000000..5ad5ac6
--- /dev/null
@@ -0,0 +1,109 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Fri, 21 Aug 2020 05:51:58 +0200
+Subject: [PATCH] mac80211: notify the driver when a sta uses 4-address
+ mode
+
+This is needed for encapsulation offload of 4-address mode packets
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -3840,6 +3840,8 @@ enum ieee80211_reconfig_type {
+  *    This callback may sleep.
+  * @update_vif_config: Update virtual interface offload flags
+  *    This callback may sleep.
++ * @sta_set_4addr: Called to notify the driver when a station starts/stops using
++ *    4-address mode
+  */
+ struct ieee80211_ops {
+       void (*tx)(struct ieee80211_hw *hw,
+@@ -4153,6 +4155,8 @@ struct ieee80211_ops {
+                               struct ieee80211_sta *sta, u8 tids);
+       void (*update_vif_offload)(struct ieee80211_hw *hw,
+                                  struct ieee80211_vif *vif);
++      void (*sta_set_4addr)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
++                            struct ieee80211_sta *sta, bool enabled);
+ };
+ /**
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1693,6 +1693,7 @@ static int ieee80211_change_station(stru
+                       rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
+                       __ieee80211_check_fast_rx_iface(vlansdata);
++                      drv_sta_set_4addr(local, sta->sdata, &sta->sta, true);
+               }
+               if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
+--- a/net/mac80211/driver-ops.h
++++ b/net/mac80211/driver-ops.h
+@@ -1400,4 +1400,18 @@ static inline void drv_update_vif_offloa
+       trace_drv_return_void(local);
+ }
++static inline void drv_sta_set_4addr(struct ieee80211_local *local,
++                                   struct ieee80211_sub_if_data *sdata,
++                                   struct ieee80211_sta *sta, bool enabled)
++{
++      sdata = get_bss_sdata(sdata);
++      if (!check_sdata_in_driver(sdata))
++              return;
++
++      trace_drv_sta_set_4addr(local, sdata, sta, enabled);
++      if (local->ops->sta_set_4addr)
++              local->ops->sta_set_4addr(&local->hw, &sdata->vif, sta, enabled);
++      trace_drv_return_void(local);
++}
++
+ #endif /* __MAC80211_DRIVER_OPS */
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -3518,6 +3518,9 @@ static bool ieee80211_assoc_success(stru
+               goto out;
+       }
++      if (sdata->wdev.use_4addr)
++              drv_sta_set_4addr(local, sdata, &sta->sta, true);
++
+       mutex_unlock(&sdata->local->sta_mtx);
+       /*
+--- a/net/mac80211/trace.h
++++ b/net/mac80211/trace.h
+@@ -2739,6 +2739,33 @@ DEFINE_EVENT(local_sdata_addr_evt, drv_u
+       TP_ARGS(local, sdata)
+ );
++TRACE_EVENT(drv_sta_set_4addr,
++      TP_PROTO(struct ieee80211_local *local,
++               struct ieee80211_sub_if_data *sdata,
++               struct ieee80211_sta *sta, bool enabled),
++
++      TP_ARGS(local, sdata, sta, enabled),
++
++      TP_STRUCT__entry(
++              LOCAL_ENTRY
++              VIF_ENTRY
++              STA_ENTRY
++              __field(bool, enabled)
++      ),
++
++      TP_fast_assign(
++              LOCAL_ASSIGN;
++              VIF_ASSIGN;
++              STA_ASSIGN;
++              __entry->enabled = enabled;
++      ),
++
++      TP_printk(
++              LOCAL_PR_FMT  VIF_PR_FMT  STA_PR_FMT " enabled:%d",
++              LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->enabled
++      )
++);
++
+ #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
+ #undef TRACE_INCLUDE_PATH
diff --git a/package/kernel/mac80211/patches/subsys/326-mac80211-set-info-control.hw_key-for-encap-offload-p.patch b/package/kernel/mac80211/patches/subsys/326-mac80211-set-info-control.hw_key-for-encap-offload-p.patch
deleted file mode 100644 (file)
index 421d18f..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 21 Aug 2020 06:03:45 +0200
-Subject: [PATCH] mac80211: set info->control.hw_key for encap offload
- packets
-
-This is needed for drivers that don't do the key lookup themselves
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -4185,6 +4185,7 @@ static void ieee80211_8023_xmit(struct i
- {
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_local *local = sdata->local;
-+      struct ieee80211_key *key;
-       struct tid_ampdu_tx *tid_tx;
-       u8 tid;
-@@ -4233,6 +4234,10 @@ static void ieee80211_8023_xmit(struct i
-       info->flags |= IEEE80211_TX_CTL_HW_80211_ENCAP;
-       info->control.vif = &sdata->vif;
-+      key = rcu_dereference(sta->ptk[sta->ptk_idx]);
-+      if (key)
-+              info->control.hw_key = &key->conf;
-+
-       ieee80211_tx_8023(sdata, skb, skb->len, sta, false);
-       return;
diff --git a/package/kernel/mac80211/patches/subsys/327-mac80211-extend-AQL-aggregation-estimation-to-HE-and.patch b/package/kernel/mac80211/patches/subsys/327-mac80211-extend-AQL-aggregation-estimation-to-HE-and.patch
deleted file mode 100644 (file)
index 3d687f8..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Thu, 27 Aug 2020 12:44:36 +0200
-Subject: [PATCH] mac80211: extend AQL aggregation estimation to HE and fix
- unit mismatch
-
-The unit of the return value of ieee80211_get_rate_duration is nanoseconds, not
-milliseconds. Adjust the duration checks to account for that.
-For higher data rates, allow larger estimated aggregation sizes, and add some
-values for HE as well, which can use much larger aggregates.
-Since small packets with high data rates can now lead to duration values too
-small for info->tx_time_est, return a minimum of 4us.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/airtime.c
-+++ b/net/mac80211/airtime.c
-@@ -668,20 +668,26 @@ u32 ieee80211_calc_expected_tx_airtime(s
-                * This will not be very accurate, but much better than simply
-                * assuming un-aggregated tx in all cases.
-                */
--              if (duration > 400) /* <= VHT20 MCS2 1S */
-+              if (duration > 400 * 1024) /* <= VHT20 MCS2 1S */
-                       agg_shift = 1;
--              else if (duration > 250) /* <= VHT20 MCS3 1S or MCS1 2S */
-+              else if (duration > 250 * 1024) /* <= VHT20 MCS3 1S or MCS1 2S */
-                       agg_shift = 2;
--              else if (duration > 150) /* <= VHT20 MCS5 1S or MCS3 2S */
-+              else if (duration > 150 * 1024) /* <= VHT20 MCS5 1S or MCS2 2S */
-                       agg_shift = 3;
--              else
-+              else if (duration > 70 * 1024) /* <= VHT20 MCS5 2S */
-                       agg_shift = 4;
-+              else if (stat.encoding != RX_ENC_HE ||
-+                       duration > 20 * 1024) /* <= HE40 MCS6 2S */
-+                      agg_shift = 5;
-+              else
-+                      agg_shift = 6;
-               duration *= len;
-               duration /= AVG_PKT_SIZE;
-               duration /= 1024;
-+              duration += (overhead >> agg_shift);
--              return duration + (overhead >> agg_shift);
-+              return max_t(u32, duration, 4);
-       }
-       if (!conf)
diff --git a/package/kernel/mac80211/patches/subsys/327-mac80211-reorganize-code-to-remove-a-forward-declara.patch b/package/kernel/mac80211/patches/subsys/327-mac80211-reorganize-code-to-remove-a-forward-declara.patch
new file mode 100644 (file)
index 0000000..a3d6001
--- /dev/null
@@ -0,0 +1,1110 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Tue, 8 Sep 2020 12:16:26 +0200
+Subject: [PATCH] mac80211: reorganize code to remove a forward
+ declaration
+
+Remove the newly added ieee80211_set_vif_encap_ops declaration.
+No further code changes
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -43,7 +43,6 @@
+  */
+ static void ieee80211_iface_work(struct work_struct *work);
+-static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata);
+ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
+ {
+@@ -349,6 +348,511 @@ static int ieee80211_check_queues(struct
+       return 0;
+ }
++static int ieee80211_open(struct net_device *dev)
++{
++      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++      int err;
++
++      /* fail early if user set an invalid address */
++      if (!is_valid_ether_addr(dev->dev_addr))
++              return -EADDRNOTAVAIL;
++
++      err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type);
++      if (err)
++              return err;
++
++      return ieee80211_do_open(&sdata->wdev, true);
++}
++
++static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
++                            bool going_down)
++{
++      struct ieee80211_local *local = sdata->local;
++      unsigned long flags;
++      struct sk_buff *skb, *tmp;
++      u32 hw_reconf_flags = 0;
++      int i, flushed;
++      struct ps_data *ps;
++      struct cfg80211_chan_def chandef;
++      bool cancel_scan;
++      struct cfg80211_nan_func *func;
++
++      clear_bit(SDATA_STATE_RUNNING, &sdata->state);
++
++      cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata;
++      if (cancel_scan)
++              ieee80211_scan_cancel(local);
++
++      /*
++       * Stop TX on this interface first.
++       */
++      if (sdata->dev)
++              netif_tx_stop_all_queues(sdata->dev);
++
++      ieee80211_roc_purge(local, sdata);
++
++      switch (sdata->vif.type) {
++      case NL80211_IFTYPE_STATION:
++              ieee80211_mgd_stop(sdata);
++              break;
++      case NL80211_IFTYPE_ADHOC:
++              ieee80211_ibss_stop(sdata);
++              break;
++      case NL80211_IFTYPE_MONITOR:
++              if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES)
++                      break;
++              list_del_rcu(&sdata->u.mntr.list);
++              break;
++      default:
++              break;
++      }
++
++      /*
++       * Remove all stations associated with this interface.
++       *
++       * This must be done before calling ops->remove_interface()
++       * because otherwise we can later invoke ops->sta_notify()
++       * whenever the STAs are removed, and that invalidates driver
++       * assumptions about always getting a vif pointer that is valid
++       * (because if we remove a STA after ops->remove_interface()
++       * the driver will have removed the vif info already!)
++       *
++       * In WDS mode a station must exist here and be flushed, for
++       * AP_VLANs stations may exist since there's nothing else that
++       * would have removed them, but in other modes there shouldn't
++       * be any stations.
++       */
++      flushed = sta_info_flush(sdata);
++      WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
++                   ((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) ||
++                    (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)));
++
++      /* don't count this interface for allmulti while it is down */
++      if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
++              atomic_dec(&local->iff_allmultis);
++
++      if (sdata->vif.type == NL80211_IFTYPE_AP) {
++              local->fif_pspoll--;
++              local->fif_probe_req--;
++      } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
++              local->fif_probe_req--;
++      }
++
++      if (sdata->dev) {
++              netif_addr_lock_bh(sdata->dev);
++              spin_lock_bh(&local->filter_lock);
++              __hw_addr_unsync(&local->mc_list, &sdata->dev->mc,
++                               sdata->dev->addr_len);
++              spin_unlock_bh(&local->filter_lock);
++              netif_addr_unlock_bh(sdata->dev);
++      }
++
++      del_timer_sync(&local->dynamic_ps_timer);
++      cancel_work_sync(&local->dynamic_ps_enable_work);
++
++      cancel_work_sync(&sdata->recalc_smps);
++      sdata_lock(sdata);
++      mutex_lock(&local->mtx);
++      sdata->vif.csa_active = false;
++      if (sdata->vif.type == NL80211_IFTYPE_STATION)
++              sdata->u.mgd.csa_waiting_bcn = false;
++      if (sdata->csa_block_tx) {
++              ieee80211_wake_vif_queues(local, sdata,
++                                        IEEE80211_QUEUE_STOP_REASON_CSA);
++              sdata->csa_block_tx = false;
++      }
++      mutex_unlock(&local->mtx);
++      sdata_unlock(sdata);
++
++      cancel_work_sync(&sdata->csa_finalize_work);
++
++      cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
++
++      if (sdata->wdev.cac_started) {
++              chandef = sdata->vif.bss_conf.chandef;
++              WARN_ON(local->suspended);
++              mutex_lock(&local->mtx);
++              ieee80211_vif_release_channel(sdata);
++              mutex_unlock(&local->mtx);
++              cfg80211_cac_event(sdata->dev, &chandef,
++                                 NL80211_RADAR_CAC_ABORTED,
++                                 GFP_KERNEL);
++      }
++
++      /* APs need special treatment */
++      if (sdata->vif.type == NL80211_IFTYPE_AP) {
++              struct ieee80211_sub_if_data *vlan, *tmpsdata;
++
++              /* down all dependent devices, that is VLANs */
++              list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans,
++                                       u.vlan.list)
++                      dev_close(vlan->dev);
++              WARN_ON(!list_empty(&sdata->u.ap.vlans));
++      } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
++              /* remove all packets in parent bc_buf pointing to this dev */
++              ps = &sdata->bss->ps;
++
++              spin_lock_irqsave(&ps->bc_buf.lock, flags);
++              skb_queue_walk_safe(&ps->bc_buf, skb, tmp) {
++                      if (skb->dev == sdata->dev) {
++                              __skb_unlink(skb, &ps->bc_buf);
++                              local->total_ps_buffered--;
++                              ieee80211_free_txskb(&local->hw, skb);
++                      }
++              }
++              spin_unlock_irqrestore(&ps->bc_buf.lock, flags);
++      }
++
++      if (going_down)
++              local->open_count--;
++
++      switch (sdata->vif.type) {
++      case NL80211_IFTYPE_AP_VLAN:
++              mutex_lock(&local->mtx);
++              list_del(&sdata->u.vlan.list);
++              mutex_unlock(&local->mtx);
++              RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL);
++              /* see comment in the default case below */
++              ieee80211_free_keys(sdata, true);
++              /* no need to tell driver */
++              break;
++      case NL80211_IFTYPE_MONITOR:
++              if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) {
++                      local->cooked_mntrs--;
++                      break;
++              }
++
++              local->monitors--;
++              if (local->monitors == 0) {
++                      local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR;
++                      hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
++              }
++
++              ieee80211_adjust_monitor_flags(sdata, -1);
++              break;
++      case NL80211_IFTYPE_NAN:
++              /* clean all the functions */
++              spin_lock_bh(&sdata->u.nan.func_lock);
++
++              idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, i) {
++                      idr_remove(&sdata->u.nan.function_inst_ids, i);
++                      cfg80211_free_nan_func(func);
++              }
++              idr_destroy(&sdata->u.nan.function_inst_ids);
++
++              spin_unlock_bh(&sdata->u.nan.func_lock);
++              break;
++      case NL80211_IFTYPE_P2P_DEVICE:
++              /* relies on synchronize_rcu() below */
++              RCU_INIT_POINTER(local->p2p_sdata, NULL);
++              /* fall through */
++      default:
++              cancel_work_sync(&sdata->work);
++              /*
++               * When we get here, the interface is marked down.
++               * Free the remaining keys, if there are any
++               * (which can happen in AP mode if userspace sets
++               * keys before the interface is operating, and maybe
++               * also in WDS mode)
++               *
++               * Force the key freeing to always synchronize_net()
++               * to wait for the RX path in case it is using this
++               * interface enqueuing frames at this very time on
++               * another CPU.
++               */
++              ieee80211_free_keys(sdata, true);
++              skb_queue_purge(&sdata->skb_queue);
++      }
++
++      spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
++      for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
++              skb_queue_walk_safe(&local->pending[i], skb, tmp) {
++                      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
++                      if (info->control.vif == &sdata->vif) {
++                              __skb_unlink(skb, &local->pending[i]);
++                              ieee80211_free_txskb(&local->hw, skb);
++                      }
++              }
++      }
++      spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
++
++      if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
++              ieee80211_txq_remove_vlan(local, sdata);
++
++      sdata->bss = NULL;
++
++      if (local->open_count == 0)
++              ieee80211_clear_tx_pending(local);
++
++      sdata->vif.bss_conf.beacon_int = 0;
++
++      /*
++       * If the interface goes down while suspended, presumably because
++       * the device was unplugged and that happens before our resume,
++       * then the driver is already unconfigured and the remainder of
++       * this function isn't needed.
++       * XXX: what about WoWLAN? If the device has software state, e.g.
++       *      memory allocated, it might expect teardown commands from
++       *      mac80211 here?
++       */
++      if (local->suspended) {
++              WARN_ON(local->wowlan);
++              WARN_ON(rtnl_dereference(local->monitor_sdata));
++              return;
++      }
++
++      switch (sdata->vif.type) {
++      case NL80211_IFTYPE_AP_VLAN:
++              break;
++      case NL80211_IFTYPE_MONITOR:
++              if (local->monitors == 0)
++                      ieee80211_del_virtual_monitor(local);
++
++              mutex_lock(&local->mtx);
++              ieee80211_recalc_idle(local);
++              mutex_unlock(&local->mtx);
++
++              if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
++                      break;
++
++              /* fall through */
++      default:
++              if (going_down)
++                      drv_remove_interface(local, sdata);
++      }
++
++      ieee80211_recalc_ps(local);
++
++      if (cancel_scan)
++              flush_delayed_work(&local->scan_work);
++
++      if (local->open_count == 0) {
++              ieee80211_stop_device(local);
++
++              /* no reconfiguring after stop! */
++              return;
++      }
++
++      /* do after stop to avoid reconfiguring when we stop anyway */
++      ieee80211_configure_filter(local);
++      ieee80211_hw_config(local, hw_reconf_flags);
++
++      if (local->monitors == local->open_count)
++              ieee80211_add_virtual_monitor(local);
++}
++
++static int ieee80211_stop(struct net_device *dev)
++{
++      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++      ieee80211_do_stop(sdata, true);
++
++      return 0;
++}
++
++static void ieee80211_set_multicast_list(struct net_device *dev)
++{
++      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++      struct ieee80211_local *local = sdata->local;
++      int allmulti, sdata_allmulti;
++
++      allmulti = !!(dev->flags & IFF_ALLMULTI);
++      sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI);
++
++      if (allmulti != sdata_allmulti) {
++              if (dev->flags & IFF_ALLMULTI)
++                      atomic_inc(&local->iff_allmultis);
++              else
++                      atomic_dec(&local->iff_allmultis);
++              sdata->flags ^= IEEE80211_SDATA_ALLMULTI;
++      }
++
++      spin_lock_bh(&local->filter_lock);
++      __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len);
++      spin_unlock_bh(&local->filter_lock);
++      ieee80211_queue_work(&local->hw, &local->reconfig_filter);
++}
++
++/*
++ * Called when the netdev is removed or, by the code below, before
++ * the interface type changes.
++ */
++static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
++{
++      int i;
++
++      /* free extra data */
++      ieee80211_free_keys(sdata, false);
++
++      ieee80211_debugfs_remove_netdev(sdata);
++
++      for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
++              __skb_queue_purge(&sdata->fragments[i].skb_list);
++      sdata->fragment_next = 0;
++
++      if (ieee80211_vif_is_mesh(&sdata->vif))
++              ieee80211_mesh_teardown_sdata(sdata);
++}
++
++static void ieee80211_uninit(struct net_device *dev)
++{
++      ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev));
++}
++
++#if LINUX_VERSION_IS_GEQ(5,2,0)
++static u16 ieee80211_netdev_select_queue(struct net_device *dev,
++                                       struct sk_buff *skb,
++                                       struct net_device *sb_dev)
++#elif LINUX_VERSION_IS_GEQ(4,19,0)
++static u16 ieee80211_netdev_select_queue(struct net_device *dev,
++                                       struct sk_buff *skb,
++                                       struct net_device *sb_dev,
++                                       select_queue_fallback_t fallback)
++#elif LINUX_VERSION_IS_GEQ(3,14,0) || \
++    (LINUX_VERSION_CODE == KERNEL_VERSION(3,13,11) && UTS_UBUNTU_RELEASE_ABI > 30)
++static u16 ieee80211_netdev_select_queue(struct net_device *dev,
++                                       struct sk_buff *skb,
++                                       void *accel_priv,
++                                       select_queue_fallback_t fallback)
++#elif LINUX_VERSION_IS_GEQ(3,13,0)
++static u16 ieee80211_netdev_select_queue(struct net_device *dev,
++                                       struct sk_buff *skb,
++                                       void *accel_priv)
++#else
++static u16 ieee80211_netdev_select_queue(struct net_device *dev,
++                                       struct sk_buff *skb)
++#endif
++{
++      return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
++}
++
++static void
++ieee80211_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
++{
++      int i;
++
++      for_each_possible_cpu(i) {
++              const struct pcpu_sw_netstats *tstats;
++              u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
++              unsigned int start;
++
++              tstats = per_cpu_ptr(netdev_tstats(dev), i);
++
++              do {
++                      start = u64_stats_fetch_begin_irq(&tstats->syncp);
++                      rx_packets = tstats->rx_packets;
++                      tx_packets = tstats->tx_packets;
++                      rx_bytes = tstats->rx_bytes;
++                      tx_bytes = tstats->tx_bytes;
++              } while (u64_stats_fetch_retry_irq(&tstats->syncp, start));
++
++              stats->rx_packets += rx_packets;
++              stats->tx_packets += tx_packets;
++              stats->rx_bytes   += rx_bytes;
++              stats->tx_bytes   += tx_bytes;
++      }
++}
++#if LINUX_VERSION_IS_LESS(4,11,0)
++/* Just declare it here to keep sparse happy */
++struct rtnl_link_stats64 *bp_ieee80211_get_stats64(struct net_device *dev,
++                                                 struct rtnl_link_stats64 *stats);
++struct rtnl_link_stats64 *
++bp_ieee80211_get_stats64(struct net_device *dev,
++                       struct rtnl_link_stats64 *stats){
++      ieee80211_get_stats64(dev, stats);
++      return stats;
++}
++#endif
++
++static const struct net_device_ops ieee80211_dataif_ops = {
++      .ndo_open               = ieee80211_open,
++      .ndo_stop               = ieee80211_stop,
++      .ndo_uninit             = ieee80211_uninit,
++      .ndo_start_xmit         = ieee80211_subif_start_xmit,
++      .ndo_set_rx_mode        = ieee80211_set_multicast_list,
++      .ndo_set_mac_address    = ieee80211_change_mac,
++      .ndo_select_queue       = ieee80211_netdev_select_queue,
++#if LINUX_VERSION_IS_GEQ(4,11,0)
++      .ndo_get_stats64        = ieee80211_get_stats64,
++#else
++      .ndo_get_stats64 = bp_ieee80211_get_stats64,
++#endif
++
++};
++
++#if LINUX_VERSION_IS_GEQ(5,2,0)
++static u16 ieee80211_monitor_select_queue(struct net_device *dev,
++                                        struct sk_buff *skb,
++                                        struct net_device *sb_dev)
++#elif LINUX_VERSION_IS_GEQ(4,19,0)
++static u16 ieee80211_monitor_select_queue(struct net_device *dev,
++                                        struct sk_buff *skb,
++                                        struct net_device *sb_dev,
++                                        select_queue_fallback_t fallback)
++#elif LINUX_VERSION_IS_GEQ(3,14,0) || \
++    (LINUX_VERSION_CODE == KERNEL_VERSION(3,13,11) && UTS_UBUNTU_RELEASE_ABI > 30)
++static u16 ieee80211_monitor_select_queue(struct net_device *dev,
++                                        struct sk_buff *skb,
++                                        void *accel_priv,
++                                        select_queue_fallback_t fallback)
++#elif LINUX_VERSION_IS_GEQ(3,13,0)
++static u16 ieee80211_monitor_select_queue(struct net_device *dev,
++                                        struct sk_buff *skb,
++                                        void *accel_priv)
++#else
++static u16 ieee80211_monitor_select_queue(struct net_device *dev,
++                                        struct sk_buff *skb)
++#endif
++{
++      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++      struct ieee80211_local *local = sdata->local;
++      struct ieee80211_hdr *hdr;
++      struct ieee80211_radiotap_header *rtap = (void *)skb->data;
++
++      if (local->hw.queues < IEEE80211_NUM_ACS)
++              return 0;
++
++      if (skb->len < 4 ||
++          skb->len < le16_to_cpu(rtap->it_len) + 2 /* frame control */)
++              return 0; /* doesn't matter, frame will be dropped */
++
++      hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
++
++      return ieee80211_select_queue_80211(sdata, skb, hdr);
++}
++
++static const struct net_device_ops ieee80211_monitorif_ops = {
++      .ndo_open               = ieee80211_open,
++      .ndo_stop               = ieee80211_stop,
++      .ndo_uninit             = ieee80211_uninit,
++      .ndo_start_xmit         = ieee80211_monitor_start_xmit,
++      .ndo_set_rx_mode        = ieee80211_set_multicast_list,
++      .ndo_set_mac_address    = ieee80211_change_mac,
++      .ndo_select_queue       = ieee80211_monitor_select_queue,
++#if LINUX_VERSION_IS_GEQ(4,11,0)
++      .ndo_get_stats64        = ieee80211_get_stats64,
++#else
++      .ndo_get_stats64 = bp_ieee80211_get_stats64,
++#endif
++
++};
++
++static const struct net_device_ops ieee80211_dataif_8023_ops = {
++      .ndo_open               = ieee80211_open,
++      .ndo_stop               = ieee80211_stop,
++      .ndo_uninit             = ieee80211_uninit,
++      .ndo_start_xmit         = ieee80211_subif_start_xmit_8023,
++      .ndo_set_rx_mode        = ieee80211_set_multicast_list,
++      .ndo_set_mac_address    = ieee80211_change_mac,
++      .ndo_select_queue       = ieee80211_netdev_select_queue,
++#if LINUX_VERSION_IS_GEQ(4,11,0)
++      .ndo_get_stats64        = ieee80211_get_stats64,
++#else
++      .ndo_get_stats64 = bp_ieee80211_get_stats64,
++#endif
++
++};
++
+ static bool ieee80211_iftype_supports_encap_offload(enum nl80211_iftype iftype)
+ {
+       switch (iftype) {
+@@ -389,6 +893,31 @@ static bool ieee80211_set_sdata_offload_
+       return true;
+ }
++static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata)
++{
++      struct ieee80211_local *local = sdata->local;
++      struct ieee80211_sub_if_data *bss = sdata;
++      bool enabled;
++
++      if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
++              if (!sdata->bss)
++                      return;
++
++              bss = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
++      }
++
++      if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) ||
++          !ieee80211_iftype_supports_encap_offload(bss->vif.type))
++              return;
++
++      enabled = bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED;
++      if (sdata->wdev.use_4addr &&
++          !(bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_4ADDR))
++              enabled = false;
++
++      sdata->dev->netdev_ops = enabled ? &ieee80211_dataif_8023_ops :
++                                         &ieee80211_dataif_ops;
++}
+ static void ieee80211_recalc_sdata_offload(struct ieee80211_sub_if_data *sdata)
+ {
+@@ -866,511 +1395,6 @@ int ieee80211_do_open(struct wireless_de
+       return res;
+ }
+-static int ieee80211_open(struct net_device *dev)
+-{
+-      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-      int err;
+-
+-      /* fail early if user set an invalid address */
+-      if (!is_valid_ether_addr(dev->dev_addr))
+-              return -EADDRNOTAVAIL;
+-
+-      err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type);
+-      if (err)
+-              return err;
+-
+-      return ieee80211_do_open(&sdata->wdev, true);
+-}
+-
+-static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
+-                            bool going_down)
+-{
+-      struct ieee80211_local *local = sdata->local;
+-      unsigned long flags;
+-      struct sk_buff *skb, *tmp;
+-      u32 hw_reconf_flags = 0;
+-      int i, flushed;
+-      struct ps_data *ps;
+-      struct cfg80211_chan_def chandef;
+-      bool cancel_scan;
+-      struct cfg80211_nan_func *func;
+-
+-      clear_bit(SDATA_STATE_RUNNING, &sdata->state);
+-
+-      cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata;
+-      if (cancel_scan)
+-              ieee80211_scan_cancel(local);
+-
+-      /*
+-       * Stop TX on this interface first.
+-       */
+-      if (sdata->dev)
+-              netif_tx_stop_all_queues(sdata->dev);
+-
+-      ieee80211_roc_purge(local, sdata);
+-
+-      switch (sdata->vif.type) {
+-      case NL80211_IFTYPE_STATION:
+-              ieee80211_mgd_stop(sdata);
+-              break;
+-      case NL80211_IFTYPE_ADHOC:
+-              ieee80211_ibss_stop(sdata);
+-              break;
+-      case NL80211_IFTYPE_MONITOR:
+-              if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES)
+-                      break;
+-              list_del_rcu(&sdata->u.mntr.list);
+-              break;
+-      default:
+-              break;
+-      }
+-
+-      /*
+-       * Remove all stations associated with this interface.
+-       *
+-       * This must be done before calling ops->remove_interface()
+-       * because otherwise we can later invoke ops->sta_notify()
+-       * whenever the STAs are removed, and that invalidates driver
+-       * assumptions about always getting a vif pointer that is valid
+-       * (because if we remove a STA after ops->remove_interface()
+-       * the driver will have removed the vif info already!)
+-       *
+-       * In WDS mode a station must exist here and be flushed, for
+-       * AP_VLANs stations may exist since there's nothing else that
+-       * would have removed them, but in other modes there shouldn't
+-       * be any stations.
+-       */
+-      flushed = sta_info_flush(sdata);
+-      WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+-                   ((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) ||
+-                    (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)));
+-
+-      /* don't count this interface for allmulti while it is down */
+-      if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
+-              atomic_dec(&local->iff_allmultis);
+-
+-      if (sdata->vif.type == NL80211_IFTYPE_AP) {
+-              local->fif_pspoll--;
+-              local->fif_probe_req--;
+-      } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+-              local->fif_probe_req--;
+-      }
+-
+-      if (sdata->dev) {
+-              netif_addr_lock_bh(sdata->dev);
+-              spin_lock_bh(&local->filter_lock);
+-              __hw_addr_unsync(&local->mc_list, &sdata->dev->mc,
+-                               sdata->dev->addr_len);
+-              spin_unlock_bh(&local->filter_lock);
+-              netif_addr_unlock_bh(sdata->dev);
+-      }
+-
+-      del_timer_sync(&local->dynamic_ps_timer);
+-      cancel_work_sync(&local->dynamic_ps_enable_work);
+-
+-      cancel_work_sync(&sdata->recalc_smps);
+-      sdata_lock(sdata);
+-      mutex_lock(&local->mtx);
+-      sdata->vif.csa_active = false;
+-      if (sdata->vif.type == NL80211_IFTYPE_STATION)
+-              sdata->u.mgd.csa_waiting_bcn = false;
+-      if (sdata->csa_block_tx) {
+-              ieee80211_wake_vif_queues(local, sdata,
+-                                        IEEE80211_QUEUE_STOP_REASON_CSA);
+-              sdata->csa_block_tx = false;
+-      }
+-      mutex_unlock(&local->mtx);
+-      sdata_unlock(sdata);
+-
+-      cancel_work_sync(&sdata->csa_finalize_work);
+-
+-      cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
+-
+-      if (sdata->wdev.cac_started) {
+-              chandef = sdata->vif.bss_conf.chandef;
+-              WARN_ON(local->suspended);
+-              mutex_lock(&local->mtx);
+-              ieee80211_vif_release_channel(sdata);
+-              mutex_unlock(&local->mtx);
+-              cfg80211_cac_event(sdata->dev, &chandef,
+-                                 NL80211_RADAR_CAC_ABORTED,
+-                                 GFP_KERNEL);
+-      }
+-
+-      /* APs need special treatment */
+-      if (sdata->vif.type == NL80211_IFTYPE_AP) {
+-              struct ieee80211_sub_if_data *vlan, *tmpsdata;
+-
+-              /* down all dependent devices, that is VLANs */
+-              list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans,
+-                                       u.vlan.list)
+-                      dev_close(vlan->dev);
+-              WARN_ON(!list_empty(&sdata->u.ap.vlans));
+-      } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+-              /* remove all packets in parent bc_buf pointing to this dev */
+-              ps = &sdata->bss->ps;
+-
+-              spin_lock_irqsave(&ps->bc_buf.lock, flags);
+-              skb_queue_walk_safe(&ps->bc_buf, skb, tmp) {
+-                      if (skb->dev == sdata->dev) {
+-                              __skb_unlink(skb, &ps->bc_buf);
+-                              local->total_ps_buffered--;
+-                              ieee80211_free_txskb(&local->hw, skb);
+-                      }
+-              }
+-              spin_unlock_irqrestore(&ps->bc_buf.lock, flags);
+-      }
+-
+-      if (going_down)
+-              local->open_count--;
+-
+-      switch (sdata->vif.type) {
+-      case NL80211_IFTYPE_AP_VLAN:
+-              mutex_lock(&local->mtx);
+-              list_del(&sdata->u.vlan.list);
+-              mutex_unlock(&local->mtx);
+-              RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL);
+-              /* see comment in the default case below */
+-              ieee80211_free_keys(sdata, true);
+-              /* no need to tell driver */
+-              break;
+-      case NL80211_IFTYPE_MONITOR:
+-              if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) {
+-                      local->cooked_mntrs--;
+-                      break;
+-              }
+-
+-              local->monitors--;
+-              if (local->monitors == 0) {
+-                      local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR;
+-                      hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
+-              }
+-
+-              ieee80211_adjust_monitor_flags(sdata, -1);
+-              break;
+-      case NL80211_IFTYPE_NAN:
+-              /* clean all the functions */
+-              spin_lock_bh(&sdata->u.nan.func_lock);
+-
+-              idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, i) {
+-                      idr_remove(&sdata->u.nan.function_inst_ids, i);
+-                      cfg80211_free_nan_func(func);
+-              }
+-              idr_destroy(&sdata->u.nan.function_inst_ids);
+-
+-              spin_unlock_bh(&sdata->u.nan.func_lock);
+-              break;
+-      case NL80211_IFTYPE_P2P_DEVICE:
+-              /* relies on synchronize_rcu() below */
+-              RCU_INIT_POINTER(local->p2p_sdata, NULL);
+-              /* fall through */
+-      default:
+-              cancel_work_sync(&sdata->work);
+-              /*
+-               * When we get here, the interface is marked down.
+-               * Free the remaining keys, if there are any
+-               * (which can happen in AP mode if userspace sets
+-               * keys before the interface is operating, and maybe
+-               * also in WDS mode)
+-               *
+-               * Force the key freeing to always synchronize_net()
+-               * to wait for the RX path in case it is using this
+-               * interface enqueuing frames at this very time on
+-               * another CPU.
+-               */
+-              ieee80211_free_keys(sdata, true);
+-              skb_queue_purge(&sdata->skb_queue);
+-      }
+-
+-      spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+-      for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
+-              skb_queue_walk_safe(&local->pending[i], skb, tmp) {
+-                      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+-                      if (info->control.vif == &sdata->vif) {
+-                              __skb_unlink(skb, &local->pending[i]);
+-                              ieee80211_free_txskb(&local->hw, skb);
+-                      }
+-              }
+-      }
+-      spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+-
+-      if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+-              ieee80211_txq_remove_vlan(local, sdata);
+-
+-      sdata->bss = NULL;
+-
+-      if (local->open_count == 0)
+-              ieee80211_clear_tx_pending(local);
+-
+-      sdata->vif.bss_conf.beacon_int = 0;
+-
+-      /*
+-       * If the interface goes down while suspended, presumably because
+-       * the device was unplugged and that happens before our resume,
+-       * then the driver is already unconfigured and the remainder of
+-       * this function isn't needed.
+-       * XXX: what about WoWLAN? If the device has software state, e.g.
+-       *      memory allocated, it might expect teardown commands from
+-       *      mac80211 here?
+-       */
+-      if (local->suspended) {
+-              WARN_ON(local->wowlan);
+-              WARN_ON(rtnl_dereference(local->monitor_sdata));
+-              return;
+-      }
+-
+-      switch (sdata->vif.type) {
+-      case NL80211_IFTYPE_AP_VLAN:
+-              break;
+-      case NL80211_IFTYPE_MONITOR:
+-              if (local->monitors == 0)
+-                      ieee80211_del_virtual_monitor(local);
+-
+-              mutex_lock(&local->mtx);
+-              ieee80211_recalc_idle(local);
+-              mutex_unlock(&local->mtx);
+-
+-              if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
+-                      break;
+-
+-              /* fall through */
+-      default:
+-              if (going_down)
+-                      drv_remove_interface(local, sdata);
+-      }
+-
+-      ieee80211_recalc_ps(local);
+-
+-      if (cancel_scan)
+-              flush_delayed_work(&local->scan_work);
+-
+-      if (local->open_count == 0) {
+-              ieee80211_stop_device(local);
+-
+-              /* no reconfiguring after stop! */
+-              return;
+-      }
+-
+-      /* do after stop to avoid reconfiguring when we stop anyway */
+-      ieee80211_configure_filter(local);
+-      ieee80211_hw_config(local, hw_reconf_flags);
+-
+-      if (local->monitors == local->open_count)
+-              ieee80211_add_virtual_monitor(local);
+-}
+-
+-static int ieee80211_stop(struct net_device *dev)
+-{
+-      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+-      ieee80211_do_stop(sdata, true);
+-
+-      return 0;
+-}
+-
+-static void ieee80211_set_multicast_list(struct net_device *dev)
+-{
+-      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-      struct ieee80211_local *local = sdata->local;
+-      int allmulti, sdata_allmulti;
+-
+-      allmulti = !!(dev->flags & IFF_ALLMULTI);
+-      sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI);
+-
+-      if (allmulti != sdata_allmulti) {
+-              if (dev->flags & IFF_ALLMULTI)
+-                      atomic_inc(&local->iff_allmultis);
+-              else
+-                      atomic_dec(&local->iff_allmultis);
+-              sdata->flags ^= IEEE80211_SDATA_ALLMULTI;
+-      }
+-
+-      spin_lock_bh(&local->filter_lock);
+-      __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len);
+-      spin_unlock_bh(&local->filter_lock);
+-      ieee80211_queue_work(&local->hw, &local->reconfig_filter);
+-}
+-
+-/*
+- * Called when the netdev is removed or, by the code below, before
+- * the interface type changes.
+- */
+-static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
+-{
+-      int i;
+-
+-      /* free extra data */
+-      ieee80211_free_keys(sdata, false);
+-
+-      ieee80211_debugfs_remove_netdev(sdata);
+-
+-      for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
+-              __skb_queue_purge(&sdata->fragments[i].skb_list);
+-      sdata->fragment_next = 0;
+-
+-      if (ieee80211_vif_is_mesh(&sdata->vif))
+-              ieee80211_mesh_teardown_sdata(sdata);
+-}
+-
+-static void ieee80211_uninit(struct net_device *dev)
+-{
+-      ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev));
+-}
+-
+-#if LINUX_VERSION_IS_GEQ(5,2,0)
+-static u16 ieee80211_netdev_select_queue(struct net_device *dev,
+-                                       struct sk_buff *skb,
+-                                       struct net_device *sb_dev)
+-#elif LINUX_VERSION_IS_GEQ(4,19,0)
+-static u16 ieee80211_netdev_select_queue(struct net_device *dev,
+-                                       struct sk_buff *skb,
+-                                       struct net_device *sb_dev,
+-                                       select_queue_fallback_t fallback)
+-#elif LINUX_VERSION_IS_GEQ(3,14,0) || \
+-    (LINUX_VERSION_CODE == KERNEL_VERSION(3,13,11) && UTS_UBUNTU_RELEASE_ABI > 30)
+-static u16 ieee80211_netdev_select_queue(struct net_device *dev,
+-                                       struct sk_buff *skb,
+-                                       void *accel_priv,
+-                                       select_queue_fallback_t fallback)
+-#elif LINUX_VERSION_IS_GEQ(3,13,0)
+-static u16 ieee80211_netdev_select_queue(struct net_device *dev,
+-                                       struct sk_buff *skb,
+-                                       void *accel_priv)
+-#else
+-static u16 ieee80211_netdev_select_queue(struct net_device *dev,
+-                                       struct sk_buff *skb)
+-#endif
+-{
+-      return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
+-}
+-
+-static void
+-ieee80211_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
+-{
+-      int i;
+-
+-      for_each_possible_cpu(i) {
+-              const struct pcpu_sw_netstats *tstats;
+-              u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
+-              unsigned int start;
+-
+-              tstats = per_cpu_ptr(netdev_tstats(dev), i);
+-
+-              do {
+-                      start = u64_stats_fetch_begin_irq(&tstats->syncp);
+-                      rx_packets = tstats->rx_packets;
+-                      tx_packets = tstats->tx_packets;
+-                      rx_bytes = tstats->rx_bytes;
+-                      tx_bytes = tstats->tx_bytes;
+-              } while (u64_stats_fetch_retry_irq(&tstats->syncp, start));
+-
+-              stats->rx_packets += rx_packets;
+-              stats->tx_packets += tx_packets;
+-              stats->rx_bytes   += rx_bytes;
+-              stats->tx_bytes   += tx_bytes;
+-      }
+-}
+-#if LINUX_VERSION_IS_LESS(4,11,0)
+-/* Just declare it here to keep sparse happy */
+-struct rtnl_link_stats64 *bp_ieee80211_get_stats64(struct net_device *dev,
+-                                                 struct rtnl_link_stats64 *stats);
+-struct rtnl_link_stats64 *
+-bp_ieee80211_get_stats64(struct net_device *dev,
+-                       struct rtnl_link_stats64 *stats){
+-      ieee80211_get_stats64(dev, stats);
+-      return stats;
+-}
+-#endif
+-
+-static const struct net_device_ops ieee80211_dataif_ops = {
+-      .ndo_open               = ieee80211_open,
+-      .ndo_stop               = ieee80211_stop,
+-      .ndo_uninit             = ieee80211_uninit,
+-      .ndo_start_xmit         = ieee80211_subif_start_xmit,
+-      .ndo_set_rx_mode        = ieee80211_set_multicast_list,
+-      .ndo_set_mac_address    = ieee80211_change_mac,
+-      .ndo_select_queue       = ieee80211_netdev_select_queue,
+-#if LINUX_VERSION_IS_GEQ(4,11,0)
+-      .ndo_get_stats64        = ieee80211_get_stats64,
+-#else
+-      .ndo_get_stats64 = bp_ieee80211_get_stats64,
+-#endif
+-
+-};
+-
+-#if LINUX_VERSION_IS_GEQ(5,2,0)
+-static u16 ieee80211_monitor_select_queue(struct net_device *dev,
+-                                        struct sk_buff *skb,
+-                                        struct net_device *sb_dev)
+-#elif LINUX_VERSION_IS_GEQ(4,19,0)
+-static u16 ieee80211_monitor_select_queue(struct net_device *dev,
+-                                        struct sk_buff *skb,
+-                                        struct net_device *sb_dev,
+-                                        select_queue_fallback_t fallback)
+-#elif LINUX_VERSION_IS_GEQ(3,14,0) || \
+-    (LINUX_VERSION_CODE == KERNEL_VERSION(3,13,11) && UTS_UBUNTU_RELEASE_ABI > 30)
+-static u16 ieee80211_monitor_select_queue(struct net_device *dev,
+-                                        struct sk_buff *skb,
+-                                        void *accel_priv,
+-                                        select_queue_fallback_t fallback)
+-#elif LINUX_VERSION_IS_GEQ(3,13,0)
+-static u16 ieee80211_monitor_select_queue(struct net_device *dev,
+-                                        struct sk_buff *skb,
+-                                        void *accel_priv)
+-#else
+-static u16 ieee80211_monitor_select_queue(struct net_device *dev,
+-                                        struct sk_buff *skb)
+-#endif
+-{
+-      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-      struct ieee80211_local *local = sdata->local;
+-      struct ieee80211_hdr *hdr;
+-      struct ieee80211_radiotap_header *rtap = (void *)skb->data;
+-
+-      if (local->hw.queues < IEEE80211_NUM_ACS)
+-              return 0;
+-
+-      if (skb->len < 4 ||
+-          skb->len < le16_to_cpu(rtap->it_len) + 2 /* frame control */)
+-              return 0; /* doesn't matter, frame will be dropped */
+-
+-      hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
+-
+-      return ieee80211_select_queue_80211(sdata, skb, hdr);
+-}
+-
+-static const struct net_device_ops ieee80211_monitorif_ops = {
+-      .ndo_open               = ieee80211_open,
+-      .ndo_stop               = ieee80211_stop,
+-      .ndo_uninit             = ieee80211_uninit,
+-      .ndo_start_xmit         = ieee80211_monitor_start_xmit,
+-      .ndo_set_rx_mode        = ieee80211_set_multicast_list,
+-      .ndo_set_mac_address    = ieee80211_change_mac,
+-      .ndo_select_queue       = ieee80211_monitor_select_queue,
+-#if LINUX_VERSION_IS_GEQ(4,11,0)
+-      .ndo_get_stats64        = ieee80211_get_stats64,
+-#else
+-      .ndo_get_stats64 = bp_ieee80211_get_stats64,
+-#endif
+-
+-};
+-
+-static const struct net_device_ops ieee80211_dataif_8023_ops = {
+-      .ndo_open               = ieee80211_open,
+-      .ndo_stop               = ieee80211_stop,
+-      .ndo_uninit             = ieee80211_uninit,
+-      .ndo_start_xmit         = ieee80211_subif_start_xmit_8023,
+-      .ndo_set_rx_mode        = ieee80211_set_multicast_list,
+-      .ndo_set_mac_address    = ieee80211_change_mac,
+-      .ndo_select_queue       = ieee80211_netdev_select_queue,
+-#if LINUX_VERSION_IS_GEQ(4,11,0)
+-      .ndo_get_stats64        = ieee80211_get_stats64,
+-#else
+-      .ndo_get_stats64 = bp_ieee80211_get_stats64,
+-#endif
+-
+-};
+-
+ static void ieee80211_if_free(struct net_device *dev)
+ {
+       free_percpu(netdev_tstats(dev));
+@@ -1401,32 +1425,6 @@ static void ieee80211_if_setup_no_queue(
+ #endif
+ }
+-static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata)
+-{
+-      struct ieee80211_local *local = sdata->local;
+-      struct ieee80211_sub_if_data *bss = sdata;
+-      bool enabled;
+-
+-      if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+-              if (!sdata->bss)
+-                      return;
+-
+-              bss = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
+-      }
+-
+-      if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) ||
+-          !ieee80211_iftype_supports_encap_offload(bss->vif.type))
+-              return;
+-
+-      enabled = bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED;
+-      if (sdata->wdev.use_4addr &&
+-          !(bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_4ADDR))
+-              enabled = false;
+-
+-      sdata->dev->netdev_ops = enabled ? &ieee80211_dataif_8023_ops :
+-                                         &ieee80211_dataif_ops;
+-}
+-
+ static void ieee80211_iface_work(struct work_struct *work)
+ {
+       struct ieee80211_sub_if_data *sdata =
diff --git a/package/kernel/mac80211/patches/subsys/328-mac80211-add-AQL-support-for-VHT160-tx-rates.patch b/package/kernel/mac80211/patches/subsys/328-mac80211-add-AQL-support-for-VHT160-tx-rates.patch
deleted file mode 100644 (file)
index e22a09e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Thu, 27 Aug 2020 12:47:48 +0200
-Subject: [PATCH] mac80211: add AQL support for VHT160 tx rates
-
-When converting from struct ieee80211_tx_rate to ieee80211_rx_status,
-there was one check missing to fill in the bandwidth for 160 MHz
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/airtime.c
-+++ b/net/mac80211/airtime.c
-@@ -560,7 +560,9 @@ static int ieee80211_fill_rx_status(stru
-       if (rate->idx < 0 || !rate->count)
-               return -1;
--      if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
-+      if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
-+              stat->bw = RATE_INFO_BW_160;
-+      else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
-               stat->bw = RATE_INFO_BW_80;
-       else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-               stat->bw = RATE_INFO_BW_40;
diff --git a/package/kernel/mac80211/patches/subsys/328-mac80211-extend-AQL-aggregation-estimation-to-HE-and.patch b/package/kernel/mac80211/patches/subsys/328-mac80211-extend-AQL-aggregation-estimation-to-HE-and.patch
new file mode 100644 (file)
index 0000000..3d687f8
--- /dev/null
@@ -0,0 +1,49 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Thu, 27 Aug 2020 12:44:36 +0200
+Subject: [PATCH] mac80211: extend AQL aggregation estimation to HE and fix
+ unit mismatch
+
+The unit of the return value of ieee80211_get_rate_duration is nanoseconds, not
+milliseconds. Adjust the duration checks to account for that.
+For higher data rates, allow larger estimated aggregation sizes, and add some
+values for HE as well, which can use much larger aggregates.
+Since small packets with high data rates can now lead to duration values too
+small for info->tx_time_est, return a minimum of 4us.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/airtime.c
++++ b/net/mac80211/airtime.c
+@@ -668,20 +668,26 @@ u32 ieee80211_calc_expected_tx_airtime(s
+                * This will not be very accurate, but much better than simply
+                * assuming un-aggregated tx in all cases.
+                */
+-              if (duration > 400) /* <= VHT20 MCS2 1S */
++              if (duration > 400 * 1024) /* <= VHT20 MCS2 1S */
+                       agg_shift = 1;
+-              else if (duration > 250) /* <= VHT20 MCS3 1S or MCS1 2S */
++              else if (duration > 250 * 1024) /* <= VHT20 MCS3 1S or MCS1 2S */
+                       agg_shift = 2;
+-              else if (duration > 150) /* <= VHT20 MCS5 1S or MCS3 2S */
++              else if (duration > 150 * 1024) /* <= VHT20 MCS5 1S or MCS2 2S */
+                       agg_shift = 3;
+-              else
++              else if (duration > 70 * 1024) /* <= VHT20 MCS5 2S */
+                       agg_shift = 4;
++              else if (stat.encoding != RX_ENC_HE ||
++                       duration > 20 * 1024) /* <= HE40 MCS6 2S */
++                      agg_shift = 5;
++              else
++                      agg_shift = 6;
+               duration *= len;
+               duration /= AVG_PKT_SIZE;
+               duration /= 1024;
++              duration += (overhead >> agg_shift);
+-              return duration + (overhead >> agg_shift);
++              return max_t(u32, duration, 4);
+       }
+       if (!conf)
diff --git a/package/kernel/mac80211/patches/subsys/329-mac80211-add-AQL-support-for-VHT160-tx-rates.patch b/package/kernel/mac80211/patches/subsys/329-mac80211-add-AQL-support-for-VHT160-tx-rates.patch
new file mode 100644 (file)
index 0000000..e22a09e
--- /dev/null
@@ -0,0 +1,23 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Thu, 27 Aug 2020 12:47:48 +0200
+Subject: [PATCH] mac80211: add AQL support for VHT160 tx rates
+
+When converting from struct ieee80211_tx_rate to ieee80211_rx_status,
+there was one check missing to fill in the bandwidth for 160 MHz
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/airtime.c
++++ b/net/mac80211/airtime.c
+@@ -560,7 +560,9 @@ static int ieee80211_fill_rx_status(stru
+       if (rate->idx < 0 || !rate->count)
+               return -1;
+-      if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
++      if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
++              stat->bw = RATE_INFO_BW_160;
++      else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
+               stat->bw = RATE_INFO_BW_80;
+       else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+               stat->bw = RATE_INFO_BW_40;
index 1487e10f42de0c9195fda064e771c785f261cf1b..8db3a758a1b346afbf566cd566a15bddf3688a07 100644 (file)
@@ -18,7 +18,7 @@
                                const u8 *addr);
 --- a/include/net/mac80211.h
 +++ b/include/net/mac80211.h
-@@ -1519,6 +1519,7 @@ enum ieee80211_smps_mode {
+@@ -1521,6 +1521,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
@@ -26,7 +26,7 @@
   *
   * @chandef: the channel definition to tune to
   * @radar_enabled: whether radar detection is enabled
-@@ -1539,6 +1540,7 @@ enum ieee80211_smps_mode {
+@@ -1541,6 +1542,7 @@ enum ieee80211_smps_mode {
  struct ieee80211_conf {
        u32 flags;
        int power_level, dynamic_ps_timeout;
@@ -57,7 +57,7 @@
        __NL80211_ATTR_AFTER_LAST,
 --- a/net/mac80211/cfg.c
 +++ b/net/mac80211/cfg.c
-@@ -2615,6 +2615,19 @@ static int ieee80211_get_tx_power(struct
+@@ -2611,6 +2611,19 @@ static int ieee80211_get_tx_power(struct
        return 0;
  }
  
@@ -77,7 +77,7 @@
  static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
                                  const u8 *addr)
  {
-@@ -4045,6 +4058,7 @@ const struct cfg80211_ops mac80211_confi
+@@ -4041,6 +4054,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,