[openwrt/openwrt] mac80211: update encap offload patches to the latest version

LEDE Commits lede-commits at lists.infradead.org
Wed Sep 9 05:53:11 EDT 2020


nbd pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/d717343c85f6c305b6896e4d3aa93f9cd67e9d22

commit d717343c85f6c305b6896e4d3aa93f9cd67e9d22
Author: Felix Fietkau <nbd at nbd.name>
AuthorDate: Tue Sep 8 14:22:28 2020 +0200

    mac80211: update encap offload patches to the latest version
    
    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 at nbd.name>
---
 ...-missing-queue-hash-initialization-to-80.patch} |    4 +-
 ...ck-and-refresh-aggregation-session-in-en.patch} |    4 +-
 ...p-encap-offload-for-tx-multicast-control.patch} |   26 +-
 ...-info-control.hw_key-for-encap-offload-p.patch} |    2 +-
 ...0211-rework-tx-encapsulation-offload-API.patch} |  180 ++--
 ...educe-duplication-in-tx-status-functions.patch} |    0
 ...ove-tx-status-call-to-ieee80211_sta_regi.patch} |    0
 ...0211-optimize-station-connection-monitor.patch} |    0
 ...p-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch} |    8 +-
 ...fy-802.3-offload-and-802.11-tx-status-co.patch} |    0
 ...port-using-ieee80211_tx_status_ext-to-fr.patch} |    0
 ...end-ieee80211_tx_status_ext-to-support-b.patch} |    4 +-
 ...ify-the-driver-when-a-sta-uses-4-address.patch} |    2 +-
 ...organize-code-to-remove-a-forward-declara.patch | 1110 ++++++++++++++++++++
 ...end-AQL-aggregation-estimation-to-HE-and.patch} |    0
 ...0211-add-AQL-support-for-VHT160-tx-rates.patch} |    0
 .../500-mac80211_configure_antenna_gain.patch      |    8 +-
 17 files changed, 1199 insertions(+), 149 deletions(-)

diff --git a/package/kernel/mac80211/patches/subsys/320-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
similarity index 97%
rename from package/kernel/mac80211/patches/subsys/320-mac80211-add-missing-queue-hash-initialization-to-80.patch
rename to package/kernel/mac80211/patches/subsys/314-mac80211-add-missing-queue-hash-initialization-to-80.patch
index d9d3fded75..eb56a2cac5 100644
--- a/package/kernel/mac80211/patches/subsys/320-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
@@ -1,7 +1,7 @@
 From: Felix Fietkau <nbd at nbd.name>
 Date: Mon, 17 Aug 2020 13:55:56 +0200
-Subject: [PATCH] mac80211: add missing queue/hash initialization to 802.3
- xmit
+Subject: [PATCH] mac80211: add missing queue/hash initialization to
+ 802.3 xmit
 
 Fixes AQL for encap-offloaded tx
 
diff --git a/package/kernel/mac80211/patches/subsys/321-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
similarity index 98%
rename from package/kernel/mac80211/patches/subsys/321-mac80211-check-and-refresh-aggregation-session-in-en.patch
rename to package/kernel/mac80211/patches/subsys/315-mac80211-check-and-refresh-aggregation-session-in-en.patch
index 0188e19b71..e411d59722 100644
--- a/package/kernel/mac80211/patches/subsys/321-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
@@ -1,7 +1,7 @@
 From: Felix Fietkau <nbd at nbd.name>
 Date: Mon, 17 Aug 2020 21:11:25 +0200
-Subject: [PATCH] mac80211: check and refresh aggregation session in encap
- offload tx
+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
diff --git a/package/kernel/mac80211/patches/subsys/325-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
similarity index 77%
rename from package/kernel/mac80211/patches/subsys/325-mac80211-skip-encap-offload-for-tx-multicast-control.patch
rename to package/kernel/mac80211/patches/subsys/316-mac80211-skip-encap-offload-for-tx-multicast-control.patch
index a32075768a..6dce21db1e 100644
--- a/package/kernel/mac80211/patches/subsys/325-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
@@ -10,28 +10,6 @@ using an AP_VLAN.
 Signed-off-by: Felix Fietkau <nbd at 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
