mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-26 17:01:14 +00:00
d717343c85
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>
614 lines
19 KiB
Diff
614 lines
19 KiB
Diff
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;
|