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