@@ -144,8 +122,8 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
 +	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 (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);
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/317-mac80211-set-info-control.hw_key-for-encap-offload-p.patch
similarity index 93%
rename from package/kernel/mac80211/patches/subsys/326-mac80211-set-info-control.hw_key-for-encap-offload-p.patch
rename to package/kernel/mac80211/patches/subsys/317-mac80211-set-info-control.hw_key-for-encap-offload-p.patch
index 421d18f2c2..cb5a986312 100644
--- a/package/kernel/mac80211/patches/subsys/326-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
@@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  	u8 tid;
  
 @@ -4233,6 +4234,10 @@ static void ieee80211_8023_xmit(struct i
- 	info->flags |= IEEE80211_TX_CTL_HW_80211_ENCAP;
+ 	info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP;
  	info->control.vif = &sdata->vif;
  
 +	key = rcu_dereference(sta->ptk[sta->ptk_idx]);
diff --git a/package/kernel/mac80211/patches/subsys/314-mac80211-rework-tx-encapsulation-offload-API.patch b/package/kernel/mac80211/patches/subsys/318-mac80211-rework-tx-encapsulation-offload-API.patch
similarity index 82%
rename from package/kernel/mac80211/patches/subsys/314-mac80211-rework-tx-encapsulation-offload-API.patch
rename to package/kernel/mac80211/patches/subsys/318-mac80211-rework-tx-encapsulation-offload-API.patch
index 4f0d264947..7593c41da0 100644
--- a/package/kernel/mac80211/patches/subsys/314-mac80211-rework-tx-encapsulation-offload-API.patch
+++ b/package/kernel/mac80211/patches/subsys/318-mac80211-rework-tx-encapsulation-offload-API.patch
@@ -198,34 +198,6 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  };
  
  /**
---- 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[] = {
@@ -287,16 +259,15 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  
  bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
  {
-@@ -348,6 +349,99 @@ static int ieee80211_check_queues(struct
+@@ -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_P2P_GO:
-+	case NL80211_IFTYPE_P2P_CLIENT:
 +	case NL80211_IFTYPE_STATION:
 +		return true;
 +	default:
@@ -307,7 +278,6 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
 +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;
@@ -315,18 +285,6 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
 +	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)
@@ -387,7 +345,7 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  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
+@@ -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);
@@ -395,7 +353,7 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  		} else {
  			netif_carrier_off(dev);
  		}
-@@ -616,6 +711,7 @@ int ieee80211_do_open(struct wireless_de
+@@ -616,6 +697,7 @@ int ieee80211_do_open(struct wireless_de
  
  		ieee80211_adjust_monitor_flags(sdata, 1);
  		ieee80211_configure_filter(local);
@@ -403,7 +361,7 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  		mutex_lock(&local->mtx);
  		ieee80211_recalc_idle(local);
  		mutex_unlock(&local->mtx);
-@@ -625,10 +721,13 @@ int ieee80211_do_open(struct wireless_de
+@@ -625,10 +707,13 @@ int ieee80211_do_open(struct wireless_de
  	default:
  		if (coming_up) {
  			ieee80211_del_virtual_monitor(local);
@@ -417,7 +375,7 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  			res = ieee80211_check_queues(sdata,
  				ieee80211_vif_type_p2p(&sdata->vif));
  			if (res)
-@@ -1286,61 +1385,6 @@ static const struct net_device_ops ieee8
+@@ -1286,61 +1371,6 @@ static const struct net_device_ops ieee8
  
  };
  
@@ -479,7 +437,7 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  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(
+@@ -1371,6 +1401,32 @@ static void ieee80211_if_setup_no_queue(
  #endif
  }
  
@@ -487,7 +445,6 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
 +{
 +	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) {
@@ -506,24 +463,6 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
 +	    !(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;
 +}
@@ -531,7 +470,7 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  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
+@@ -1553,7 +1609,6 @@ static void ieee80211_setup_sdata(struct
  	sdata->vif.bss_conf.txpower = INT_MIN; /* unset */
  
  	sdata->noack_map = 0;
@@ -539,7 +478,7 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  
  	/* only monitor/p2p-device differ */
  	if (sdata->dev) {
-@@ -1688,6 +1776,7 @@ static int ieee80211_runtime_change_ifty
+@@ -1688,6 +1743,7 @@ static int ieee80211_runtime_change_ifty
  
  	ieee80211_teardown_sdata(sdata);
  
@@ -547,7 +486,7 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  	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
+@@ -1700,6 +1756,7 @@ static int ieee80211_runtime_change_ifty
  	ieee80211_check_queues(sdata, type);
  
  	ieee80211_setup_sdata(sdata, type);
@@ -586,40 +525,6 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  	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,
@@ -637,15 +542,72 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  #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
+@@ -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);
- 		return NETDEV_TX_OK;
+@@ -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/315-mac80211-reduce-duplication-in-tx-status-functions.patch b/package/kernel/mac80211/patches/subsys/319-mac80211-reduce-duplication-in-tx-status-functions.patch
similarity index 100%
rename from package/kernel/mac80211/patches/subsys/315-mac80211-reduce-duplication-in-tx-status-functions.patch
rename to package/kernel/mac80211/patches/subsys/319-mac80211-reduce-duplication-in-tx-status-functions.patch
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/320-mac80211-remove-tx-status-call-to-ieee80211_sta_regi.patch
similarity index 100%
rename from package/kernel/mac80211/patches/subsys/316-mac80211-remove-tx-status-call-to-ieee80211_sta_regi.patch
rename to package/kernel/mac80211/patches/subsys/320-mac80211-remove-tx-status-call-to-ieee80211_sta_regi.patch
diff --git a/package/kernel/mac80211/patches/subsys/317-mac80211-optimize-station-connection-monitor.patch b/package/kernel/mac80211/patches/subsys/321-mac80211-optimize-station-connection-monitor.patch
similarity index 100%
rename from package/kernel/mac80211/patches/subsys/317-mac80211-optimize-station-connection-monitor.patch
rename to package/kernel/mac80211/patches/subsys/321-mac80211-optimize-station-connection-monitor.patch
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/322-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch
similarity index 97%
rename from package/kernel/mac80211/patches/subsys/318-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch
rename to package/kernel/mac80211/patches/subsys/322-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch
index 85287a6ef1..b9069ef9b8 100644
--- a/package/kernel/mac80211/patches/subsys/318-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
@@ -198,7 +198,7 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  		goto encap_out;
  
  	if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
