aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/mac80211/patches/subsys/314-mac80211-rework-tx-encapsulation-offload-API.patch
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2020-09-08 14:22:28 +0200
committerFelix Fietkau <nbd@nbd.name>2020-09-09 11:51:47 +0200
commitd717343c85f6c305b6896e4d3aa93f9cd67e9d22 (patch)
treef1980987e216215a2331273254e615bb3f8afe27 /package/kernel/mac80211/patches/subsys/314-mac80211-rework-tx-encapsulation-offload-API.patch
parentc18a872825c8dd27a398e4f5b2f98c9b5066d8a9 (diff)
downloadupstream-d717343c85f6c305b6896e4d3aa93f9cd67e9d22.tar.gz
upstream-d717343c85f6c305b6896e4d3aa93f9cd67e9d22.tar.bz2
upstream-d717343c85f6c305b6896e4d3aa93f9cd67e9d22.zip
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@nbd.name>
Diffstat (limited to 'package/kernel/mac80211/patches/subsys/314-mac80211-rework-tx-encapsulation-offload-API.patch')
-rw-r--r--package/kernel/mac80211/patches/subsys/314-mac80211-rework-tx-encapsulation-offload-API.patch651
1 files changed, 0 insertions, 651 deletions
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
index 4f0d264947..0000000000
--- a/package/kernel/mac80211/patches/subsys/314-mac80211-rework-tx-encapsulation-offload-API.patch
+++ /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;