The removed patches were applied upstream.
Remove the 300-mac80211-optimize-skb-resizing.patch.
This patch was not applied upstream, but it conflicts with upstream
changes and needs bigger changes. It was applied with Felix to remove
this patch for now. It should be reworked and then send upstream later.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
PKG_NAME:=mac80211
-PKG_VERSION:=5.8.18-1
-PKG_RELEASE:=5
-PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.8.18/
-PKG_HASH:=f04a8172423c6a945fc7d9844b04f33fda9ae574e552f8f18ee3bdfcfb494563
+PKG_VERSION:=5.9.12-1
+PKG_RELEASE:=1
+PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.9.12/
+PKG_HASH:=8cf3f23152a787eeec2df1d7b38a559b0d89bdc823d9ac99175a4eb76d2b619e
PKG_SOURCE:=backports-$(PKG_VERSION).tar.xz
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/backports-$(PKG_VERSION)
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
-@@ -3045,6 +3045,8 @@ void regulatory_hint_country_ie(struct w
+@@ -3047,6 +3047,8 @@ void regulatory_hint_country_ie(struct w
enum environment_cap env = ENVIRON_ANY;
struct regulatory_request *request = NULL, *lr;
/* IE len must be evenly divisible by 2 */
if (country_ie_len & 0x01)
return;
-@@ -3296,6 +3298,7 @@ static bool is_wiphy_all_set_reg_flag(en
+@@ -3298,6 +3300,7 @@ static bool is_wiphy_all_set_reg_flag(en
void regulatory_hint_disconnect(void)
{
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -9053,6 +9053,21 @@ static int ath10k_mac_init_rd(struct ath
+@@ -9049,6 +9049,21 @@ static int ath10k_mac_init_rd(struct ath
return 0;
}
int ath10k_mac_register(struct ath10k *ar)
{
static const u32 cipher_suites[] = {
-@@ -9380,6 +9395,12 @@ int ath10k_mac_register(struct ath10k *a
+@@ -9376,6 +9391,12 @@ int ath10k_mac_register(struct ath10k *a
ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER;
if (ret)
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -9397,7 +9397,7 @@ int ath10k_mac_register(struct ath10k *a
+@@ -9393,7 +9393,7 @@ int ath10k_mac_register(struct ath10k *a
ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER;
#ifdef CPTCFG_MAC80211_LEDS
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -1043,7 +1043,7 @@ static int ath10k_monitor_vdev_start(str
+@@ -1038,7 +1038,7 @@ static int ath10k_monitor_vdev_start(str
arg.channel.min_power = 0;
arg.channel.max_power = channel->max_power * 2;
arg.channel.max_reg_power = channel->max_reg_power * 2;
reinit_completion(&ar->vdev_setup_done);
reinit_completion(&ar->vdev_delete_done);
-@@ -1489,7 +1489,7 @@ static int ath10k_vdev_start_restart(str
+@@ -1484,7 +1484,7 @@ static int ath10k_vdev_start_restart(str
arg.channel.min_power = 0;
arg.channel.max_power = chandef->chan->max_power * 2;
arg.channel.max_reg_power = chandef->chan->max_reg_power * 2;
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
arg.ssid = arvif->u.ap.ssid;
-@@ -3194,7 +3194,7 @@ static int ath10k_update_channel_list(st
+@@ -3189,7 +3189,7 @@ static int ath10k_update_channel_list(st
ch->min_power = 0;
ch->max_power = channel->max_power * 2;
ch->max_reg_power = channel->max_reg_power * 2;
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -1011,6 +1011,40 @@ static inline int ath10k_vdev_setup_sync
+@@ -1006,6 +1006,40 @@ static inline int ath10k_vdev_setup_sync
return ar->last_wmi_vdev_start_status;
}
static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
{
struct cfg80211_chan_def *chandef = NULL;
-@@ -1043,7 +1077,8 @@ static int ath10k_monitor_vdev_start(str
+@@ -1038,7 +1072,8 @@ static int ath10k_monitor_vdev_start(str
arg.channel.min_power = 0;
arg.channel.max_power = channel->max_power * 2;
arg.channel.max_reg_power = channel->max_reg_power * 2;
reinit_completion(&ar->vdev_setup_done);
reinit_completion(&ar->vdev_delete_done);
-@@ -1489,7 +1524,8 @@ static int ath10k_vdev_start_restart(str
+@@ -1484,7 +1519,8 @@ static int ath10k_vdev_start_restart(str
arg.channel.min_power = 0;
arg.channel.max_power = chandef->chan->max_power * 2;
arg.channel.max_reg_power = chandef->chan->max_reg_power * 2;
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
arg.ssid = arvif->u.ap.ssid;
-@@ -3194,7 +3230,8 @@ static int ath10k_update_channel_list(st
+@@ -3189,7 +3225,8 @@ static int ath10k_update_channel_list(st
ch->min_power = 0;
ch->max_power = channel->max_power * 2;
ch->max_reg_power = channel->max_reg_power * 2;
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1551,6 +1551,7 @@ int __init brcmf_core_init(void)
+@@ -1554,6 +1554,7 @@ int __init brcmf_core_init(void)
{
if (!schedule_work(&brcmf_driver_work))
return -EBUSY;
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -2955,6 +2955,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip
+@@ -2956,6 +2956,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip
* preference in cfg struct to apply this to
* FW later while initializing the dongle
*/
void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
struct brcmf_mp_device *settings)
{
-@@ -30,6 +60,8 @@ void brcmf_of_probe(struct device *dev,
+@@ -43,6 +73,8 @@ void brcmf_of_probe(struct device *dev,
of_node_put(root);
}
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -2907,6 +2907,63 @@ done:
+@@ -2908,6 +2908,63 @@ done:
}
static int
brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev,
int idx, u8 *mac, struct station_info *sinfo)
{
-@@ -3002,6 +3059,7 @@ static s32 brcmf_inform_single_bss(struc
+@@ -3003,6 +3060,7 @@ static s32 brcmf_inform_single_bss(struc
struct brcmu_chan ch;
u16 channel;
u32 freq;
u16 notify_capability;
u16 notify_interval;
u8 *notify_ie;
-@@ -3026,6 +3084,17 @@ static s32 brcmf_inform_single_bss(struc
+@@ -3027,6 +3085,17 @@ static s32 brcmf_inform_single_bss(struc
band = NL80211_BAND_5GHZ;
freq = ieee80211_channel_to_frequency(channel, band);
bss_data.chan = ieee80211_get_channel(wiphy, freq);
bss_data.scan_width = NL80211_BSS_CHAN_WIDTH_20;
bss_data.boottime_ns = ktime_to_ns(ktime_get_boottime());
-@@ -5478,6 +5547,7 @@ static struct cfg80211_ops brcmf_cfg8021
+@@ -5481,6 +5550,7 @@ static struct cfg80211_ops brcmf_cfg8021
.leave_ibss = brcmf_cfg80211_leave_ibss,
.get_station = brcmf_cfg80211_get_station,
.dump_station = brcmf_cfg80211_dump_station,
.add_key = brcmf_cfg80211_add_key,
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1349,6 +1349,8 @@ int brcmf_attach(struct device *dev)
+@@ -1352,6 +1352,8 @@ int brcmf_attach(struct device *dev)
/* Link to bus module */
drvr->hdrlen = 0;
/* Attach and link in the protocol */
ret = brcmf_proto_attach(drvr);
-@@ -1431,6 +1433,12 @@ void brcmf_detach(struct device *dev)
+@@ -1434,6 +1436,12 @@ void brcmf_detach(struct device *dev)
if (drvr == NULL)
return;
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
-@@ -11470,6 +11470,15 @@ static const struct attribute_group ipw_
+@@ -11472,6 +11472,15 @@ static const struct attribute_group ipw_
.attrs = ipw_sysfs_entries,
};
#ifdef CPTCFG_IPW2200_PROMISCUOUS
static int ipw_prom_open(struct net_device *dev)
{
-@@ -11518,15 +11527,6 @@ static netdev_tx_t ipw_prom_hard_start_x
+@@ -11520,15 +11529,6 @@ static netdev_tx_t ipw_prom_hard_start_x
return NETDEV_TX_OK;
}
--- a/local-symbols
+++ b/local-symbols
-@@ -424,43 +424,6 @@ USB_SIERRA_NET=
+@@ -435,43 +435,6 @@ USB_SIERRA_NET=
USB_VL600=
USB_NET_CH9200=
USB_NET_AQC111=
gpiodev = bus->chipco.dev ? : pcidev;
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h
-@@ -22,7 +22,7 @@ struct brcms_led {
- bool active_low;
+@@ -24,7 +24,7 @@ struct brcms_led {
+ struct gpio_desc *gpiod;
};
-#ifdef CPTCFG_BCMA_DRIVER_GPIO
select BRCMUTIL
--- a/Kconfig.local
+++ b/Kconfig.local
-@@ -1276,117 +1276,6 @@ config BACKPORTED_USB_NET_CH9200
+@@ -1309,117 +1309,6 @@ config BACKPORTED_USB_NET_CH9200
config BACKPORTED_USB_NET_AQC111
tristate
default USB_NET_AQC111
--- a/local-symbols
+++ b/local-symbols
-@@ -321,6 +321,7 @@ RT2X00_LIB_FIRMWARE=
+@@ -330,6 +330,7 @@ RT2X00_LIB_FIRMWARE=
RT2X00_LIB_CRYPTO=
RT2X00_LIB_LEDS=
RT2X00_LIB_DEBUGFS=
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 14 Aug 2020 16:13:45 +0200
-Subject: [PATCH] backports: add netif_receive_skb_list
-
-It will be needed by pending mac80211 changes
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/backport-include/linux/netdevice.h
-+++ b/backport-include/linux/netdevice.h
-@@ -372,6 +372,18 @@ static inline int _bp_netdev_upper_dev_l
- macro_dispatcher(netdev_upper_dev_link, __VA_ARGS__)(__VA_ARGS__)
- #endif
-
-+#if LINUX_VERSION_IS_LESS(4,19,0)
-+static inline void netif_receive_skb_list(struct list_head *head)
-+{
-+ struct sk_buff *skb, *next;
-+
-+ list_for_each_entry_safe(skb, next, head, list) {
-+ skb_list_del_init(skb);
-+ netif_receive_skb(skb);
-+ }
-+}
-+#endif
-+
- #if LINUX_VERSION_IS_LESS(5,0,0)
- static inline int backport_dev_open(struct net_device *dev, struct netlink_ext_ack *extack)
- {
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 14 Aug 2020 16:13:55 +0200
-Subject: [PATCH] backports: add skb_list_del_init
-
-It will be needed by pending mac80211 changes
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/backport-include/linux/skbuff.h
-+++ b/backport-include/linux/skbuff.h
-@@ -384,6 +384,12 @@ static inline void skb_mark_not_on_list(
- {
- skb->next = NULL;
- }
-+
-+static inline void skb_list_del_init(struct sk_buff *skb)
-+{
-+ __list_del_entry(&skb->list);
-+ skb_mark_not_on_list(skb);
-+}
- #endif /* 4.19.10 <= x < 4.20 */
- #endif
-
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Mon, 28 Sep 2020 08:35:28 +0200
-Subject: [PATCH] backports: add sched_set_fifo_low
-
-It is needed for mt76
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
- create mode 100644 backport/backport-include/linux/sched.h
-
---- /dev/null
-+++ b/backport-include/linux/sched.h
-@@ -0,0 +1,19 @@
-+#ifndef __BACKPORT_LINUX_SCHED_H
-+#define __BACKPORT_LINUX_SCHED_H
-+
-+#include_next <linux/sched.h>
-+#include <linux/version.h>
-+
-+#if LINUX_VERSION_IS_LESS(5,9,0)
-+#include <uapi/linux/sched/types.h>
-+
-+static inline void sched_set_fifo_low(struct task_struct *p)
-+{
-+ struct sched_param sparam = {.sched_priority = 1};
-+
-+ sched_setscheduler(p, SCHED_FIFO, &sparam);
-+}
-+
-+#endif
-+
-+#endif
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 11 Nov 2020 13:34:26 +0100
-Subject: [PATCH] backports: backport tasklet_setup, from_tasklet
-
-Backport the new tasklet API
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/backport-include/linux/interrupt.h
-+++ b/backport-include/linux/interrupt.h
-@@ -31,6 +31,23 @@ static inline void backport_hrtimer_star
- hrtimer_start(timer, _time, mode);
- }
- #define hrtimer_start LINUX_BACKPORT(hrtimer_start)
-+
-+#endif
-+
-+#if LINUX_VERSION_IS_LESS(5,9,0)
-+
-+static inline void
-+tasklet_setup(struct tasklet_struct *t,
-+ void (*callback)(struct tasklet_struct *))
-+{
-+ void (*cb)(unsigned long data) = (void *)callback;
-+
-+ tasklet_init(t, cb, (unsigned long)t);
-+}
-+
-+#define from_tasklet(var, callback_tasklet, tasklet_fieldname) \
-+ container_of(callback_tasklet, typeof(*var), tasklet_fieldname)
-+
- #endif
-
- #endif /* _BP_LINUX_INTERRUPT_H */
- aead_request_set_ad(aead_req, sg[0].length);
-
- crypto_aead_encrypt(aead_req);
-- kzfree(aead_req);
+- kfree_sensitive(aead_req);
-
- return 0;
-}
- aead_request_set_ad(aead_req, sg[0].length);
-
- err = crypto_aead_decrypt(aead_req);
-- kzfree(aead_req);
+- kfree_sensitive(aead_req);
-
- return err;
-}
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -1198,7 +1198,6 @@ static int ieee80211_stop_ap(struct wiph
+@@ -1200,7 +1200,6 @@ static int ieee80211_stop_ap(struct wiph
sdata->vif.bss_conf.ftmr_params = NULL;
__sta_info_flush(sdata, true);
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -2346,7 +2346,7 @@ static int ieee80211_scan(struct wiphy *
+@@ -2353,7 +2353,7 @@ static int ieee80211_scan(struct wiphy *
* the frames sent while scanning on other channel will be
* lost)
*/
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sun, 17 Mar 2019 18:11:30 +0100
-Subject: [PATCH] mac80211: optimize skb resizing
-
-When forwarding unicast packets from ethernet to batman-adv over 802.11s
-(with forwarding disabled), the typical required headroom to transmit
-encrypted packets on mt76 is 32 (802.11) + 6 (802.11s) + 8 (CCMP) +
-2 (padding) + 6 (LLC) + 18 (batman-adv) - 14 (old ethernet header) = 58 bytes.
-
-On systems where NET_SKB_PAD is 64 this leads to a call to pskb_expand_head
-for every packet, since mac80211 also tries to allocate 16 bytes status
-headroom for radiotap headers.
-
-This patch fixes these unnecessary reallocations by only requiring the extra
-status headroom in ieee80211_tx_monitor()
-If however a reallocation happens before that call, the status headroom gets
-added there as well, in order to avoid double reallocation.
-
-The patch also cleans up the code by moving the headroom calculation to
-ieee80211_skb_resize.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -1809,6 +1809,9 @@ int ieee80211_tx_control_port(struct wip
- u64 *cookie);
- int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
- const u8 *buf, size_t len);
-+int ieee80211_skb_resize(struct ieee80211_local *local,
-+ struct ieee80211_sub_if_data *sdata,
-+ struct sk_buff *skb, int hdrlen, int hdr_add);
-
- /* HT */
- void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -846,6 +846,11 @@ void ieee80211_tx_monitor(struct ieee802
- struct net_device *prev_dev = NULL;
- int rtap_len;
-
-+ if (ieee80211_skb_resize(local, NULL, skb, 0, 0)) {
-+ dev_kfree_skb(skb);
-+ return;
-+ }
-+
- /* send frame to monitor interfaces now */
- rtap_len = ieee80211_tx_radiotap_len(info, status);
- if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -1937,37 +1937,53 @@ static bool ieee80211_tx(struct ieee8021
- }
-
- /* device xmit handlers */
--
--static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
-- struct sk_buff *skb,
-- int head_need, bool may_encrypt)
-+int ieee80211_skb_resize(struct ieee80211_local *local,
-+ struct ieee80211_sub_if_data *sdata,
-+ struct sk_buff *skb, int hdr_len, int hdr_extra)
- {
-- struct ieee80211_local *local = sdata->local;
-+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hdr *hdr;
-- bool enc_tailroom;
-- int tail_need = 0;
--
-- hdr = (struct ieee80211_hdr *) skb->data;
-- enc_tailroom = may_encrypt &&
-- (sdata->crypto_tx_tailroom_needed_cnt ||
-- ieee80211_is_mgmt(hdr->frame_control));
--
-- if (enc_tailroom) {
-- tail_need = IEEE80211_ENCRYPT_TAILROOM;
-- tail_need -= skb_tailroom(skb);
-- tail_need = max_t(int, tail_need, 0);
-+ int head_need, head_max;
-+ int tail_need, tail_max;
-+ bool enc_tailroom = false;
-+
-+ if (sdata && !hdr_len &&
-+ !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) {
-+ hdr = (struct ieee80211_hdr *) skb->data;
-+ enc_tailroom = (sdata->crypto_tx_tailroom_needed_cnt ||
-+ ieee80211_is_mgmt(hdr->frame_control));
-+ hdr_len += sdata->encrypt_headroom;
-+ }
-+
-+ head_need = head_max = hdr_len;
-+ tail_need = tail_max = 0;
-+ if (!sdata) {
-+ head_need = head_max = local->tx_headroom;
-+ } else {
-+ head_max += hdr_extra;
-+ head_max += max_t(int, local->tx_headroom,
-+ local->hw.extra_tx_headroom);
-+ head_need += local->hw.extra_tx_headroom;
-+
-+ tail_max = IEEE80211_ENCRYPT_TAILROOM;
-+ if (enc_tailroom)
-+ tail_need = tail_max;
- }
-
- if (skb_cloned(skb) &&
- (!ieee80211_hw_check(&local->hw, SUPPORTS_CLONED_SKBS) ||
- !skb_clone_writable(skb, ETH_HLEN) || enc_tailroom))
- I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
-- else if (head_need || tail_need)
-+ else if (head_need > skb_headroom(skb) ||
-+ tail_need > skb_tailroom(skb))
- I802_DEBUG_INC(local->tx_expand_skb_head);
- else
- return 0;
-
-- if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) {
-+ head_max = max_t(int, 0, head_max - skb_headroom(skb));
-+ tail_max = max_t(int, 0, tail_max - skb_tailroom(skb));
-+
-+ if (pskb_expand_head(skb, head_max, tail_max, GFP_ATOMIC)) {
- wiphy_debug(local->hw.wiphy,
- "failed to reallocate TX buffer\n");
- return -ENOMEM;
-@@ -1983,18 +1999,8 @@ void ieee80211_xmit(struct ieee80211_sub
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hdr *hdr;
-- int headroom;
-- bool may_encrypt;
--
-- may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT);
-
-- headroom = local->tx_headroom;
-- if (may_encrypt)
-- headroom += sdata->encrypt_headroom;
-- headroom -= skb_headroom(skb);
-- headroom = max_t(int, 0, headroom);
--
-- if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
-+ if (ieee80211_skb_resize(local, sdata, skb, 0, 0)) {
- ieee80211_free_txskb(&local->hw, skb);
- return;
- }
-@@ -2809,29 +2815,13 @@ static struct sk_buff *ieee80211_build_h
- }
-
- skb_pull(skb, skip_header_bytes);
-- head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
-+ head_need = hdrlen + encaps_len + meshhdrlen;
-
-- /*
-- * So we need to modify the skb header and hence need a copy of
-- * that. The head_need variable above doesn't, so far, include
-- * the needed header space that we don't need right away. If we
-- * can, then we don't reallocate right now but only after the
-- * frame arrives at the master device (if it does...)
-- *
-- * If we cannot, however, then we will reallocate to include all
-- * the ever needed space. Also, if we need to reallocate it anyway,
-- * make it big enough for everything we may ever need.
-- */
--
-- if (head_need > 0 || skb_cloned(skb)) {
-- head_need += sdata->encrypt_headroom;
-- head_need += local->tx_headroom;
-- head_need = max_t(int, 0, head_need);
-- if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
-- ieee80211_free_txskb(&local->hw, skb);
-- skb = NULL;
-- return ERR_PTR(-ENOMEM);
-- }
-+ if (ieee80211_skb_resize(local, sdata, skb, head_need,
-+ sdata->encrypt_headroom)) {
-+ ieee80211_free_txskb(&local->hw, skb);
-+ skb = NULL;
-+ return ERR_PTR(-ENOMEM);
- }
-
- if (encaps_data)
-@@ -3446,7 +3436,6 @@ static bool ieee80211_xmit_fast(struct i
- struct ieee80211_local *local = sdata->local;
- u16 ethertype = (skb->data[12] << 8) | skb->data[13];
- int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
-- int hw_headroom = sdata->local->hw.extra_tx_headroom;
- struct ethhdr eth;
- struct ieee80211_tx_info *info;
- struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
-@@ -3498,10 +3487,7 @@ static bool ieee80211_xmit_fast(struct i
- * as the may-encrypt argument for the resize to not account for
- * more room than we already have in 'extra_head'
- */
-- if (unlikely(ieee80211_skb_resize(sdata, skb,
-- max_t(int, extra_head + hw_headroom -
-- skb_headroom(skb), 0),
-- false))) {
-+ if (unlikely(ieee80211_skb_resize(local, sdata, skb, extra_head, 0))) {
- kfree_skb(skb);
- return true;
- }
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
-@@ -339,6 +339,7 @@ struct sta_info *sta_info_alloc(struct i
+@@ -357,6 +357,7 @@ struct sta_info *sta_info_alloc(struct i
INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
mutex_init(&sta->ampdu_mlme.mtx);
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 24 Jul 2020 20:25:07 +0200
-Subject: [PATCH] mac80211: improve AQL tx airtime estimation
-
-AQL does not take into account that most HT/VHT/HE traffic is A-MPDU aggregated.
-Because of that, the per-packet airtime overhead is vastly overestimated.
-Improve it by assuming an average aggregation length of 16 for non-legacy
-traffic if not using the VO AC queue.
-This should improve performance with high data rates, especially with multiple
-stations
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/airtime.c
-+++ b/net/mac80211/airtime.c
-@@ -551,7 +551,7 @@ EXPORT_SYMBOL_GPL(ieee80211_calc_tx_airt
- u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *pubsta,
-- int len)
-+ int len, bool ampdu)
- {
- struct ieee80211_supported_band *sband;
- struct ieee80211_chanctx_conf *conf;
-@@ -572,10 +572,26 @@ u32 ieee80211_calc_expected_tx_airtime(s
- if (pubsta) {
- struct sta_info *sta = container_of(pubsta, struct sta_info,
- sta);
-+ struct ieee80211_tx_rate *rate = &sta->tx_stats.last_rate;
-+ u32 airtime;
-
-- return ieee80211_calc_tx_airtime_rate(hw,
-- &sta->tx_stats.last_rate,
-- band, len);
-+ if (!(rate->flags & (IEEE80211_TX_RC_VHT_MCS |
-+ IEEE80211_TX_RC_MCS)))
-+ ampdu = false;
-+
-+ /*
-+ * Assume that HT/VHT transmission on any AC except VO will
-+ * use aggregation. Since we don't have reliable reporting
-+ * of aggregation length, assume an average of 16.
-+ * This will not be very accurate, but much better than simply
-+ * assuming un-aggregated tx.
-+ */
-+ airtime = ieee80211_calc_tx_airtime_rate(hw, rate, band,
-+ ampdu ? len * 16 : len);
-+ if (ampdu)
-+ airtime /= 16;
-+
-+ return airtime;
- }
-
- if (!conf)
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -2294,7 +2294,7 @@ extern const struct ethtool_ops ieee8021
- u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *pubsta,
-- int len);
-+ int len, bool ampdu);
- #ifdef CPTCFG_MAC80211_NOINLINE
- #define debug_noinline noinline
- #else
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -3707,10 +3707,11 @@ encap_out:
-
- if (vif &&
- wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
-+ bool ampdu = txq->ac != IEEE80211_AC_VO;
- u32 airtime;
-
- airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta,
-- skb->len);
-+ skb->len, ampdu);
- if (airtime) {
- airtime = ieee80211_info_set_tx_time_est(info, airtime);
- ieee80211_sta_update_pending_airtime(local, tx.sta,
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sat, 25 Jul 2020 20:53:23 +0200
-Subject: [PATCH] mac80211: add a function for running rx without passing skbs
- to the stack
-
-This can be used to run mac80211 rx processing on a batch of frames in NAPI
-poll before passing them to the network stack in a large batch.
-This can improve icache footprint, or it can be used to pass frames via
-netif_receive_skb_list.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -4358,6 +4358,31 @@ void ieee80211_free_hw(struct ieee80211_
- void ieee80211_restart_hw(struct ieee80211_hw *hw);
-
- /**
-+ * ieee80211_rx_list - receive frame and store processed skbs in a list
-+ *
-+ * Use this function to hand received frames to mac80211. The receive
-+ * buffer in @skb must start with an IEEE 802.11 header. In case of a
-+ * paged @skb is used, the driver is recommended to put the ieee80211
-+ * header of the frame on the linear part of the @skb to avoid memory
-+ * allocation and/or memcpy by the stack.
-+ *
-+ * This function may not be called in IRQ context. Calls to this function
-+ * for a single hardware must be synchronized against each other. Calls to
-+ * this function, ieee80211_rx_ni() and ieee80211_rx_irqsafe() may not be
-+ * mixed for a single hardware. Must not run concurrently with
-+ * ieee80211_tx_status() or ieee80211_tx_status_ni().
-+ *
-+ * This function must be called with BHs disabled and RCU read lock
-+ *
-+ * @hw: the hardware this frame came in on
-+ * @sta: the station the frame was received from, or %NULL
-+ * @skb: the buffer to receive, owned by mac80211 after this call
-+ * @list: the destination list
-+ */
-+void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
-+ struct sk_buff *skb, struct list_head *list);
-+
-+/**
- * ieee80211_rx_napi - receive frame from NAPI context
- *
- * Use this function to hand received frames to mac80211. The receive
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -218,7 +218,7 @@ enum ieee80211_rx_flags {
- };
-
- struct ieee80211_rx_data {
-- struct napi_struct *napi;
-+ struct list_head *list;
- struct sk_buff *skb;
- struct ieee80211_local *local;
- struct ieee80211_sub_if_data *sdata;
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2579,8 +2579,8 @@ static void ieee80211_deliver_skb_to_loc
- memset(skb->cb, 0, sizeof(skb->cb));
-
- /* deliver to local stack */
-- if (rx->napi)
-- napi_gro_receive(rx->napi, skb);
-+ if (rx->list)
-+ list_add_tail(&skb->list, rx->list);
- else
- netif_receive_skb(skb);
- }
-@@ -3870,7 +3870,6 @@ void ieee80211_release_reorder_timeout(s
- /* This is OK -- must be QoS data frame */
- .security_idx = tid,
- .seqno_idx = tid,
-- .napi = NULL, /* must be NULL to not have races */
- };
- struct tid_ampdu_rx *tid_agg_rx;
-
-@@ -4480,8 +4479,8 @@ static bool ieee80211_invoke_fast_rx(str
- /* deliver to local stack */
- skb->protocol = eth_type_trans(skb, fast_rx->dev);
- memset(skb->cb, 0, sizeof(skb->cb));
-- if (rx->napi)
-- napi_gro_receive(rx->napi, skb);
-+ if (rx->list)
-+ list_add_tail(&skb->list, rx->list);
- else
- netif_receive_skb(skb);
-
-@@ -4548,7 +4547,7 @@ static bool ieee80211_prepare_and_rx_han
- static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
- struct ieee80211_sta *pubsta,
- struct sk_buff *skb,
-- struct napi_struct *napi)
-+ struct list_head *list)
- {
- struct ieee80211_local *local = hw_to_local(hw);
- struct ieee80211_sub_if_data *sdata;
-@@ -4563,7 +4562,7 @@ static void __ieee80211_rx_handle_packet
- memset(&rx, 0, sizeof(rx));
- rx.skb = skb;
- rx.local = local;
-- rx.napi = napi;
-+ rx.list = list;
-
- if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
- I802_DEBUG_INC(local->dot11ReceivedFragmentCount);
-@@ -4671,8 +4670,8 @@ static void __ieee80211_rx_handle_packet
- * This is the receive path handler. It is called by a low level driver when an
- * 802.11 MPDU is received from the hardware.
- */
--void ieee80211_rx_napi(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
-- struct sk_buff *skb, struct napi_struct *napi)
-+void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
-+ struct sk_buff *skb, struct list_head *list)
- {
- struct ieee80211_local *local = hw_to_local(hw);
- struct ieee80211_rate *rate = NULL;
-@@ -4764,36 +4763,53 @@ void ieee80211_rx_napi(struct ieee80211_
- status->rx_flags = 0;
-
- /*
-- * key references and virtual interfaces are protected using RCU
-- * and this requires that we are in a read-side RCU section during
-- * receive processing
-- */
-- rcu_read_lock();
--
-- /*
- * Frames with failed FCS/PLCP checksum are not returned,
- * all other frames are returned without radiotap header
- * if it was previously present.
- * Also, frames with less than 16 bytes are dropped.
- */
- skb = ieee80211_rx_monitor(local, skb, rate);
-- if (!skb) {
-- rcu_read_unlock();
-+ if (!skb)
- return;
-- }
-
- ieee80211_tpt_led_trig_rx(local,
- ((struct ieee80211_hdr *)skb->data)->frame_control,
- skb->len);
-
-- __ieee80211_rx_handle_packet(hw, pubsta, skb, napi);
--
-- rcu_read_unlock();
-+ __ieee80211_rx_handle_packet(hw, pubsta, skb, list);
-
- return;
- drop:
- kfree_skb(skb);
- }
-+EXPORT_SYMBOL(ieee80211_rx_list);
-+
-+void ieee80211_rx_napi(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
-+ struct sk_buff *skb, struct napi_struct *napi)
-+{
-+ struct sk_buff *tmp;
-+ LIST_HEAD(list);
-+
-+
-+ /*
-+ * key references and virtual interfaces are protected using RCU
-+ * and this requires that we are in a read-side RCU section during
-+ * receive processing
-+ */
-+ rcu_read_lock();
-+ ieee80211_rx_list(hw, pubsta, skb, &list);
-+ rcu_read_unlock();
-+
-+ if (!napi) {
-+ netif_receive_skb_list(&list);
-+ return;
-+ }
-+
-+ list_for_each_entry_safe(skb, tmp, &list, list) {
-+ skb_list_del_init(skb);
-+ napi_gro_receive(napi, skb);
-+ }
-+}
- EXPORT_SYMBOL(ieee80211_rx_napi);
-
- /* This is a version of the rx handler that can be called from hard irq
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sun, 26 Jul 2020 14:37:02 +0200
-Subject: [PATCH] net/fq_impl: use skb_get_hash instead of
- skb_get_hash_perturb
-
-This avoids unnecessary regenerating of the skb flow hash
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/include/net/fq.h
-+++ b/include/net/fq.h
-@@ -69,15 +69,6 @@ struct fq {
- struct list_head backlogs;
- spinlock_t lock;
- u32 flows_cnt;
--#if LINUX_VERSION_IS_GEQ(5,3,10) || \
-- LINUX_VERSION_IN_RANGE(4,19,83, 4,20,0) || \
-- LINUX_VERSION_IN_RANGE(4,14,153, 4,15,0) || \
-- LINUX_VERSION_IN_RANGE(4,9,200, 4,10,0) || \
-- LINUX_VERSION_IN_RANGE(4,4,200, 4,5,0)
-- siphash_key_t perturbation;
--#else
-- u32 perturbation;
--#endif
- u32 limit;
- u32 memory_limit;
- u32 memory_usage;
---- a/include/net/fq_impl.h
-+++ b/include/net/fq_impl.h
-@@ -108,15 +108,7 @@ begin:
-
- static u32 fq_flow_idx(struct fq *fq, struct sk_buff *skb)
- {
--#if LINUX_VERSION_IS_GEQ(5,3,10) || \
-- LINUX_VERSION_IN_RANGE(4,19,83, 4,20,0) || \
-- LINUX_VERSION_IN_RANGE(4,14,153, 4,15,0) || \
-- LINUX_VERSION_IN_RANGE(4,9,200, 4,10,0) || \
-- LINUX_VERSION_IN_RANGE(4,4,200, 4,5,0)
-- u32 hash = skb_get_hash_perturb(skb, &fq->perturbation);
--#else
-- u32 hash = skb_get_hash_perturb(skb, fq->perturbation);
--#endif
-+ u32 hash = skb_get_hash(skb);
-
- return reciprocal_scale(hash, fq->flows_cnt);
- }
-@@ -316,7 +308,6 @@ static int fq_init(struct fq *fq, int fl
- INIT_LIST_HEAD(&fq->backlogs);
- spin_lock_init(&fq->lock);
- fq->flows_cnt = max_t(u32, flows_cnt, 1);
-- get_random_bytes(&fq->perturbation, sizeof(fq->perturbation));
- fq->quantum = 300;
- fq->limit = 8192;
- fq->memory_limit = 16 << 20; /* 16 MBytes */
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sun, 26 Jul 2020 14:42:58 +0200
-Subject: [PATCH] mac80211: calculcate skb hash early when using itxq
-
-This avoids flow separation issues when using software encryption
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -3937,6 +3937,7 @@ void __ieee80211_subif_start_xmit(struct
- if (local->ops->wake_tx_queue) {
- u16 queue = __ieee80211_select_queue(sdata, sta, skb);
- skb_set_queue_mapping(skb, queue);
-+ skb_get_hash(skb);
- }
-
- if (sta) {
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 12 Aug 2020 17:04:22 +0200
-Subject: [PATCH] mac80211: use rate provided via status->rate on
- ieee80211_tx_status_ext for AQL
-
-Since ieee80211_tx_info does not have enough room to encode HE rates, HE
-drivers use status->rate to provide rate info.
-Store it in struct sta_info and use it for AQL.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/airtime.c
-+++ b/net/mac80211/airtime.c
-@@ -487,14 +487,61 @@ u32 ieee80211_calc_rx_airtime(struct iee
- }
- EXPORT_SYMBOL_GPL(ieee80211_calc_rx_airtime);
-
-+static bool ieee80211_fill_rate_info(struct ieee80211_hw *hw,
-+ struct ieee80211_rx_status *stat, u8 band,
-+ struct rate_info *ri)
-+{
-+ struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
-+ int i;
-+
-+ if (!ri || !sband)
-+ return false;
-+
-+ stat->bw = ri->bw;
-+ stat->nss = ri->nss;
-+ stat->rate_idx = ri->mcs;
-+
-+ if (ri->flags & RATE_INFO_FLAGS_HE_MCS)
-+ stat->encoding = RX_ENC_HE;
-+ else if (ri->flags & RATE_INFO_FLAGS_VHT_MCS)
-+ stat->encoding = RX_ENC_VHT;
-+ else if (ri->flags & RATE_INFO_FLAGS_MCS)
-+ stat->encoding = RX_ENC_HT;
-+ else
-+ stat->encoding = RX_ENC_LEGACY;
-+
-+ if (ri->flags & RATE_INFO_FLAGS_SHORT_GI)
-+ stat->enc_flags |= RX_ENC_FLAG_SHORT_GI;
-+
-+ stat->he_gi = ri->he_gi;
-+
-+ if (stat->encoding != RX_ENC_LEGACY)
-+ return true;
-+
-+ stat->rate_idx = 0;
-+ for (i = 0; i < sband->n_bitrates; i++) {
-+ if (ri->legacy != sband->bitrates[i].bitrate)
-+ continue;
-+
-+ stat->rate_idx = i;
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
- static u32 ieee80211_calc_tx_airtime_rate(struct ieee80211_hw *hw,
- struct ieee80211_tx_rate *rate,
-+ struct rate_info *ri,
- u8 band, int len)
- {
- struct ieee80211_rx_status stat = {
- .band = band,
- };
-
-+ if (ieee80211_fill_rate_info(hw, &stat, band, ri))
-+ goto out;
-+
- if (rate->idx < 0 || !rate->count)
- return 0;
-
-@@ -522,6 +569,7 @@ static u32 ieee80211_calc_tx_airtime_rat
- stat.encoding = RX_ENC_LEGACY;
- }
-
-+out:
- return ieee80211_calc_rx_airtime(hw, &stat, len);
- }
-
-@@ -536,7 +584,7 @@ u32 ieee80211_calc_tx_airtime(struct iee
- struct ieee80211_tx_rate *rate = &info->status.rates[i];
- u32 cur_duration;
-
-- cur_duration = ieee80211_calc_tx_airtime_rate(hw, rate,
-+ cur_duration = ieee80211_calc_tx_airtime_rate(hw, rate, NULL,
- info->band, len);
- if (!cur_duration)
- break;
-@@ -573,6 +621,7 @@ u32 ieee80211_calc_expected_tx_airtime(s
- struct sta_info *sta = container_of(pubsta, struct sta_info,
- sta);
- struct ieee80211_tx_rate *rate = &sta->tx_stats.last_rate;
-+ struct rate_info *ri = &sta->tx_stats.last_rate_info;
- u32 airtime;
-
- if (!(rate->flags & (IEEE80211_TX_RC_VHT_MCS |
-@@ -586,7 +635,7 @@ u32 ieee80211_calc_expected_tx_airtime(s
- * This will not be very accurate, but much better than simply
- * assuming un-aggregated tx.
- */
-- airtime = ieee80211_calc_tx_airtime_rate(hw, rate, band,
-+ airtime = ieee80211_calc_tx_airtime_rate(hw, rate, ri, band,
- ampdu ? len * 16 : len);
- if (ampdu)
- airtime /= 16;
---- a/net/mac80211/sta_info.h
-+++ b/net/mac80211/sta_info.h
-@@ -609,6 +609,7 @@ struct sta_info {
- u64 packets[IEEE80211_NUM_ACS];
- u64 bytes[IEEE80211_NUM_ACS];
- struct ieee80211_tx_rate last_rate;
-+ struct rate_info last_rate_info;
- u64 msdu[IEEE80211_NUM_TIDS + 1];
- } tx_stats;
- u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -1147,9 +1147,17 @@ 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;
- int retry_count;
- bool acked, noack_success;
-
-+ if (pubsta) {
-+ sta = container_of(pubsta, struct sta_info, sta);
-+
-+ if (status->rate)
-+ sta->tx_stats.last_rate_info = *status->rate;
-+ }
-+
- if (status->skb)
- return __ieee80211_tx_status(hw, status);
-
-@@ -1164,10 +1172,6 @@ void ieee80211_tx_status_ext(struct ieee
- noack_success = !!(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED);
-
- if (pubsta) {
-- struct sta_info *sta;
--
-- sta = container_of(pubsta, struct sta_info, sta);
--
- if (!acked && !noack_success)
- sta->status_stats.retry_failed++;
- sta->status_stats.retry_count += retry_count;
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 12 Aug 2020 17:06:12 +0200
-Subject: [PATCH] mac80211: factor out code to look up the average packet
- length duration for a rate
-
-This will be used to enhance AQL estimated aggregation length
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/airtime.c
-+++ b/net/mac80211/airtime.c
-@@ -405,18 +405,14 @@ ieee80211_calc_legacy_rate_duration(u16
- return duration;
- }
-
--u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw,
-- struct ieee80211_rx_status *status,
-- int len)
-+static u32 ieee80211_get_rate_duration(struct ieee80211_hw *hw,
-+ struct ieee80211_rx_status *status,
-+ u32 *overhead)
- {
-- struct ieee80211_supported_band *sband;
-- const struct ieee80211_rate *rate;
- bool sgi = status->enc_flags & RX_ENC_FLAG_SHORT_GI;
-- bool sp = status->enc_flags & RX_ENC_FLAG_SHORTPRE;
- int bw, streams;
- int group, idx;
- u32 duration;
-- bool cck;
-
- switch (status->bw) {
- case RATE_INFO_BW_20:
-@@ -437,20 +433,6 @@ u32 ieee80211_calc_rx_airtime(struct iee
- }
-
- switch (status->encoding) {
-- case RX_ENC_LEGACY:
-- if (WARN_ON_ONCE(status->band > NL80211_BAND_5GHZ))
-- return 0;
--
-- sband = hw->wiphy->bands[status->band];
-- if (!sband || status->rate_idx >= sband->n_bitrates)
-- return 0;
--
-- rate = &sband->bitrates[status->rate_idx];
-- cck = rate->flags & IEEE80211_RATE_MANDATORY_B;
--
-- return ieee80211_calc_legacy_rate_duration(rate->bitrate, sp,
-- cck, len);
--
- case RX_ENC_VHT:
- streams = status->nss;
- idx = status->rate_idx;
-@@ -477,13 +459,47 @@ u32 ieee80211_calc_rx_airtime(struct iee
-
- duration = airtime_mcs_groups[group].duration[idx];
- duration <<= airtime_mcs_groups[group].shift;
-+ *overhead = 36 + (streams << 2);
-+
-+ return duration;
-+}
-+
-+
-+u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw,
-+ struct ieee80211_rx_status *status,
-+ int len)
-+{
-+ struct ieee80211_supported_band *sband;
-+ u32 duration, overhead = 0;
-+
-+ if (status->encoding == RX_ENC_LEGACY) {
-+ const struct ieee80211_rate *rate;
-+ bool sp = status->enc_flags & RX_ENC_FLAG_SHORTPRE;
-+ bool cck;
-+
-+ if (WARN_ON_ONCE(status->band > NL80211_BAND_5GHZ))
-+ return 0;
-+
-+ sband = hw->wiphy->bands[status->band];
-+ if (!sband || status->rate_idx >= sband->n_bitrates)
-+ return 0;
-+
-+ rate = &sband->bitrates[status->rate_idx];
-+ cck = rate->flags & IEEE80211_RATE_MANDATORY_B;
-+
-+ return ieee80211_calc_legacy_rate_duration(rate->bitrate, sp,
-+ cck, len);
-+ }
-+
-+ duration = ieee80211_get_rate_duration(hw, status, &overhead);
-+ if (!duration)
-+ return 0;
-+
- duration *= len;
- duration /= AVG_PKT_SIZE;
- duration /= 1024;
-
-- duration += 36 + (streams << 2);
--
-- return duration;
-+ return duration + overhead;
- }
- EXPORT_SYMBOL_GPL(ieee80211_calc_rx_airtime);
-
-@@ -530,46 +546,57 @@ static bool ieee80211_fill_rate_info(str
- return false;
- }
-
--static u32 ieee80211_calc_tx_airtime_rate(struct ieee80211_hw *hw,
-- struct ieee80211_tx_rate *rate,
-- struct rate_info *ri,
-- u8 band, int len)
-+static int ieee80211_fill_rx_status(struct ieee80211_rx_status *stat,
-+ struct ieee80211_hw *hw,
-+ struct ieee80211_tx_rate *rate,
-+ struct rate_info *ri, u8 band, int len)
- {
-- struct ieee80211_rx_status stat = {
-- .band = band,
-- };
-+ memset(stat, 0, sizeof(*stat));
-+ stat->band = band;
-
-- if (ieee80211_fill_rate_info(hw, &stat, band, ri))
-- goto out;
-+ if (ieee80211_fill_rate_info(hw, stat, band, ri))
-+ return 0;
-
- if (rate->idx < 0 || !rate->count)
-- return 0;
-+ return -1;
-
- if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
-- stat.bw = RATE_INFO_BW_80;
-+ stat->bw = RATE_INFO_BW_80;
- else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-- stat.bw = RATE_INFO_BW_40;
-+ stat->bw = RATE_INFO_BW_40;
- else
-- stat.bw = RATE_INFO_BW_20;
-+ stat->bw = RATE_INFO_BW_20;
-
-- stat.enc_flags = 0;
-+ stat->enc_flags = 0;
- if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-- stat.enc_flags |= RX_ENC_FLAG_SHORTPRE;
-+ stat->enc_flags |= RX_ENC_FLAG_SHORTPRE;
- if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
-- stat.enc_flags |= RX_ENC_FLAG_SHORT_GI;
-+ stat->enc_flags |= RX_ENC_FLAG_SHORT_GI;
-
-- stat.rate_idx = rate->idx;
-+ stat->rate_idx = rate->idx;
- if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
-- stat.encoding = RX_ENC_VHT;
-- stat.rate_idx = ieee80211_rate_get_vht_mcs(rate);
-- stat.nss = ieee80211_rate_get_vht_nss(rate);
-+ stat->encoding = RX_ENC_VHT;
-+ stat->rate_idx = ieee80211_rate_get_vht_mcs(rate);
-+ stat->nss = ieee80211_rate_get_vht_nss(rate);
- } else if (rate->flags & IEEE80211_TX_RC_MCS) {
-- stat.encoding = RX_ENC_HT;
-+ stat->encoding = RX_ENC_HT;
- } else {
-- stat.encoding = RX_ENC_LEGACY;
-+ stat->encoding = RX_ENC_LEGACY;
- }
-
--out:
-+ return 0;
-+}
-+
-+static u32 ieee80211_calc_tx_airtime_rate(struct ieee80211_hw *hw,
-+ struct ieee80211_tx_rate *rate,
-+ struct rate_info *ri,
-+ u8 band, int len)
-+{
-+ struct ieee80211_rx_status stat;
-+
-+ if (ieee80211_fill_rx_status(&stat, hw, rate, ri, band, len))
-+ return 0;
-+
- return ieee80211_calc_rx_airtime(hw, &stat, len);
- }
-
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 12 Aug 2020 17:07:10 +0200
-Subject: [PATCH] mac80211: improve AQL aggregation estimation for low data
- rates
-
-Links with low data rates use much smaller aggregates and are much more
-sensitive to latency added by bufferbloat.
-Tune the assumed aggregation length based on the tx rate duration.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/airtime.c
-+++ b/net/mac80211/airtime.c
-@@ -647,27 +647,41 @@ u32 ieee80211_calc_expected_tx_airtime(s
- if (pubsta) {
- struct sta_info *sta = container_of(pubsta, struct sta_info,
- sta);
-+ struct ieee80211_rx_status stat;
- struct ieee80211_tx_rate *rate = &sta->tx_stats.last_rate;
- struct rate_info *ri = &sta->tx_stats.last_rate_info;
-- u32 airtime;
-+ u32 duration, overhead;
-+ u8 agg_shift;
-
-- if (!(rate->flags & (IEEE80211_TX_RC_VHT_MCS |
-- IEEE80211_TX_RC_MCS)))
-- ampdu = false;
-+ if (ieee80211_fill_rx_status(&stat, hw, rate, ri, band, len))
-+ return 0;
-
-+ if (stat.encoding == RX_ENC_LEGACY || !ampdu)
-+ return ieee80211_calc_rx_airtime(hw, &stat, len);
-+
-+ duration = ieee80211_get_rate_duration(hw, &stat, &overhead);
- /*
- * Assume that HT/VHT transmission on any AC except VO will
- * use aggregation. Since we don't have reliable reporting
-- * of aggregation length, assume an average of 16.
-+ * of aggregation length, assume an average size based on the
-+ * tx rate.
- * This will not be very accurate, but much better than simply
-- * assuming un-aggregated tx.
-+ * assuming un-aggregated tx in all cases.
- */
-- airtime = ieee80211_calc_tx_airtime_rate(hw, rate, ri, band,
-- ampdu ? len * 16 : len);
-- if (ampdu)
-- airtime /= 16;
-+ if (duration > 400) /* <= VHT20 MCS2 1S */
-+ agg_shift = 1;
-+ else if (duration > 250) /* <= VHT20 MCS3 1S or MCS1 2S */
-+ agg_shift = 2;
-+ else if (duration > 150) /* <= VHT20 MCS5 1S or MCS3 2S */
-+ agg_shift = 3;
-+ else
-+ agg_shift = 4;
-+
-+ duration *= len;
-+ duration /= AVG_PKT_SIZE;
-+ duration /= 1024;
-
-- return airtime;
-+ return duration + (overhead >> agg_shift);
- }
-
- if (!conf)
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-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 <nbd@nbd.name>
----
-
---- 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)
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
-@@ -4189,6 +4189,8 @@ static void ieee80211_8023_xmit(struct i
+@@ -4186,6 +4186,8 @@ static void ieee80211_8023_xmit(struct i
bool authorized = false;
bool multicast;
unsigned char *ra = ehdr->h_dest;
if (IS_ERR(sta) || (sta && !sta->uploaded))
sta = NULL;
-@@ -4226,6 +4228,22 @@ static void ieee80211_8023_xmit(struct i
+@@ -4223,6 +4225,22 @@ static void ieee80211_8023_xmit(struct i
memset(info, 0, sizeof(*info));
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
-@@ -4184,88 +4184,47 @@ static void ieee80211_8023_xmit(struct i
+@@ -4181,88 +4181,47 @@ static void ieee80211_8023_xmit(struct i
struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(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
+@@ -4283,6 +4242,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 sta_info *sta;
if (WARN_ON(!sdata->hw_80211_encap)) {
-@@ -4302,6 +4262,10 @@ netdev_tx_t ieee80211_subif_start_xmit_8
+@@ -4299,6 +4259,10 @@ netdev_tx_t ieee80211_subif_start_xmit_8
if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
kfree_skb(skb);
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
-@@ -4185,6 +4185,7 @@ static void ieee80211_8023_xmit(struct i
+@@ -4182,6 +4182,7 @@ static void ieee80211_8023_xmit(struct i
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_local *local = sdata->local;
struct tid_ampdu_tx *tid_tx;
u8 tid;
-@@ -4233,6 +4234,10 @@ static void ieee80211_8023_xmit(struct i
+@@ -4230,6 +4231,10 @@ static void ieee80211_8023_xmit(struct i
info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP;
info->control.vif = &sdata->vif;
--- 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
+@@ -4304,6 +4304,35 @@ static int ath11k_set_he_mu_sounding_mod
return ret;
}
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
+@@ -4313,7 +4342,6 @@ static int ath11k_mac_op_add_interface(s
struct vdev_create_params vdev_param = {0};
struct peer_create_params peer_param;
u32 param_id, param_value;
u16 nss;
int i;
int ret;
-@@ -4253,30 +4281,7 @@ static int ath11k_mac_op_add_interface(s
+@@ -4407,30 +4435,7 @@ static int ath11k_mac_op_add_interface(s
list_add(&arvif->list, &ar->arvifs);
spin_unlock_bh(&ar->data_lock);
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
+@@ -5753,6 +5758,7 @@ static const struct ieee80211_ops ath11k
.reconfig_complete = ath11k_mac_op_reconfig_complete,
.add_interface = ath11k_mac_op_add_interface,
.remove_interface = ath11k_mac_op_remove_interface,
.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
+@@ -6034,6 +6040,7 @@ static int __ath11k_mac_register(struct
ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);
ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW);
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -1603,6 +1603,21 @@ enum ieee80211_vif_flags {
+@@ -1606,6 +1606,21 @@ enum ieee80211_vif_flags {
IEEE80211_VIF_GET_NOA_UPDATE = BIT(3),
};
/**
* struct ieee80211_vif - per-interface data
*
-@@ -1623,6 +1638,11 @@ enum ieee80211_vif_flags {
+@@ -1626,6 +1641,11 @@ enum ieee80211_vif_flags {
* these need to be set (or cleared) when the interface is added
* or, if supported by the driver, the interface type is changed
* at runtime, mac80211 will never touch this field
* @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 {
+@@ -1662,6 +1682,7 @@ struct ieee80211_vif {
struct ieee80211_chanctx_conf __rcu *chanctx_conf;
u32 driver_flags;
#ifdef CPTCFG_MAC80211_DEBUGFS
struct dentry *debugfs_dir;
-@@ -2325,6 +2346,9 @@ struct ieee80211_txq {
+@@ -2328,6 +2349,9 @@ struct ieee80211_txq {
* aggregating MPDUs with the same keyid, allowing mac80211 to keep Tx
* A-MPDU sessions active while rekeying with Extended Key ID.
*
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
*/
enum ieee80211_hw_flags {
-@@ -2377,6 +2401,7 @@ enum ieee80211_hw_flags {
+@@ -2380,6 +2404,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_SUPPORTS_MULTI_BSSID,
IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID,
IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT,
/* keep last, obviously */
NUM_IEEE80211_HW_FLAGS
-@@ -3811,6 +3836,8 @@ enum ieee80211_reconfig_type {
+@@ -3814,6 +3839,8 @@ enum ieee80211_reconfig_type {
* @set_tid_config: Apply TID specific configurations. This callback may sleep.
* @reset_tid_config: Reset TID specific configuration for the peer.
* This callback may sleep.
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
-@@ -4122,6 +4149,8 @@ struct ieee80211_ops {
+@@ -4125,6 +4152,8 @@ struct ieee80211_ops {
int (*reset_tid_config)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u8 tids);
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
-@@ -1385,4 +1385,19 @@ static inline int drv_reset_tid_config(s
+@@ -1384,4 +1384,19 @@ static inline int drv_reset_tid_config(s
return ret;
}
#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 {
+@@ -993,8 +993,6 @@ struct ieee80211_sub_if_data {
} debugfs;
#endif
/* must be last, dynamically sized area in this! */
struct ieee80211_vif vif;
};
-@@ -1769,6 +1767,7 @@ void ieee80211_del_virtual_monitor(struc
+@@ -1772,6 +1770,7 @@ void ieee80211_del_virtual_monitor(struc
bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata,
bool update_bss);
res = ieee80211_check_queues(sdata,
ieee80211_vif_type_p2p(&sdata->vif));
if (res)
-@@ -1286,61 +1371,6 @@ static const struct net_device_ops ieee8
+@@ -1293,61 +1378,6 @@ static const struct net_device_ops ieee8
};
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(
+@@ -1378,6 +1408,32 @@ static void ieee80211_if_setup_no_queue(
#endif
}
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
+@@ -1560,7 +1616,6 @@ static void ieee80211_setup_sdata(struct
sdata->vif.bss_conf.txpower = INT_MIN; /* unset */
sdata->noack_map = 0;
/* only monitor/p2p-device differ */
if (sdata->dev) {
-@@ -1688,6 +1743,7 @@ static int ieee80211_runtime_change_ifty
+@@ -1695,6 +1750,7 @@ static int ieee80211_runtime_change_ifty
ieee80211_teardown_sdata(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
+@@ -1707,6 +1763,7 @@ static int ieee80211_runtime_change_ifty
ieee80211_check_queues(sdata, type);
ieee80211_setup_sdata(sdata, type);
- */
- if (sdata->hw_80211_encap)
- return -EINVAL;
-- /* Fall through */
+- fallthrough;
-
case WLAN_CIPHER_SUITE_AES_CMAC:
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
-@@ -2733,6 +2733,12 @@ TRACE_EVENT(drv_get_ftm_responder_stats,
+@@ -2734,6 +2734,12 @@ TRACE_EVENT(drv_get_ftm_responder_stats,
)
);
#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
+@@ -4178,11 +4178,10 @@ static bool ieee80211_tx_8023(struct iee
static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
struct net_device *dev, struct sta_info *sta,
struct tid_ampdu_tx *tid_tx;
u8 tid;
-@@ -4234,7 +4233,6 @@ static void ieee80211_8023_xmit(struct i
+@@ -4231,7 +4230,6 @@ static void ieee80211_8023_xmit(struct i
info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP;
info->control.vif = &sdata->vif;
if (key)
info->control.hw_key = &key->conf;
-@@ -4251,12 +4249,9 @@ netdev_tx_t ieee80211_subif_start_xmit_8
+@@ -4248,12 +4246,9 @@ netdev_tx_t ieee80211_subif_start_xmit_8
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ethhdr *ehdr = (struct ethhdr *)skb->data;
if (unlikely(skb->len < ETH_HLEN)) {
kfree_skb(skb);
-@@ -4265,15 +4260,26 @@ netdev_tx_t ieee80211_subif_start_xmit_8
+@@ -4262,15 +4257,26 @@ netdev_tx_t ieee80211_subif_start_xmit_8
rcu_read_lock();
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
+@@ -897,7 +885,8 @@ void ieee80211_tx_monitor(struct ieee802
}
static void __ieee80211_tx_status(struct ieee80211_hw *hw,
{
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
+@@ -906,8 +895,6 @@ static void __ieee80211_tx_status(struct
struct sta_info *sta;
__le16 fc;
struct ieee80211_supported_band *sband;
bool send_to_cooked;
bool acked;
bool noack_success;
-@@ -918,8 +905,6 @@ static void __ieee80211_tx_status(struct
+@@ -916,8 +903,6 @@ static void __ieee80211_tx_status(struct
int tid = IEEE80211_NUM_TIDS;
u16 tx_time_est;
sband = local->hw.wiphy->bands[info->band];
fc = hdr->frame_control;
-@@ -996,24 +981,14 @@ static void __ieee80211_tx_status(struct
+@@ -994,24 +979,14 @@ static void __ieee80211_tx_status(struct
if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
ieee80211_handle_filtered_frame(local, sta, skb);
return;
if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && acked)
ieee80211_frame_acked(sta, skb);
-@@ -1038,20 +1013,6 @@ static void __ieee80211_tx_status(struct
+@@ -1036,20 +1011,6 @@ static void __ieee80211_tx_status(struct
true);
ieee80211_info_set_tx_time_est(info, 0);
}
}
/* SNMP counters
-@@ -1135,7 +1096,7 @@ void ieee80211_tx_status(struct ieee8021
+@@ -1133,7 +1094,7 @@ void ieee80211_tx_status(struct ieee8021
if (sta)
status.sta = &sta->sta;
rcu_read_unlock();
}
EXPORT_SYMBOL(ieee80211_tx_status);
-@@ -1148,7 +1109,7 @@ void ieee80211_tx_status_ext(struct ieee
+@@ -1146,7 +1107,7 @@ void ieee80211_tx_status_ext(struct ieee
struct ieee80211_sta *pubsta = status->sta;
struct ieee80211_supported_band *sband;
struct sta_info *sta;
bool acked, noack_success;
if (pubsta) {
-@@ -1158,13 +1119,7 @@ void ieee80211_tx_status_ext(struct ieee
+@@ -1156,13 +1117,7 @@ void ieee80211_tx_status_ext(struct ieee
sta->tx_stats.last_rate_info = *status->rate;
}
sband = hw->wiphy->bands[info->band];
-@@ -1176,20 +1131,30 @@ void ieee80211_tx_status_ext(struct ieee
+@@ -1174,20 +1129,30 @@ void ieee80211_tx_status_ext(struct ieee
sta->status_stats.retry_failed++;
sta->status_stats.retry_count += retry_count;
}
rate_control_tx_status(local, sband, status);
-@@ -1197,6 +1162,10 @@ void ieee80211_tx_status_ext(struct ieee
+@@ -1195,6 +1160,10 @@ void ieee80211_tx_status_ext(struct ieee
ieee80211s_update_metric(local, sta, status);
}
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
-@@ -997,12 +997,6 @@ static void __ieee80211_tx_status(struct
+@@ -995,12 +995,6 @@ static void __ieee80211_tx_status(struct
ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data,
acked, info->status.tx_time);
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
-@@ -2045,8 +2045,6 @@ void ieee80211_dynamic_ps_timer(struct t
+@@ -2047,8 +2047,6 @@ void ieee80211_dynamic_ps_timer(struct t
void ieee80211_send_nullfunc(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
bool powersave);
}
static void ieee80211_mlme_send_probe_req(struct ieee80211_sub_if_data *sdata,
-@@ -3600,8 +3575,8 @@ static bool ieee80211_assoc_success(stru
+@@ -3605,8 +3580,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.
*/
ret = true;
out:
-@@ -4569,10 +4544,26 @@ static void ieee80211_sta_conn_mon_timer
+@@ -4577,10 +4552,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;
sta->rx_stats.fragments++;
u64_stats_update_begin(&rx->sta->rx_stats.syncp);
-@@ -4149,7 +4146,6 @@ void ieee80211_check_fast_rx(struct sta_
+@@ -4153,7 +4150,6 @@ void ieee80211_check_fast_rx(struct sta_
fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr2);
fastrx.expected_ds_bits = 0;
} else {
fastrx.da_offs = offsetof(struct ieee80211_hdr, addr1);
fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr3);
fastrx.expected_ds_bits =
-@@ -4379,11 +4375,6 @@ static bool ieee80211_invoke_fast_rx(str
+@@ -4383,11 +4379,6 @@ static bool ieee80211_invoke_fast_rx(str
pskb_trim(skb, skb->len - fast_rx->icv_len))
goto drop;
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
+@@ -1225,9 +1225,6 @@ void ieee80211_tx_status_8023(struct iee
sta->status_stats.retry_count += retry_count;
if (ieee80211_hw_check(hw, REPORTS_TX_ACK_STATUS)) {
--- 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
+@@ -3898,7 +3898,7 @@ static int ath11k_mac_mgmt_tx_wmi(struct
return -ENOSPC;
info = IEEE80211_SKB_CB(skb);
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
+@@ -4025,7 +4025,7 @@ static void ath11k_mac_op_tx(struct ieee
bool is_prb_rsp;
int ret;
+ * @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.
+ * @IEEE80211_TX_CTRL_NO_SEQNO: Do not overwrite the sequence number that
+ * has already been assigned to this frame.
*
- * These flags are used in tx_info->control.flags.
- */
-@@ -835,7 +835,7 @@ enum mac80211_tx_control_flags {
+@@ -837,7 +837,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),
+ IEEE80211_TX_CTRL_NO_SEQNO = BIT(7),
};
- /*
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -212,7 +212,7 @@ static void prepare_frame_for_deferred_t
}
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
-@@ -2897,7 +2897,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
+@@ -2901,7 +2901,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));
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
+@@ -531,7 +531,7 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
info->control.jiffies = jiffies;
info->control.vif = &tx->sdata->vif;
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
+@@ -1134,7 +1134,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_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
+@@ -1179,7 +1179,7 @@ ieee80211_tx_prepare(struct ieee80211_su
* we are doing the needed processing, so remove the flag
* now.
*/
hdr = (struct ieee80211_hdr *) skb->data;
-@@ -1256,7 +1256,7 @@ static struct txq_info *ieee80211_get_tx
+@@ -1258,7 +1258,7 @@ static struct txq_info *ieee80211_get_tx
(info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
return NULL;
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:
+@@ -3637,7 +3637,7 @@ begin:
else
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
goto encap_out;
if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
-@@ -4230,7 +4230,7 @@ static void ieee80211_8023_xmit(struct i
+@@ -4227,7 +4227,7 @@ static void ieee80211_8023_xmit(struct i
sdata = container_of(sdata->bss,
struct ieee80211_sub_if_data, u.ap);
info->control.vif = &sdata->vif;
if (key)
-@@ -4355,7 +4355,7 @@ static bool ieee80211_tx_pending_skb(str
+@@ -4352,7 +4352,7 @@ static bool ieee80211_tx_pending_skb(str
sdata = vif_to_sdata(info->control.vif);
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
+@@ -4360,7 +4360,7 @@ static bool ieee80211_tx_pending_skb(str
}
info->band = chanctx_conf->def.chan->band;
- result = ieee80211_tx(sdata, NULL, skb, true, 0);
+ result = ieee80211_tx(sdata, NULL, skb, true);
- } 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)) {
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
-@@ -903,7 +903,6 @@ static void __ieee80211_tx_status(struct
+@@ -901,7 +901,6 @@ static void __ieee80211_tx_status(struct
struct ieee80211_bar *bar;
int shift = 0;
int tid = IEEE80211_NUM_TIDS;
sband = local->hw.wiphy->bands[info->band];
fc = hdr->frame_control;
-@@ -996,17 +995,6 @@ static void __ieee80211_tx_status(struct
+@@ -994,17 +993,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);
}
/* SNMP counters
-@@ -1102,9 +1090,11 @@ void ieee80211_tx_status_ext(struct ieee
+@@ -1100,9 +1088,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;
if (pubsta) {
sta = container_of(pubsta, struct sta_info, sta);
-@@ -1156,7 +1146,18 @@ void ieee80211_tx_status_ext(struct ieee
+@@ -1154,7 +1144,18 @@ void ieee80211_tx_status_ext(struct ieee
ieee80211s_update_metric(local, sta, status);
}
return __ieee80211_tx_status(hw, status, rates_idx,
retry_count);
-@@ -1171,6 +1172,12 @@ void ieee80211_tx_status_ext(struct ieee
+@@ -1169,6 +1170,12 @@ void ieee80211_tx_status_ext(struct ieee
} else {
I802_DEBUG_INC(local->dot11FailedCount);
}
}
EXPORT_SYMBOL(ieee80211_tx_status_ext);
-@@ -1197,66 +1204,23 @@ void ieee80211_tx_status_8023(struct iee
+@@ -1195,66 +1202,23 @@ void ieee80211_tx_status_8023(struct iee
struct ieee80211_vif *vif,
struct sk_buff *skb)
{
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
-@@ -1103,6 +1103,21 @@ void ieee80211_tx_status_ext(struct ieee
+@@ -1101,6 +1101,21 @@ void ieee80211_tx_status_ext(struct ieee
sta->tx_stats.last_rate_info = *status->rate;
}
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
+@@ -1144,17 +1159,6 @@ void ieee80211_tx_status_ext(struct ieee
ieee80211s_update_metric(local, sta, status);
}
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
+@@ -1171,6 +1175,7 @@ void ieee80211_tx_status_ext(struct ieee
I802_DEBUG_INC(local->dot11FailedCount);
}
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -1092,12 +1092,14 @@ ieee80211_info_get_tx_time_est(struct ie
+@@ -1095,12 +1095,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
/**
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
-@@ -1053,7 +1053,10 @@ static void __ieee80211_tx_status(struct
+@@ -1051,7 +1051,10 @@ static void __ieee80211_tx_status(struct
* with this test...
*/
if (!local->monitors && (!send_to_cooked || !local->cooked_mntrs)) {
return;
}
-@@ -1182,7 +1185,10 @@ free:
+@@ -1180,7 +1183,10 @@ free:
return;
ieee80211_report_used_skb(local, skb, false);
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -3840,6 +3840,8 @@ enum ieee80211_reconfig_type {
+@@ -3843,6 +3843,8 @@ enum ieee80211_reconfig_type {
* 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,
-@@ -4153,6 +4155,8 @@ struct ieee80211_ops {
+@@ -4156,6 +4158,8 @@ struct ieee80211_ops {
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
-@@ -1694,6 +1694,7 @@ static int ieee80211_change_station(stru
+@@ -1696,6 +1696,7 @@ static int ieee80211_change_station(stru
rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
__ieee80211_check_fast_rx_iface(vlansdata);
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
+@@ -1399,4 +1399,18 @@ static inline void drv_update_vif_offloa
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
+@@ -3523,6 +3523,9 @@ static bool ieee80211_assoc_success(stru
goto out;
}
/*
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
-@@ -2739,6 +2739,33 @@ DEFINE_EVENT(local_sdata_addr_evt, drv_u
+@@ -2740,6 +2740,33 @@ DEFINE_EVENT(local_sdata_addr_evt, drv_u
TP_ARGS(local, sdata)
);
bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
{
-@@ -349,6 +348,511 @@ static int ieee80211_check_queues(struct
+@@ -349,6 +348,518 @@ static int ieee80211_check_queues(struct
return 0;
}
+ case NL80211_IFTYPE_P2P_DEVICE:
+ /* relies on synchronize_rcu() below */
+ RCU_INIT_POINTER(local->p2p_sdata, NULL);
-+ /* fall through */
++ fallthrough;
+ default:
+ cancel_work_sync(&sdata->work);
+ /*
+ if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
+ break;
+
-+ /* fall through */
++ fallthrough;
+ default:
+ if (going_down)
+ drv_remove_interface(local, sdata);
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = sdata->local;
++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr;
-+ struct ieee80211_radiotap_header *rtap = (void *)skb->data;
++ int len_rthdr;
+
+ if (local->hw.queues < IEEE80211_NUM_ACS)
+ return 0;
+
-+ if (skb->len < 4 ||
-+ skb->len < le16_to_cpu(rtap->it_len) + 2 /* frame control */)
++ /* reset flags and info before parsing radiotap header */
++ memset(info, 0, sizeof(*info));
++
++ if (!ieee80211_parse_tx_radiotap(skb, dev))
+ return 0; /* doesn't matter, frame will be dropped */
+
-+ hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
++ len_rthdr = ieee80211_get_radiotap_len(skb->data);
++ hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
++ if (skb->len < len_rthdr + 2 ||
++ skb->len < len_rthdr + ieee80211_hdrlen(hdr->frame_control))
++ return 0; /* doesn't matter, frame will be dropped */
+
+ return ieee80211_select_queue_80211(sdata, skb, hdr);
+}
static bool ieee80211_iftype_supports_encap_offload(enum nl80211_iftype iftype)
{
switch (iftype) {
-@@ -389,6 +893,31 @@ static bool ieee80211_set_sdata_offload_
+@@ -389,6 +900,31 @@ static bool ieee80211_set_sdata_offload_
return true;
}
static void ieee80211_recalc_sdata_offload(struct ieee80211_sub_if_data *sdata)
{
-@@ -866,511 +1395,6 @@ int ieee80211_do_open(struct wireless_de
+@@ -866,518 +1402,6 @@ int ieee80211_do_open(struct wireless_de
return res;
}
- case NL80211_IFTYPE_P2P_DEVICE:
- /* relies on synchronize_rcu() below */
- RCU_INIT_POINTER(local->p2p_sdata, NULL);
-- /* fall through */
+- fallthrough;
- default:
- cancel_work_sync(&sdata->work);
- /*
- if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
- break;
-
-- /* fall through */
+- fallthrough;
- default:
- if (going_down)
- drv_remove_interface(local, sdata);
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct ieee80211_local *local = sdata->local;
+- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hdr *hdr;
-- struct ieee80211_radiotap_header *rtap = (void *)skb->data;
+- int len_rthdr;
-
- if (local->hw.queues < IEEE80211_NUM_ACS)
- return 0;
-
-- if (skb->len < 4 ||
-- skb->len < le16_to_cpu(rtap->it_len) + 2 /* frame control */)
+- /* reset flags and info before parsing radiotap header */
+- memset(info, 0, sizeof(*info));
+-
+- if (!ieee80211_parse_tx_radiotap(skb, dev))
- return 0; /* doesn't matter, frame will be dropped */
-
-- hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
+- len_rthdr = ieee80211_get_radiotap_len(skb->data);
+- hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
+- if (skb->len < len_rthdr + 2 ||
+- skb->len < len_rthdr + ieee80211_hdrlen(hdr->frame_control))
+- return 0; /* doesn't matter, frame will be dropped */
-
- return ieee80211_select_queue_80211(sdata, skb, hdr);
-}
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(
+@@ -1408,32 +1432,6 @@ static void ieee80211_if_setup_no_queue(
#endif
}
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-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 <nbd@nbd.name>
----
-
---- 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)
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-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 <nbd@nbd.name>
----
-
---- 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;
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
-@@ -991,10 +991,6 @@ static void __ieee80211_tx_status(struct
+@@ -989,10 +989,6 @@ static void __ieee80211_tx_status(struct
if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && acked)
ieee80211_frame_acked(sta, skb);
}
/* SNMP counters
-@@ -1129,11 +1125,18 @@ void ieee80211_tx_status_ext(struct ieee
+@@ -1127,11 +1123,18 @@ void ieee80211_tx_status_ext(struct ieee
noack_success = !!(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED);
if (pubsta) {
if (acked) {
sta->status_stats.last_ack = jiffies;
-@@ -1143,6 +1146,11 @@ void ieee80211_tx_status_ext(struct ieee
+@@ -1141,6 +1144,11 @@ void ieee80211_tx_status_ext(struct ieee
/* Track when last packet was ACKed */
sta->status_stats.last_pkt_time = jiffies;
ieee80211_free_txskb(&local->hw, skb);
return;
}
-@@ -924,15 +925,6 @@ static void __ieee80211_tx_status(struct
+@@ -922,15 +923,6 @@ static void __ieee80211_tx_status(struct
ieee80211_mpsp_trigger_process(
ieee80211_get_qos_ctl(hdr), sta, true, acked);
if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL) &&
(ieee80211_is_data(hdr->frame_control)) &&
(rates_idx != -1))
-@@ -1159,6 +1151,12 @@ void ieee80211_tx_status_ext(struct ieee
+@@ -1157,6 +1149,12 @@ void ieee80211_tx_status_ext(struct ieee
-info->status.ack_signal);
}
} else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 11 Nov 2020 19:17:44 +0100
-Subject: [PATCH] mac80211: minstrel: remove deferred sampling code
-
-Deferring sampling attempts to the second stage has some bad interactions
-with drivers that process the rate table in hardware and use the probe flag
-to indicate probing packets (e.g. most mt76 drivers). On affected drivers
-it can lead to probing not working at all.
-
-If the link conditions turn worse, it might not be such a good idea to
-do a lot of sampling for lower rates in this case.
-
-Fix this by simply skipping the sample attempt instead of deferring it,
-but keep the checks that would allow it to be sampled if it was skipped
-too often, but only if it has less than 95% success probability.
-
-Also ensure that IEEE80211_TX_CTL_RATE_CTRL_PROBE is set for all probing
-packets.
-
-Cc: stable@vger.kernel.org
-Fixes: cccf129f820e ("mac80211: add the 'minstrel' rate control algorithm")
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rc80211_minstrel.c
-+++ b/net/mac80211/rc80211_minstrel.c
-@@ -287,12 +287,6 @@ minstrel_tx_status(void *priv, struct ie
- mi->r[ndx].stats.success += success;
- }
-
-- if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0))
-- mi->sample_packets++;
--
-- if (mi->sample_deferred > 0)
-- mi->sample_deferred--;
--
- if (time_after(jiffies, mi->last_stats_update +
- mp->update_interval / (mp->new_avg ? 2 : 1)))
- minstrel_update_stats(mp, mi);
-@@ -367,7 +361,7 @@ minstrel_get_rate(void *priv, struct iee
- return;
-
- delta = (mi->total_packets * sampling_ratio / 100) -
-- (mi->sample_packets + mi->sample_deferred / 2);
-+ mi->sample_packets;
-
- /* delta < 0: no sampling required */
- prev_sample = mi->prev_sample;
-@@ -376,7 +370,6 @@ minstrel_get_rate(void *priv, struct iee
- return;
-
- if (mi->total_packets >= 10000) {
-- mi->sample_deferred = 0;
- mi->sample_packets = 0;
- mi->total_packets = 0;
- } else if (delta > mi->n_rates * 2) {
-@@ -401,19 +394,8 @@ minstrel_get_rate(void *priv, struct iee
- * rate sampling method should be used.
- * Respect such rates that are not sampled for 20 interations.
- */
-- if (mrr_capable &&
-- msr->perfect_tx_time > mr->perfect_tx_time &&
-- msr->stats.sample_skipped < 20) {
-- /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
-- * packets that have the sampling rate deferred to the
-- * second MRR stage. Increase the sample counter only
-- * if the deferred sample rate was actually used.
-- * Use the sample_deferred counter to make sure that
-- * the sampling is not done in large bursts */
-- info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
-- rate++;
-- mi->sample_deferred++;
-- } else {
-+ if (msr->perfect_tx_time < mr->perfect_tx_time ||
-+ msr->stats.sample_skipped >= 20) {
- if (!msr->sample_limit)
- return;
-
-@@ -433,6 +415,7 @@ minstrel_get_rate(void *priv, struct iee
-
- rate->idx = mi->r[ndx].rix;
- rate->count = minstrel_get_retry_count(&mi->r[ndx], info);
-+ info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
- }
-
-
---- a/net/mac80211/rc80211_minstrel.h
-+++ b/net/mac80211/rc80211_minstrel.h
-@@ -126,7 +126,6 @@ struct minstrel_sta_info {
- u8 max_prob_rate;
- unsigned int total_packets;
- unsigned int sample_packets;
-- int sample_deferred;
-
- unsigned int sample_row;
- unsigned int sample_column;
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 11 Nov 2020 19:25:39 +0100
-Subject: [PATCH] mac80211: minstrel: fix tx status processing corner case
-
-Some drivers fill the status rate list without setting the rate index after
-the final rate to -1. minstrel_ht already deals with this, but minstrel
-doesn't, which causes it to get stuck at the lowest rate on these drivers.
-
-Fix this by checking the count as well.
-
-Cc: stable@vger.kernel.org
-Fixes: cccf129f820e ("mac80211: add the 'minstrel' rate control algorithm")
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rc80211_minstrel.c
-+++ b/net/mac80211/rc80211_minstrel.c
-@@ -274,7 +274,7 @@ minstrel_tx_status(void *priv, struct ie
- success = !!(info->flags & IEEE80211_TX_STAT_ACK);
-
- for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
-- if (ar[i].idx < 0)
-+ if (ar[i].idx < 0 || !ar[i].count)
- break;
-
- ndx = rix_to_ndx(mi, ar[i].idx);
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
-@@ -657,7 +657,7 @@ ieee80211_tx_h_select_key(struct ieee802
+@@ -658,7 +658,7 @@ ieee80211_tx_h_select_key(struct ieee802
if (!skip_hw && tx->key &&
tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
info->control.hw_key = &tx->key->conf;
- if (!mi->avg_ampdu_len)
- return AVG_AMPDU_SIZE;
+ int duration;
-
-- return MINSTREL_TRUNC(mi->avg_ampdu_len);
++
+ if (mi->avg_ampdu_len)
+ return MINSTREL_TRUNC(mi->avg_ampdu_len);
+
+ return 1;
+
+ duration = minstrel_get_duration(mi->max_tp_rate[0]);
-+
+
+- return MINSTREL_TRUNC(mi->avg_ampdu_len);
+ if (duration > 400 * 1000)
+ return 2;
+
+ if (!rate)
return;
- }
-
+-
- i = 0;
- if (n_rates > 1) {
- random = prandom_u32();
- i = random % n_rates;
- }
- probe_rate = rates[i];
--
+
-out:
- mi->sample_rate = probe_rate;
+ mi->sample_rate = rate;
-
- if (!(mi->supported[sample_group] & BIT(sample_idx)))
- return -1;
--
++ u8 seq;
+
- mrs = &mg->rates[sample_idx];
- sample_idx += MI_RATE(sample_group, 0);
-
- tp_rate1 = mi->max_tp_rate[0];
-+ u8 seq;
-
+-
- /* Set tp_rate2 to the second highest max_tp_rate */
- if (minstrel_get_duration(mi->max_tp_rate[0]) >
- minstrel_get_duration(mi->max_tp_rate[1])) {
- else
- sample_idx = minstrel_get_sample_rate(mp, mi);
+ return;
-
-- if (sample_idx < 0)
++
+ if (mp->hw->max_rates == 1 && mp->sample_switch &&
+ (mi->total_packets_cur >= SAMPLE_SWITCH_THR ||
+ mp->sample_switch == 1))
+
+ if (time_is_before_jiffies(mi->sample_time))
+ return;
-+
+
+- if (sample_idx < 0)
+ mi->sample_time = jiffies + MINSTREL_SAMPLE_INTERVAL;
+ sample_idx = minstrel_ht_get_sample_rate(mp, mi);
+ if (!sample_idx)
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
-@@ -3610,6 +3610,7 @@ struct mgmt_frame_regs {
+@@ -3637,6 +3637,7 @@ struct mgmt_frame_regs {
* (as advertised by the nl80211 feature flag.)
* @get_tx_power: store the current TX power into the dbm variable;
* return 0 if successful
*
* @set_wds_peer: set the WDS peer for a WDS interface
*
-@@ -3932,6 +3933,7 @@ struct cfg80211_ops {
+@@ -3959,6 +3960,7 @@ struct cfg80211_ops {
enum nl80211_tx_power_setting type, int mbm);
int (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
int *dbm);
const u8 *addr);
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -1521,6 +1521,7 @@ enum ieee80211_smps_mode {
+@@ -1524,6 +1524,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
*
* @chandef: the channel definition to tune to
* @radar_enabled: whether radar detection is enabled
-@@ -1541,6 +1542,7 @@ enum ieee80211_smps_mode {
+@@ -1544,6 +1545,7 @@ enum ieee80211_smps_mode {
struct ieee80211_conf {
u32 flags;
int power_level, dynamic_ps_timeout;
u8 ps_dtim_period;
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
-@@ -2505,6 +2505,9 @@ enum nl80211_commands {
+@@ -2515,6 +2515,9 @@ enum nl80211_commands {
* @NL80211_ATTR_HE_6GHZ_CAPABILITY: HE 6 GHz Band Capability element (from
* association request when used with NL80211_CMD_NEW_STATION).
*
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
-@@ -2987,6 +2990,8 @@ enum nl80211_attrs {
+@@ -2997,6 +3000,8 @@ enum nl80211_attrs {
NL80211_ATTR_HE_6GHZ_CAPABILITY,
__NL80211_ATTR_AFTER_LAST,
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -2612,6 +2612,19 @@ static int ieee80211_get_tx_power(struct
+@@ -2619,6 +2619,19 @@ static int ieee80211_get_tx_power(struct
return 0;
}
static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
const u8 *addr)
{
-@@ -4042,6 +4055,7 @@ const struct cfg80211_ops mac80211_confi
+@@ -4049,6 +4062,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,
CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
-@@ -1383,6 +1383,7 @@ struct ieee80211_local {
+@@ -1386,6 +1386,7 @@ struct ieee80211_local {
int dynamic_ps_forced_timeout;
int user_power_level; /* in dBm, for all interfaces */