-@@ -4247,7 +4247,7 @@ static void ieee80211_8023_xmit(struct i
+@@ -4230,7 +4230,7 @@ static void ieee80211_8023_xmit(struct i
  		sdata = container_of(sdata->bss,
  				     struct ieee80211_sub_if_data, u.ap);
  
@@ -206,8 +206,8 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
 +	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
+ 	if (key)
+@@ -4355,7 +4355,7 @@ static bool ieee80211_tx_pending_skb(str
  
  	sdata = vif_to_sdata(info->control.vif);
  
@@ -216,7 +216,7 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  		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
+@@ -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);
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/323-mac80211-unify-802.3-offload-and-802.11-tx-status-co.patch
similarity index 100%
rename from package/kernel/mac80211/patches/subsys/319-mac80211-unify-802.3-offload-and-802.11-tx-status-co.patch
rename to package/kernel/mac80211/patches/subsys/323-mac80211-unify-802.3-offload-and-802.11-tx-status-co.patch
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/324-mac80211-support-using-ieee80211_tx_status_ext-to-fr.patch
similarity index 100%
rename from package/kernel/mac80211/patches/subsys/322-mac80211-support-using-ieee80211_tx_status_ext-to-fr.patch
rename to package/kernel/mac80211/patches/subsys/324-mac80211-support-using-ieee80211_tx_status_ext-to-fr.patch
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/325-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch
similarity index 98%
rename from package/kernel/mac80211/patches/subsys/323-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch
rename to package/kernel/mac80211/patches/subsys/325-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch
index c0f2b7b10a..e8b29bb4c5 100644
--- a/package/kernel/mac80211/patches/subsys/323-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
@@ -1,7 +1,7 @@
 From: Felix Fietkau <nbd at nbd.name>
 Date: Fri, 21 Aug 2020 05:49:07 +0200
-Subject: [PATCH] mac80211: extend ieee80211_tx_status_ext to support bulk
- free
+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
 
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/326-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch
similarity index 97%
rename from package/kernel/mac80211/patches/subsys/324-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch
rename to package/kernel/mac80211/patches/subsys/326-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch
index abfb5b76d0..5ad5ac6a78 100644
--- a/package/kernel/mac80211/patches/subsys/324-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
@@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  /**
 --- a/net/mac80211/cfg.c
 +++ b/net/mac80211/cfg.c
-@@ -1698,6 +1698,7 @@ static int ieee80211_change_station(stru
+@@ -1693,6 +1693,7 @@ static int ieee80211_change_station(stru
  
  			rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
  			__ieee80211_check_fast_rx_iface(vlansdata);
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
index 0000000000..a3d600152c
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/327-mac80211-reorganize-code-to-remove-a-forward-declara.patch
@@ -0,0 +1,1110 @@
+From: Felix Fietkau <nbd at 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 at 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/327-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
similarity index 100%
rename from package/kernel/mac80211/patches/subsys/327-mac80211-extend-AQL-aggregation-estimation-to-HE-and.patch
rename to package/kernel/mac80211/patches/subsys/328-mac80211-extend-AQL-aggregation-estimation-to-HE-and.patch
diff --git a/package/kernel/mac80211/patches/subsys/328-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
similarity index 100%
rename from package/kernel/mac80211/patches/subsys/328-mac80211-add-AQL-support-for-VHT160-tx-rates.patch
rename to package/kernel/mac80211/patches/subsys/329-mac80211-add-AQL-support-for-VHT160-tx-rates.patch
diff --git a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch
index 1487e10f42..8db3a758a1 100644
--- a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch
+++ b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch
@@ -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,



More information about the lede-commits mailing list