The removed patches were applied upstream. Remove the 300-mac80211-optimize-skb-resizing.patch. This patch was not applied upstream, but it conflicts with upstream changes and needs bigger changes. It was applied with Felix to remove this patch for now. It should be reworked and then send upstream later. Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
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
|
|
@@ -4304,6 +4304,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)
|
|
{
|
|
@@ -4313,7 +4342,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;
|
|
@@ -4407,30 +4435,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,
|
|
@@ -5753,6 +5758,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,
|
|
@@ -6034,6 +6040,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
|
|
@@ -1606,6 +1606,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
|
|
*
|
|
@@ -1626,6 +1641,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
|
|
@@ -1662,6 +1682,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;
|
|
@@ -2328,6 +2349,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 {
|
|
@@ -2380,6 +2404,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
|
|
@@ -3814,6 +3839,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,
|
|
@@ -4125,6 +4152,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
|
|
@@ -1384,4 +1384,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
|
|
@@ -993,8 +993,6 @@ struct ieee80211_sub_if_data {
|
|
} debugfs;
|
|
#endif
|
|
|
|
- bool hw_80211_encap;
|
|
-
|
|
/* must be last, dynamically sized area in this! */
|
|
struct ieee80211_vif vif;
|
|
};
|
|
@@ -1772,6 +1770,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)
|
|
@@ -1293,61 +1378,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));
|
|
@@ -1378,6 +1408,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 =
|
|
@@ -1560,7 +1616,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) {
|
|
@@ -1695,6 +1750,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);
|
|
@@ -1707,6 +1763,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;
|
|
- fallthrough;
|
|
-
|
|
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
|
|
@@ -2734,6 +2734,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
|
|
@@ -4178,11 +4178,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;
|
|
|
|
@@ -4231,7 +4230,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;
|
|
|
|
@@ -4248,12 +4246,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);
|
|
@@ -4262,15 +4257,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;
|