PKG_NAME:=mac80211
-PKG_VERSION:=5.1-rc2-1
+PKG_VERSION:=5.1.16-1
PKG_RELEASE:=1
-PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.1-rc2/
-PKG_HASH:=bb65aeb3da1563e18238a6e9aa84f12e82bd477d8404ad4525bc305d4ce1e241
+PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.1.16/
+PKG_HASH:=b5adc5d458734b9231e81bcf03af2fb1bf2e289a87f1551a4f02bdf3ba053fb8
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
-@@ -3002,6 +3002,8 @@ void regulatory_hint_country_ie(struct w
+@@ -3041,6 +3041,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;
-@@ -3253,6 +3255,7 @@ static bool is_wiphy_all_set_reg_flag(en
+@@ -3292,6 +3294,7 @@ static bool is_wiphy_all_set_reg_flag(en
void regulatory_hint_disconnect(void)
{
#include "htt.h"
#include "htc.h"
-@@ -1147,6 +1148,13 @@ struct ath10k {
+@@ -1150,6 +1151,13 @@ struct ath10k {
} testmode;
struct {
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
-@@ -1195,6 +1195,10 @@ struct ath10k {
+@@ -1198,6 +1198,10 @@ struct ath10k {
struct work_struct radar_confirmation_work;
struct ath10k_bus_params bus_param;
@@ -5792,7 +5792,11 @@ static void ath10k_bss_info_changed(stru
if (changed & BSS_CHANGED_MCAST_RATE &&
- !WARN_ON(ath10k_mac_vif_chan(arvif->vif, &def))) {
+ !ath10k_mac_vif_chan(arvif->vif, &def)) {
band = def.chan->band;
- rateidx = vif->bss_conf.mcast_rate[band] - 1;
+ mcast_rate = vif->bss_conf.mcast_rate[band];
void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state);
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1294,6 +1294,16 @@ void brcmf_dev_coredump(struct device *d
+@@ -1298,6 +1298,16 @@ void brcmf_dev_coredump(struct device *d
brcmf_dbg(TRACE, "failed to create coredump\n");
}
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -1090,8 +1090,8 @@ static u32 brcmf_sdio_hostmail(struct br
+@@ -1101,8 +1101,8 @@ static u32 brcmf_sdio_hostmail(struct br
/* dongle indicates the firmware has halted/crashed */
if (hmb_data & HMB_DATA_FWHALT) {
*/
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1105,6 +1105,14 @@ static int brcmf_revinfo_read(struct seq
+@@ -1109,6 +1109,14 @@ static int brcmf_revinfo_read(struct seq
return 0;
}
static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops)
{
int ret = -1;
-@@ -1176,6 +1184,8 @@ static int brcmf_bus_started(struct brcm
+@@ -1180,6 +1188,8 @@ static int brcmf_bus_started(struct brcm
#endif
#endif /* CONFIG_INET */
/* populate debugfs */
brcmf_debugfs_add_entry(drvr, "revinfo", brcmf_revinfo_read);
brcmf_feat_debugfs_create(drvr);
-@@ -1302,6 +1312,8 @@ void brcmf_fw_crashed(struct device *dev
+@@ -1306,6 +1316,8 @@ void brcmf_fw_crashed(struct device *dev
bphy_err(drvr, "Firmware has halted or crashed\n");
brcmf_dev_coredump(dev);
+++ /dev/null
-From c80d26e81ef1802f30364b4ad1955c1443a592b9 Mon Sep 17 00:00:00 2001
-From: Piotr Figiel <p.figiel@camlintechnologies.com>
-Date: Mon, 4 Mar 2019 15:42:49 +0000
-Subject: [PATCH] brcmfmac: fix WARNING during USB disconnect in case of
- unempty psq
-
-brcmu_pkt_buf_free_skb emits WARNING when attempting to free a sk_buff
-which is part of any queue. After USB disconnect this may have happened
-when brcmf_fws_hanger_cleanup() is called as per-interface psq was never
-cleaned when removing the interface.
-Change brcmf_fws_macdesc_cleanup() in a way that it removes the
-corresponding packets from hanger table (to avoid double-free when
-brcmf_fws_hanger_cleanup() is called) and add a call to clean-up the
-interface specific packet queue.
-
-Below is a WARNING during USB disconnect with Raspberry Pi WiFi dongle
-running in AP mode. This was reproducible when the interface was
-transmitting during the disconnect and is fixed with this commit.
-
-------------[ cut here ]------------
-WARNING: CPU: 0 PID: 1171 at drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c:49 brcmu_pkt_buf_free_skb+0x3c/0x40
-Modules linked in: nf_log_ipv4 nf_log_common xt_LOG xt_limit iptable_mangle xt_connmark xt_tcpudp xt_conntrack nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_filter ip_tables x_tables usb_f_mass_storage usb_f_rndis u_ether cdc_acm smsc95xx usbnet ci_hdrc_imx ci_hdrc ulpi usbmisc_imx 8250_exar 8250_pci 8250 8250_base libcomposite configfs udc_core
-CPU: 0 PID: 1171 Comm: kworker/0:0 Not tainted 4.19.23-00075-gde33ed8 #99
-Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
-Workqueue: usb_hub_wq hub_event
-[<8010ff84>] (unwind_backtrace) from [<8010bb64>] (show_stack+0x10/0x14)
-[<8010bb64>] (show_stack) from [<80840278>] (dump_stack+0x88/0x9c)
-[<80840278>] (dump_stack) from [<8011f5ec>] (__warn+0xfc/0x114)
-[<8011f5ec>] (__warn) from [<8011f71c>] (warn_slowpath_null+0x40/0x48)
-[<8011f71c>] (warn_slowpath_null) from [<805a476c>] (brcmu_pkt_buf_free_skb+0x3c/0x40)
-[<805a476c>] (brcmu_pkt_buf_free_skb) from [<805bb6c4>] (brcmf_fws_cleanup+0x1e4/0x22c)
-[<805bb6c4>] (brcmf_fws_cleanup) from [<805bc854>] (brcmf_fws_del_interface+0x58/0x68)
-[<805bc854>] (brcmf_fws_del_interface) from [<805b66ac>] (brcmf_remove_interface+0x40/0x150)
-[<805b66ac>] (brcmf_remove_interface) from [<805b6870>] (brcmf_detach+0x6c/0xb0)
-[<805b6870>] (brcmf_detach) from [<805bdbb8>] (brcmf_usb_disconnect+0x30/0x4c)
-[<805bdbb8>] (brcmf_usb_disconnect) from [<805e5d64>] (usb_unbind_interface+0x5c/0x1e0)
-[<805e5d64>] (usb_unbind_interface) from [<804aab10>] (device_release_driver_internal+0x154/0x1ec)
-[<804aab10>] (device_release_driver_internal) from [<804a97f4>] (bus_remove_device+0xcc/0xf8)
-[<804a97f4>] (bus_remove_device) from [<804a6fc0>] (device_del+0x118/0x308)
-[<804a6fc0>] (device_del) from [<805e488c>] (usb_disable_device+0xa0/0x1c8)
-[<805e488c>] (usb_disable_device) from [<805dcf98>] (usb_disconnect+0x70/0x1d8)
-[<805dcf98>] (usb_disconnect) from [<805ddd84>] (hub_event+0x464/0xf50)
-[<805ddd84>] (hub_event) from [<80135a70>] (process_one_work+0x138/0x3f8)
-[<80135a70>] (process_one_work) from [<80135d5c>] (worker_thread+0x2c/0x554)
-[<80135d5c>] (worker_thread) from [<8013b1a0>] (kthread+0x124/0x154)
-[<8013b1a0>] (kthread) from [<801010e8>] (ret_from_fork+0x14/0x2c)
-Exception stack(0xecf8dfb0 to 0xecf8dff8)
-dfa0: 00000000 00000000 00000000 00000000
-dfc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
-dfe0: 00000000 00000000 00000000 00000000 00000013 00000000
----[ end trace 38d234018e9e2a90 ]---
-------------[ cut here ]------------
-
-Signed-off-by: Piotr Figiel <p.figiel@camlintechnologies.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../broadcom/brcm80211/brcmfmac/fwsignal.c | 42 +++++++++++--------
- 1 file changed, 24 insertions(+), 18 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
-@@ -580,24 +580,6 @@ static bool brcmf_fws_ifidx_match(struct
- return ifidx == *(int *)arg;
- }
-
--static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q,
-- int ifidx)
--{
-- bool (*matchfn)(struct sk_buff *, void *) = NULL;
-- struct sk_buff *skb;
-- int prec;
--
-- if (ifidx != -1)
-- matchfn = brcmf_fws_ifidx_match;
-- for (prec = 0; prec < q->num_prec; prec++) {
-- skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
-- while (skb) {
-- brcmu_pkt_buf_free_skb(skb);
-- skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
-- }
-- }
--}
--
- static void brcmf_fws_hanger_init(struct brcmf_fws_hanger *hanger)
- {
- int i;
-@@ -669,6 +651,28 @@ static inline int brcmf_fws_hanger_poppk
- return 0;
- }
-
-+static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q,
-+ int ifidx)
-+{
-+ bool (*matchfn)(struct sk_buff *, void *) = NULL;
-+ struct sk_buff *skb;
-+ int prec;
-+ u32 hslot;
-+
-+ if (ifidx != -1)
-+ matchfn = brcmf_fws_ifidx_match;
-+ for (prec = 0; prec < q->num_prec; prec++) {
-+ skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
-+ while (skb) {
-+ hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
-+ brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
-+ true);
-+ brcmu_pkt_buf_free_skb(skb);
-+ skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
-+ }
-+ }
-+}
-+
- static int brcmf_fws_hanger_mark_suppressed(struct brcmf_fws_hanger *h,
- u32 slot_id)
- {
-@@ -2200,6 +2204,8 @@ void brcmf_fws_del_interface(struct brcm
- brcmf_fws_lock(fws);
- ifp->fws_desc = NULL;
- brcmf_dbg(TRACE, "deleting %s\n", entry->name);
-+ brcmf_fws_macdesc_cleanup(fws, &fws->desc.iface[ifp->ifidx],
-+ ifp->ifidx);
- brcmf_fws_macdesc_deinit(entry);
- brcmf_fws_cleanup(fws, ifp->ifidx);
- brcmf_fws_unlock(fws);
+++ /dev/null
-From 5cdb0ef6144f47440850553579aa923c20a63f23 Mon Sep 17 00:00:00 2001
-From: Piotr Figiel <p.figiel@camlintechnologies.com>
-Date: Mon, 4 Mar 2019 15:42:52 +0000
-Subject: [PATCH] brcmfmac: fix NULL pointer derefence during USB disconnect
-
-In case USB disconnect happens at the moment transmitting workqueue is in
-progress the underlying interface may be gone causing a NULL pointer
-dereference. Add synchronization of the workqueue destruction with the
-detach implementation in core so that the transmitting workqueue is stopped
-during detach before the interfaces are removed.
-
-Fix following Oops:
-
-Unable to handle kernel NULL pointer dereference at virtual address 00000008
-pgd = 9e6a802d
-[00000008] *pgd=00000000
-Internal error: Oops: 5 [#1] PREEMPT SMP ARM
-Modules linked in: nf_log_ipv4 nf_log_common xt_LOG xt_limit iptable_mangle
-xt_connmark xt_tcpudp xt_conntrack nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4
-iptable_filter ip_tables x_tables usb_f_mass_storage usb_f_rndis u_ether
-usb_serial_simple usbserial cdc_acm brcmfmac brcmutil smsc95xx usbnet
-ci_hdrc_imx ci_hdrc ulpi usbmisc_imx 8250_exar 8250_pci 8250 8250_base
-libcomposite configfs udc_core
-CPU: 0 PID: 7 Comm: kworker/u8:0 Not tainted 4.19.23-00076-g03740aa-dirty #102
-Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
-Workqueue: brcmf_fws_wq brcmf_fws_dequeue_worker [brcmfmac]
-PC is at brcmf_txfinalize+0x34/0x90 [brcmfmac]
-LR is at brcmf_fws_dequeue_worker+0x218/0x33c [brcmfmac]
-pc : [<7f0dee64>] lr : [<7f0e4140>] psr: 60010093
-sp : ee8abef0 ip : 00000000 fp : edf38000
-r10: ffffffed r9 : edf38970 r8 : edf38004
-r7 : edf3e970 r6 : 00000000 r5 : ede69000 r4 : 00000000
-r3 : 00000a97 r2 : 00000000 r1 : 0000888e r0 : ede69000
-Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment none
-Control: 10c5387d Table: 7d03c04a DAC: 00000051
-Process kworker/u8:0 (pid: 7, stack limit = 0x24ec3e04)
-Stack: (0xee8abef0 to 0xee8ac000)
-bee0: ede69000 00000000 ed56c3e0 7f0e4140
-bf00: 00000001 00000000 edf38004 edf3e99c ed56c3e0 80d03d00 edfea43a edf3e970
-bf20: ee809880 ee804200 ee971100 00000000 edf3e974 00000000 ee804200 80135a70
-bf40: 80d03d00 ee804218 ee809880 ee809894 ee804200 80d03d00 ee804218 ee8aa000
-bf60: 00000088 80135d5c 00000000 ee829f00 ee829dc0 00000000 ee809880 80135d30
-bf80: ee829f1c ee873eac 00000000 8013b1a0 ee829dc0 8013b07c 00000000 00000000
-bfa0: 00000000 00000000 00000000 801010e8 00000000 00000000 00000000 00000000
-bfc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
-bfe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000
-[<7f0dee64>] (brcmf_txfinalize [brcmfmac]) from [<7f0e4140>] (brcmf_fws_dequeue_worker+0x218/0x33c [brcmfmac])
-[<7f0e4140>] (brcmf_fws_dequeue_worker [brcmfmac]) from [<80135a70>] (process_one_work+0x138/0x3f8)
-[<80135a70>] (process_one_work) from [<80135d5c>] (worker_thread+0x2c/0x554)
-[<80135d5c>] (worker_thread) from [<8013b1a0>] (kthread+0x124/0x154)
-[<8013b1a0>] (kthread) from [<801010e8>] (ret_from_fork+0x14/0x2c)
-Exception stack(0xee8abfb0 to 0xee8abff8)
-bfa0: 00000000 00000000 00000000 00000000
-bfc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
-bfe0: 00000000 00000000 00000000 00000000 00000013 00000000
-Code: e1530001 0a000007 e3560000 e1a00005 (05942008)
----[ end trace 079239dd31c86e90 ]---
-
-Signed-off-by: Piotr Figiel <p.figiel@camlintechnologies.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 11 +++++++++--
- .../wireless/broadcom/brcm80211/brcmfmac/bcdc.h | 6 ++++--
- .../wireless/broadcom/brcm80211/brcmfmac/core.c | 4 +++-
- .../broadcom/brcm80211/brcmfmac/fwsignal.c | 16 ++++++++++++----
- .../broadcom/brcm80211/brcmfmac/fwsignal.h | 3 ++-
- .../wireless/broadcom/brcm80211/brcmfmac/proto.c | 10 ++++++++--
- .../wireless/broadcom/brcm80211/brcmfmac/proto.h | 3 ++-
- 7 files changed, 40 insertions(+), 13 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
-@@ -490,11 +490,18 @@ fail:
- return -ENOMEM;
- }
-
--void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr)
-+void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr)
-+{
-+ struct brcmf_bcdc *bcdc = drvr->proto->pd;
-+
-+ brcmf_fws_detach_pre_delif(bcdc->fws);
-+}
-+
-+void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr)
- {
- struct brcmf_bcdc *bcdc = drvr->proto->pd;
-
- drvr->proto->pd = NULL;
-- brcmf_fws_detach(bcdc->fws);
-+ brcmf_fws_detach_post_delif(bcdc->fws);
- kfree(bcdc);
- }
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h
-@@ -18,14 +18,16 @@
-
- #ifdef CPTCFG_BRCMFMAC_PROTO_BCDC
- int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr);
--void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr);
-+void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr);
-+void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr);
- void brcmf_proto_bcdc_txflowblock(struct device *dev, bool state);
- void brcmf_proto_bcdc_txcomplete(struct device *dev, struct sk_buff *txp,
- bool success);
- struct brcmf_fws_info *drvr_to_fws(struct brcmf_pub *drvr);
- #else
- static inline int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) { return 0; }
--static inline void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr) {}
-+static void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr) {};
-+static inline void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr) {}
- #endif
-
- #endif /* BRCMFMAC_BCDC_H */
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1342,6 +1342,8 @@ void brcmf_detach(struct device *dev)
-
- brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN);
-
-+ brcmf_proto_detach_pre_delif(drvr);
-+
- /* make sure primary interface removed last */
- for (i = BRCMF_MAX_IFS-1; i > -1; i--)
- brcmf_remove_interface(drvr->iflist[i], false);
-@@ -1351,7 +1353,7 @@ void brcmf_detach(struct device *dev)
-
- brcmf_bus_stop(drvr->bus_if);
-
-- brcmf_proto_detach(drvr);
-+ brcmf_proto_detach_post_delif(drvr);
-
- bus_if->drvr = NULL;
- wiphy_free(drvr->wiphy);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
-@@ -2443,17 +2443,25 @@ struct brcmf_fws_info *brcmf_fws_attach(
- return fws;
-
- fail:
-- brcmf_fws_detach(fws);
-+ brcmf_fws_detach_pre_delif(fws);
-+ brcmf_fws_detach_post_delif(fws);
- return ERR_PTR(rc);
- }
-
--void brcmf_fws_detach(struct brcmf_fws_info *fws)
-+void brcmf_fws_detach_pre_delif(struct brcmf_fws_info *fws)
- {
- if (!fws)
- return;
--
-- if (fws->fws_wq)
-+ if (fws->fws_wq) {
- destroy_workqueue(fws->fws_wq);
-+ fws->fws_wq = NULL;
-+ }
-+}
-+
-+void brcmf_fws_detach_post_delif(struct brcmf_fws_info *fws)
-+{
-+ if (!fws)
-+ return;
-
- /* cleanup */
- brcmf_fws_lock(fws);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
-@@ -19,7 +19,8 @@
- #define FWSIGNAL_H_
-
- struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr);
--void brcmf_fws_detach(struct brcmf_fws_info *fws);
-+void brcmf_fws_detach_pre_delif(struct brcmf_fws_info *fws);
-+void brcmf_fws_detach_post_delif(struct brcmf_fws_info *fws);
- void brcmf_fws_debugfs_create(struct brcmf_pub *drvr);
- bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws);
- bool brcmf_fws_fc_active(struct brcmf_fws_info *fws);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c
-@@ -67,16 +67,22 @@ fail:
- return -ENOMEM;
- }
-
--void brcmf_proto_detach(struct brcmf_pub *drvr)
-+void brcmf_proto_detach_post_delif(struct brcmf_pub *drvr)
- {
- brcmf_dbg(TRACE, "Enter\n");
-
- if (drvr->proto) {
- if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC)
-- brcmf_proto_bcdc_detach(drvr);
-+ brcmf_proto_bcdc_detach_post_delif(drvr);
- else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF)
- brcmf_proto_msgbuf_detach(drvr);
- kfree(drvr->proto);
- drvr->proto = NULL;
- }
- }
-+
-+void brcmf_proto_detach_pre_delif(struct brcmf_pub *drvr)
-+{
-+ if (drvr->proto && drvr->bus_if->proto_type == BRCMF_PROTO_BCDC)
-+ brcmf_proto_bcdc_detach_pre_delif(drvr);
-+}
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
-@@ -54,7 +54,8 @@ struct brcmf_proto {
-
-
- int brcmf_proto_attach(struct brcmf_pub *drvr);
--void brcmf_proto_detach(struct brcmf_pub *drvr);
-+void brcmf_proto_detach_pre_delif(struct brcmf_pub *drvr);
-+void brcmf_proto_detach_post_delif(struct brcmf_pub *drvr);
-
- static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws,
- struct sk_buff *skb,
+++ /dev/null
-From db3b9e2e1d58080d0754bdf9293dabf8c6491b67 Mon Sep 17 00:00:00 2001
-From: Piotr Figiel <p.figiel@camlintechnologies.com>
-Date: Fri, 8 Mar 2019 15:25:04 +0000
-Subject: [PATCH] brcmfmac: fix race during disconnect when USB completion is
- in progress
-
-It was observed that rarely during USB disconnect happening shortly after
-connect (before full initialization completes) usb_hub_wq would wait
-forever for the dev_init_lock to be unlocked. dev_init_lock would remain
-locked though because of infinite wait during usb_kill_urb:
-
-[ 2730.656472] kworker/0:2 D 0 260 2 0x00000000
-[ 2730.660700] Workqueue: events request_firmware_work_func
-[ 2730.664807] [<809dca20>] (__schedule) from [<809dd164>] (schedule+0x4c/0xac)
-[ 2730.670587] [<809dd164>] (schedule) from [<8069af44>] (usb_kill_urb+0xdc/0x114)
-[ 2730.676815] [<8069af44>] (usb_kill_urb) from [<7f258b50>] (brcmf_usb_free_q+0x34/0xa8 [brcmfmac])
-[ 2730.684833] [<7f258b50>] (brcmf_usb_free_q [brcmfmac]) from [<7f2517d4>] (brcmf_detach+0xa0/0xb8 [brcmfmac])
-[ 2730.693557] [<7f2517d4>] (brcmf_detach [brcmfmac]) from [<7f251a34>] (brcmf_attach+0xac/0x3d8 [brcmfmac])
-[ 2730.702094] [<7f251a34>] (brcmf_attach [brcmfmac]) from [<7f2587ac>] (brcmf_usb_probe_phase2+0x468/0x4a0 [brcmfmac])
-[ 2730.711601] [<7f2587ac>] (brcmf_usb_probe_phase2 [brcmfmac]) from [<7f252888>] (brcmf_fw_request_done+0x194/0x220 [brcmfmac])
-[ 2730.721795] [<7f252888>] (brcmf_fw_request_done [brcmfmac]) from [<805748e4>] (request_firmware_work_func+0x4c/0x88)
-[ 2730.731125] [<805748e4>] (request_firmware_work_func) from [<80141474>] (process_one_work+0x228/0x808)
-[ 2730.739223] [<80141474>] (process_one_work) from [<80141a80>] (worker_thread+0x2c/0x564)
-[ 2730.746105] [<80141a80>] (worker_thread) from [<80147bcc>] (kthread+0x13c/0x16c)
-[ 2730.752227] [<80147bcc>] (kthread) from [<801010b4>] (ret_from_fork+0x14/0x20)
-
-[ 2733.099695] kworker/0:3 D 0 1065 2 0x00000000
-[ 2733.103926] Workqueue: usb_hub_wq hub_event
-[ 2733.106914] [<809dca20>] (__schedule) from [<809dd164>] (schedule+0x4c/0xac)
-[ 2733.112693] [<809dd164>] (schedule) from [<809e2a8c>] (schedule_timeout+0x214/0x3e4)
-[ 2733.119621] [<809e2a8c>] (schedule_timeout) from [<809dde2c>] (wait_for_common+0xc4/0x1c0)
-[ 2733.126810] [<809dde2c>] (wait_for_common) from [<7f258d00>] (brcmf_usb_disconnect+0x1c/0x4c [brcmfmac])
-[ 2733.135206] [<7f258d00>] (brcmf_usb_disconnect [brcmfmac]) from [<8069e0c8>] (usb_unbind_interface+0x5c/0x1e4)
-[ 2733.143943] [<8069e0c8>] (usb_unbind_interface) from [<8056d3e8>] (device_release_driver_internal+0x164/0x1fc)
-[ 2733.152769] [<8056d3e8>] (device_release_driver_internal) from [<8056c078>] (bus_remove_device+0xd0/0xfc)
-[ 2733.161138] [<8056c078>] (bus_remove_device) from [<8056977c>] (device_del+0x11c/0x310)
-[ 2733.167939] [<8056977c>] (device_del) from [<8069cba8>] (usb_disable_device+0xa0/0x1cc)
-[ 2733.174743] [<8069cba8>] (usb_disable_device) from [<8069507c>] (usb_disconnect+0x74/0x1dc)
-[ 2733.181823] [<8069507c>] (usb_disconnect) from [<80695e88>] (hub_event+0x478/0xf88)
-[ 2733.188278] [<80695e88>] (hub_event) from [<80141474>] (process_one_work+0x228/0x808)
-[ 2733.194905] [<80141474>] (process_one_work) from [<80141a80>] (worker_thread+0x2c/0x564)
-[ 2733.201724] [<80141a80>] (worker_thread) from [<80147bcc>] (kthread+0x13c/0x16c)
-[ 2733.207913] [<80147bcc>] (kthread) from [<801010b4>] (ret_from_fork+0x14/0x20)
-
-It was traced down to a case where usb_kill_urb would be called on an URB
-structure containing more or less random data, including large number in
-its use_count. During the debugging it appeared that in brcmf_usb_free_q()
-the traversal over URBs' lists is not synchronized with operations on those
-lists in brcmf_usb_rx_complete() leading to handling
-brcmf_usbdev_info structure (holding lists' head) as lists' element and in
-result causing above problem.
-
-Fix it by walking through all URBs during brcmf_cancel_all_urbs using the
-arrays of requests instead of linked lists.
-
-Signed-off-by: Piotr Figiel <p.figiel@camlintechnologies.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-@@ -682,12 +682,18 @@ static int brcmf_usb_up(struct device *d
-
- static void brcmf_cancel_all_urbs(struct brcmf_usbdev_info *devinfo)
- {
-+ int i;
-+
- if (devinfo->ctl_urb)
- usb_kill_urb(devinfo->ctl_urb);
- if (devinfo->bulk_urb)
- usb_kill_urb(devinfo->bulk_urb);
-- brcmf_usb_free_q(&devinfo->tx_postq, true);
-- brcmf_usb_free_q(&devinfo->rx_postq, true);
-+ if (devinfo->tx_reqs)
-+ for (i = 0; i < devinfo->bus_pub.ntxq; i++)
-+ usb_kill_urb(devinfo->tx_reqs[i].urb);
-+ if (devinfo->rx_reqs)
-+ for (i = 0; i < devinfo->bus_pub.nrxq; i++)
-+ usb_kill_urb(devinfo->rx_reqs[i].urb);
- }
-
- static void brcmf_usb_down(struct device *dev)
+++ /dev/null
-From 24d413a31afaee9bbbf79226052c386b01780ce2 Mon Sep 17 00:00:00 2001
-From: Piotr Figiel <p.figiel@camlintechnologies.com>
-Date: Wed, 13 Mar 2019 09:52:01 +0000
-Subject: [PATCH] brcmfmac: fix Oops when bringing up interface during USB
- disconnect
-
-Fix a race which leads to an Oops with NULL pointer dereference. The
-dereference is in brcmf_config_dongle() when cfg_to_ndev() attempts to get
-net_device structure of interface with index 0 via if2bss mapping. This
-shouldn't fail because of check for bus being ready in brcmf_netdev_open(),
-but it's not synchronised with USB disconnect and there is a race: after
-the check the bus can be marked down and the mapping for interface 0 may be
-gone.
-
-Solve this by modifying disconnect handling so that the removal of mapping
-of ifidx to brcmf_if structure happens after netdev removal (which is
-synchronous with brcmf_netdev_open() thanks to rtln being locked in
-devinet_ioctl()). This assures brcmf_netdev_open() returns before the
-mapping is removed during disconnect.
-
-Unable to handle kernel NULL pointer dereference at virtual address 00000008
-pgd = bcae2612
-[00000008] *pgd=8be73831
-Internal error: Oops: 17 [#1] PREEMPT SMP ARM
-Modules linked in: brcmfmac brcmutil nf_log_ipv4 nf_log_common xt_LOG xt_limit
-iptable_mangle xt_connmark xt_tcpudp xt_conntrack nf_conntrack nf_defrag_ipv6
-nf_defrag_ipv4 iptable_filter ip_tables x_tables usb_f_mass_storage usb_f_rndis
-u_ether usb_serial_simple usbserial cdc_acm smsc95xx usbnet ci_hdrc_imx ci_hdrc
-usbmisc_imx ulpi 8250_exar 8250_pci 8250 8250_base libcomposite configfs
-udc_core [last unloaded: brcmutil]
-CPU: 2 PID: 24478 Comm: ifconfig Not tainted 4.19.23-00078-ga62866d-dirty #115
-Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
-PC is at brcmf_cfg80211_up+0x94/0x29c [brcmfmac]
-LR is at brcmf_cfg80211_up+0x8c/0x29c [brcmfmac]
-pc : [<7f26a91c>] lr : [<7f26a914>] psr: a0070013
-sp : eca99d28 ip : 00000000 fp : ee9c6c00
-r10: 00000036 r9 : 00000000 r8 : ece4002c
-r7 : edb5b800 r6 : 00000000 r5 : 80f08448 r4 : edb5b968
-r3 : ffffffff r2 : 00000000 r1 : 00000002 r0 : 00000000
-Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none
-Control: 10c5387d Table: 7ca0c04a DAC: 00000051
-Process ifconfig (pid: 24478, stack limit = 0xd9e85a0e)
-Stack: (0xeca99d28 to 0xeca9a000)
-9d20: 00000000 80f873b0 0000000d 80f08448 eca99d68 50d45f32
-9d40: 7f27de94 ece40000 80f08448 80f08448 7f27de94 ece4002c 00000000 00000036
-9d60: ee9c6c00 7f27262c 00001002 50d45f32 ece40000 00000000 80f08448 80772008
-9d80: 00000001 00001043 00001002 ece40000 00000000 50d45f32 ece40000 00000001
-9da0: 80f08448 00001043 00001002 807723d0 00000000 50d45f32 80f08448 eca99e58
-9dc0: 80f87113 50d45f32 80f08448 ece40000 ece40138 00001002 80f08448 00000000
-9de0: 00000000 80772434 edbd5380 eca99e58 edbd5380 80f08448 ee9c6c0c 80805f70
-9e00: 00000000 ede08e00 00008914 ece40000 00000014 ee9c6c0c 600c0013 00001043
-9e20: 0208a8c0 ffffffff 00000000 50d45f32 eca98000 80f08448 7ee9fc38 00008914
-9e40: 80f68e40 00000051 eca98000 00000036 00000003 80808b9c 6e616c77 00000030
-9e60: 00000000 00000000 00001043 0208a8c0 ffffffff 00000000 80f08448 00000000
-9e80: 00000000 816d8b20 600c0013 00000001 ede09320 801763d4 00000000 50d45f32
-9ea0: eca98000 80f08448 7ee9fc38 50d45f32 00008914 80f08448 7ee9fc38 80f68e40
-9ec0: ed531540 8074721c 00000800 00000001 00000000 6e616c77 00000030 00000000
-9ee0: 00000000 00001002 0208a8c0 ffffffff 00000000 50d45f32 80f08448 7ee9fc38
-9f00: ed531560 ec8fc900 80285a6c 80285138 edb910c0 00000000 ecd91008 ede08e00
-9f20: 80f08448 00000000 00000000 816d8b20 600c0013 00000001 ede09320 801763d4
-9f40: 00000000 50d45f32 00021000 edb91118 edb910c0 80f08448 01b29000 edb91118
-9f60: eca99f7c 50d45f32 00021000 ec8fc900 00000003 ec8fc900 00008914 7ee9fc38
-9f80: eca98000 00000036 00000003 80285a6c 00086364 7ee9fe1c 000000c3 00000036
-9fa0: 801011c4 80101000 00086364 7ee9fe1c 00000003 00008914 7ee9fc38 00086364
-9fc0: 00086364 7ee9fe1c 000000c3 00000036 0008630c 7ee9fe1c 7ee9fc38 00000003
-9fe0: 000a42b8 7ee9fbd4 00019914 76e09acc 600c0010 00000003 00000000 00000000
-[<7f26a91c>] (brcmf_cfg80211_up [brcmfmac]) from [<7f27262c>] (brcmf_netdev_open+0x74/0xe8 [brcmfmac])
-[<7f27262c>] (brcmf_netdev_open [brcmfmac]) from [<80772008>] (__dev_open+0xcc/0x150)
-[<80772008>] (__dev_open) from [<807723d0>] (__dev_change_flags+0x168/0x1b4)
-[<807723d0>] (__dev_change_flags) from [<80772434>] (dev_change_flags+0x18/0x48)
-[<80772434>] (dev_change_flags) from [<80805f70>] (devinet_ioctl+0x67c/0x79c)
-[<80805f70>] (devinet_ioctl) from [<80808b9c>] (inet_ioctl+0x210/0x3d4)
-[<80808b9c>] (inet_ioctl) from [<8074721c>] (sock_ioctl+0x350/0x524)
-[<8074721c>] (sock_ioctl) from [<80285138>] (do_vfs_ioctl+0xb0/0x9b0)
-[<80285138>] (do_vfs_ioctl) from [<80285a6c>] (ksys_ioctl+0x34/0x5c)
-[<80285a6c>] (ksys_ioctl) from [<80101000>] (ret_fast_syscall+0x0/0x28)
-Exception stack(0xeca99fa8 to 0xeca99ff0)
-9fa0: 00086364 7ee9fe1c 00000003 00008914 7ee9fc38 00086364
-9fc0: 00086364 7ee9fe1c 000000c3 00000036 0008630c 7ee9fe1c 7ee9fc38 00000003
-9fe0: 000a42b8 7ee9fbd4 00019914 76e09acc
-Code: e5970328 eb002021 e1a02006 e3a01002 (e5909008)
----[ end trace 5cbac2333f3ac5df ]---
-
-Signed-off-by: Piotr Figiel <p.figiel@camlintechnologies.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../net/wireless/broadcom/brcm80211/brcmfmac/core.c | 10 +++++++---
- 1 file changed, 7 insertions(+), 3 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -862,17 +862,17 @@ static void brcmf_del_if(struct brcmf_pu
- bool rtnl_locked)
- {
- struct brcmf_if *ifp;
-+ int ifidx;
-
- ifp = drvr->iflist[bsscfgidx];
-- drvr->iflist[bsscfgidx] = NULL;
- if (!ifp) {
- bphy_err(drvr, "Null interface, bsscfgidx=%d\n", bsscfgidx);
- return;
- }
- brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", bsscfgidx,
- ifp->ifidx);
-- if (drvr->if2bss[ifp->ifidx] == bsscfgidx)
-- drvr->if2bss[ifp->ifidx] = BRCMF_BSSIDX_INVALID;
-+ ifidx = ifp->ifidx;
-+
- if (ifp->ndev) {
- if (bsscfgidx == 0) {
- if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
-@@ -900,6 +900,10 @@ static void brcmf_del_if(struct brcmf_pu
- brcmf_p2p_ifp_removed(ifp, rtnl_locked);
- kfree(ifp);
- }
-+
-+ drvr->iflist[bsscfgidx] = NULL;
-+ if (drvr->if2bss[ifidx] == bsscfgidx)
-+ drvr->if2bss[ifidx] = BRCMF_BSSIDX_INVALID;
- }
-
- void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked)
+++ /dev/null
-From a9fd0953fa4a62887306be28641b4b0809f3b2fd Mon Sep 17 00:00:00 2001
-From: Piotr Figiel <p.figiel@camlintechnologies.com>
-Date: Wed, 13 Mar 2019 09:52:42 +0000
-Subject: [PATCH] brcmfmac: convert dev_init_lock mutex to completion
-
-Leaving dev_init_lock mutex locked in probe causes BUG and a WARNING when
-kernel is compiled with CONFIG_PROVE_LOCKING. Convert mutex to completion
-which silences those warnings and improves code readability.
-
-Fix below errors when connecting the USB WiFi dongle:
-
-brcmfmac: brcmf_fw_alloc_request: using brcm/brcmfmac43143 for chip BCM43143/2
-BUG: workqueue leaked lock or atomic: kworker/0:2/0x00000000/434
- last function: hub_event
-1 lock held by kworker/0:2/434:
- #0: 18d5dcdf (&devinfo->dev_init_lock){+.+.}, at: brcmf_usb_probe+0x78/0x550 [brcmfmac]
-CPU: 0 PID: 434 Comm: kworker/0:2 Not tainted 4.19.23-00084-g454a789-dirty #123
-Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
-Workqueue: usb_hub_wq hub_event
-[<8011237c>] (unwind_backtrace) from [<8010d74c>] (show_stack+0x10/0x14)
-[<8010d74c>] (show_stack) from [<809c4324>] (dump_stack+0xa8/0xd4)
-[<809c4324>] (dump_stack) from [<8014195c>] (process_one_work+0x710/0x808)
-[<8014195c>] (process_one_work) from [<80141a80>] (worker_thread+0x2c/0x564)
-[<80141a80>] (worker_thread) from [<80147bcc>] (kthread+0x13c/0x16c)
-[<80147bcc>] (kthread) from [<801010b4>] (ret_from_fork+0x14/0x20)
-Exception stack(0xed1d9fb0 to 0xed1d9ff8)
-9fa0: 00000000 00000000 00000000 00000000
-9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
-9fe0: 00000000 00000000 00000000 00000000 00000013 00000000
-
-======================================================
-WARNING: possible circular locking dependency detected
-4.19.23-00084-g454a789-dirty #123 Not tainted
-------------------------------------------------------
-kworker/0:2/434 is trying to acquire lock:
-e29cf799 ((wq_completion)"events"){+.+.}, at: process_one_work+0x174/0x808
-
-but task is already holding lock:
-18d5dcdf (&devinfo->dev_init_lock){+.+.}, at: brcmf_usb_probe+0x78/0x550 [brcmfmac]
-
-which lock already depends on the new lock.
-
-the existing dependency chain (in reverse order) is:
-
--> #2 (&devinfo->dev_init_lock){+.+.}:
- mutex_lock_nested+0x1c/0x24
- brcmf_usb_probe+0x78/0x550 [brcmfmac]
- usb_probe_interface+0xc0/0x1bc
- really_probe+0x228/0x2c0
- __driver_attach+0xe4/0xe8
- bus_for_each_dev+0x68/0xb4
- bus_add_driver+0x19c/0x214
- driver_register+0x78/0x110
- usb_register_driver+0x84/0x148
- process_one_work+0x228/0x808
- worker_thread+0x2c/0x564
- kthread+0x13c/0x16c
- ret_from_fork+0x14/0x20
- (null)
-
--> #1 (brcmf_driver_work){+.+.}:
- worker_thread+0x2c/0x564
- kthread+0x13c/0x16c
- ret_from_fork+0x14/0x20
- (null)
-
--> #0 ((wq_completion)"events"){+.+.}:
- process_one_work+0x1b8/0x808
- worker_thread+0x2c/0x564
- kthread+0x13c/0x16c
- ret_from_fork+0x14/0x20
- (null)
-
-other info that might help us debug this:
-
-Chain exists of:
- (wq_completion)"events" --> brcmf_driver_work --> &devinfo->dev_init_lock
-
- Possible unsafe locking scenario:
-
- CPU0 CPU1
- ---- ----
- lock(&devinfo->dev_init_lock);
- lock(brcmf_driver_work);
- lock(&devinfo->dev_init_lock);
- lock((wq_completion)"events");
-
- *** DEADLOCK ***
-
-1 lock held by kworker/0:2/434:
- #0: 18d5dcdf (&devinfo->dev_init_lock){+.+.}, at: brcmf_usb_probe+0x78/0x550 [brcmfmac]
-
-stack backtrace:
-CPU: 0 PID: 434 Comm: kworker/0:2 Not tainted 4.19.23-00084-g454a789-dirty #123
-Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
-Workqueue: events request_firmware_work_func
-[<8011237c>] (unwind_backtrace) from [<8010d74c>] (show_stack+0x10/0x14)
-[<8010d74c>] (show_stack) from [<809c4324>] (dump_stack+0xa8/0xd4)
-[<809c4324>] (dump_stack) from [<80172838>] (print_circular_bug+0x210/0x330)
-[<80172838>] (print_circular_bug) from [<80175940>] (__lock_acquire+0x160c/0x1a30)
-[<80175940>] (__lock_acquire) from [<8017671c>] (lock_acquire+0xe0/0x268)
-[<8017671c>] (lock_acquire) from [<80141404>] (process_one_work+0x1b8/0x808)
-[<80141404>] (process_one_work) from [<80141a80>] (worker_thread+0x2c/0x564)
-[<80141a80>] (worker_thread) from [<80147bcc>] (kthread+0x13c/0x16c)
-[<80147bcc>] (kthread) from [<801010b4>] (ret_from_fork+0x14/0x20)
-Exception stack(0xed1d9fb0 to 0xed1d9ff8)
-9fa0: 00000000 00000000 00000000 00000000
-9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
-9fe0: 00000000 00000000 00000000 00000000 00000013 00000000
-
-Signed-off-by: Piotr Figiel <p.figiel@camlintechnologies.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/usb.c | 17 ++++++++---------
- 1 file changed, 8 insertions(+), 9 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-@@ -160,7 +160,7 @@ struct brcmf_usbdev_info {
-
- struct usb_device *usbdev;
- struct device *dev;
-- struct mutex dev_init_lock;
-+ struct completion dev_init_done;
-
- int ctl_in_pipe, ctl_out_pipe;
- struct urb *ctl_urb; /* URB for control endpoint */
-@@ -1194,11 +1194,11 @@ static void brcmf_usb_probe_phase2(struc
- if (ret)
- goto error;
-
-- mutex_unlock(&devinfo->dev_init_lock);
-+ complete(&devinfo->dev_init_done);
- return;
- error:
- brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), ret);
-- mutex_unlock(&devinfo->dev_init_lock);
-+ complete(&devinfo->dev_init_done);
- device_release_driver(dev);
- }
-
-@@ -1266,7 +1266,7 @@ static int brcmf_usb_probe_cb(struct brc
- if (ret)
- goto fail;
- /* we are done */
-- mutex_unlock(&devinfo->dev_init_lock);
-+ complete(&devinfo->dev_init_done);
- return 0;
- }
- bus->chip = bus_pub->devid;
-@@ -1326,11 +1326,10 @@ brcmf_usb_probe(struct usb_interface *in
-
- devinfo->usbdev = usb;
- devinfo->dev = &usb->dev;
-- /* Take an init lock, to protect for disconnect while still loading.
-+ /* Init completion, to protect for disconnect while still loading.
- * Necessary because of the asynchronous firmware load construction
- */
-- mutex_init(&devinfo->dev_init_lock);
-- mutex_lock(&devinfo->dev_init_lock);
-+ init_completion(&devinfo->dev_init_done);
-
- usb_set_intfdata(intf, devinfo);
-
-@@ -1408,7 +1407,7 @@ brcmf_usb_probe(struct usb_interface *in
- return 0;
-
- fail:
-- mutex_unlock(&devinfo->dev_init_lock);
-+ complete(&devinfo->dev_init_done);
- kfree(devinfo);
- usb_set_intfdata(intf, NULL);
- return ret;
-@@ -1423,7 +1422,7 @@ brcmf_usb_disconnect(struct usb_interfac
- devinfo = (struct brcmf_usbdev_info *)usb_get_intfdata(intf);
-
- if (devinfo) {
-- mutex_lock(&devinfo->dev_init_lock);
-+ wait_for_completion(&devinfo->dev_init_done);
- /* Make sure that devinfo still exists. Firmware probe routines
- * may have released the device and cleared the intfdata.
- */
+++ /dev/null
-From 46953f97224d56a12ccbe9c6acaa84ca0dab2780 Mon Sep 17 00:00:00 2001
-From: Kangjie Lu <kjlu@umn.edu>
-Date: Fri, 15 Mar 2019 12:04:32 -0500
-Subject: [PATCH] brcmfmac: fix missing checks for kmemdup
-
-In case kmemdup fails, the fix sets conn_info->req_ie_len and
-conn_info->resp_ie_len to zero to avoid buffer overflows.
-
-Signed-off-by: Kangjie Lu <kjlu@umn.edu>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -5464,6 +5464,8 @@ static s32 brcmf_get_assoc_ies(struct br
- conn_info->req_ie =
- kmemdup(cfg->extra_buf, conn_info->req_ie_len,
- GFP_KERNEL);
-+ if (!conn_info->req_ie)
-+ conn_info->req_ie_len = 0;
- } else {
- conn_info->req_ie_len = 0;
- conn_info->req_ie = NULL;
-@@ -5480,6 +5482,8 @@ static s32 brcmf_get_assoc_ies(struct br
- conn_info->resp_ie =
- kmemdup(cfg->extra_buf, conn_info->resp_ie_len,
- GFP_KERNEL);
-+ if (!conn_info->resp_ie)
-+ conn_info->resp_ie_len = 0;
- } else {
- conn_info->resp_ie_len = 0;
- conn_info->resp_ie = NULL;
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c
-@@ -31,6 +31,10 @@ struct brcmf_dmi_data {
-
- /* NOTE: Please keep all entries sorted alphabetically */
+@@ -35,6 +35,10 @@ static const struct brcmf_dmi_data acepc
+ BRCM_CC_4345_CHIP_ID, 6, "acepc-t8"
+ };
+static const struct brcmf_dmi_data acepc_t8_data = {
+ BRCM_CC_4345_CHIP_ID, 6, "acepc-t8"
static const struct brcmf_dmi_data gpd_win_pocket_data = {
BRCM_CC_4356_CHIP_ID, 2, "gpd-win-pocket"
};
-@@ -49,6 +53,28 @@ static const struct brcmf_dmi_data pov_t
-
- static const struct dmi_system_id dmi_platform_data[] = {
- {
+@@ -76,6 +80,28 @@ static const struct dmi_system_id dmi_pl
+ /* also match on somewhat unique bios-version */
+ DMI_EXACT_MATCH(DMI_BIOS_VERSION, "1.000"),
+ },
++ .driver_data = (void *)&acepc_t8_data,
++ },
++ {
+ /* ACEPC T8 Cherry Trail Z8350 mini PC */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."),
+ /* also match on somewhat unique bios-version */
+ DMI_EXACT_MATCH(DMI_BIOS_VERSION, "1.000"),
+ },
-+ .driver_data = (void *)&acepc_t8_data,
-+ },
-+ {
- /* Match for the GPDwin which unfortunately uses somewhat
- * generic dmi strings, which is why we test for 4 strings.
- * Comparing against 23 other byt/cht boards, board_vendor
+ .driver_data = (void *)&acepc_t8_data,
+ },
+ {
+++ /dev/null
-From e025da3d7aa4770bb1d1b3b0aa7cc4da1744852d Mon Sep 17 00:00:00 2001
-From: Dan Carpenter <dan.carpenter@oracle.com>
-Date: Wed, 24 Apr 2019 12:52:18 +0300
-Subject: [PATCH] brcm80211: potential NULL dereference in
- brcmf_cfg80211_vndr_cmds_dcmd_handler()
-
-If "ret_len" is negative then it could lead to a NULL dereference.
-
-The "ret_len" value comes from nl80211_vendor_cmd(), if it's negative
-then we don't allocate the "dcmd_buf" buffer. Then we pass "ret_len" to
-brcmf_fil_cmd_data_set() where it is cast to a very high u32 value.
-Most of the functions in that call tree check whether the buffer we pass
-is NULL but there are at least a couple places which don't such as
-brcmf_dbg_hex_dump() and brcmf_msgbuf_query_dcmd(). We memcpy() to and
-from the buffer so it would result in a NULL dereference.
-
-The fix is to change the types so that "ret_len" can't be negative. (If
-we memcpy() zero bytes to NULL, that's a no-op and doesn't cause an
-issue).
-
-Fixes: 1bacb0487d0e ("brcmfmac: replace cfg80211 testmode with vendor command")
-Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
-@@ -35,9 +35,10 @@ static int brcmf_cfg80211_vndr_cmds_dcmd
- struct brcmf_if *ifp;
- const struct brcmf_vndr_dcmd_hdr *cmdhdr = data;
- struct sk_buff *reply;
-- int ret, payload, ret_len;
-+ unsigned int payload, ret_len;
- void *dcmd_buf = NULL, *wr_pointer;
- u16 msglen, maxmsglen = PAGE_SIZE - 0x100;
-+ int ret;
-
- if (len < sizeof(*cmdhdr)) {
- brcmf_err("vendor command too short: %d\n", len);
-@@ -65,7 +66,7 @@ static int brcmf_cfg80211_vndr_cmds_dcmd
- brcmf_err("oversize return buffer %d\n", ret_len);
- ret_len = BRCMF_DCMD_MAXLEN;
- }
-- payload = max(ret_len, len) + 1;
-+ payload = max_t(unsigned int, ret_len, len) + 1;
- dcmd_buf = vzalloc(payload);
- if (NULL == dcmd_buf)
- return -ENOMEM;
--- a/drivers/net/wireless/marvell/mwl8k.c
+++ b/drivers/net/wireless/marvell/mwl8k.c
-@@ -5686,6 +5686,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
+@@ -5691,6 +5691,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
static const struct pci_device_id mwl8k_pci_id_table[] = {
--- a/drivers/net/wireless/marvell/mwl8k.c
+++ b/drivers/net/wireless/marvell/mwl8k.c
-@@ -6271,6 +6271,8 @@ static int mwl8k_probe(struct pci_dev *p
+@@ -6276,6 +6276,8 @@ static int mwl8k_probe(struct pci_dev *p
priv->running_bsses = 0;
return rc;
err_stop_firmware:
-@@ -6304,8 +6306,6 @@ static void mwl8k_remove(struct pci_dev
+@@ -6309,8 +6311,6 @@ static void mwl8k_remove(struct pci_dev
return;
priv = hw->priv;
+++ /dev/null
-From b897577af85bb5e5638efa780bc3716fae5212d3 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
-Date: Mon, 8 Apr 2019 09:45:56 +0200
-Subject: [PATCH] mwl8k: Fix rate_idx underflow
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-It was reported on OpenWrt bug tracking system[1], that several users
-are affected by the endless reboot of their routers if they configure
-5GHz interface with channel 44 or 48.
-
-The reboot loop is caused by the following excessive number of WARN_ON
-messages:
-
- WARNING: CPU: 0 PID: 0 at backports-4.19.23-1/net/mac80211/rx.c:4516
- ieee80211_rx_napi+0x1fc/0xa54 [mac80211]
-
-as the messages are being correctly emitted by the following guard:
-
- case RX_ENC_LEGACY:
- if (WARN_ON(status->rate_idx >= sband->n_bitrates))
-
-as the rate_idx is in this case erroneously set to 251 (0xfb). This fix
-simply converts previously used magic number to proper constant and
-guards against substraction which is leading to the currently observed
-underflow.
-
-1. https://bugs.openwrt.org/index.php?do=details&task_id=2218
-
-Fixes: 854783444bab ("mwl8k: properly set receive status rate index on 5 GHz receive")
-Cc: <stable@vger.kernel.org>
-Tested-by: Eubert Bao <bunnier@gmail.com>
-Reported-by: Eubert Bao <bunnier@gmail.com>
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- drivers/net/wireless/marvell/mwl8k.c | 13 +++++++++----
- 1 file changed, 9 insertions(+), 4 deletions(-)
-
---- a/drivers/net/wireless/marvell/mwl8k.c
-+++ b/drivers/net/wireless/marvell/mwl8k.c
-@@ -441,6 +441,9 @@ static const struct ieee80211_rate mwl8k
- #define MWL8K_CMD_UPDATE_STADB 0x1123
- #define MWL8K_CMD_BASTREAM 0x1125
-
-+#define MWL8K_LEGACY_5G_RATE_OFFSET \
-+ (ARRAY_SIZE(mwl8k_rates_24) - ARRAY_SIZE(mwl8k_rates_50))
-+
- static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize)
- {
- u16 command = le16_to_cpu(cmd);
-@@ -1016,8 +1019,9 @@ mwl8k_rxd_ap_process(void *_rxd, struct
-
- if (rxd->channel > 14) {
- status->band = NL80211_BAND_5GHZ;
-- if (!(status->encoding == RX_ENC_HT))
-- status->rate_idx -= 5;
-+ if (!(status->encoding == RX_ENC_HT) &&
-+ status->rate_idx >= MWL8K_LEGACY_5G_RATE_OFFSET)
-+ status->rate_idx -= MWL8K_LEGACY_5G_RATE_OFFSET;
- } else {
- status->band = NL80211_BAND_2GHZ;
- }
-@@ -1124,8 +1128,9 @@ mwl8k_rxd_sta_process(void *_rxd, struct
-
- if (rxd->channel > 14) {
- status->band = NL80211_BAND_5GHZ;
-- if (!(status->encoding == RX_ENC_HT))
-- status->rate_idx -= 5;
-+ if (!(status->encoding == RX_ENC_HT) &&
-+ status->rate_idx >= MWL8K_LEGACY_5G_RATE_OFFSET)
-+ status->rate_idx -= MWL8K_LEGACY_5G_RATE_OFFSET;
- } else {
- status->band = NL80211_BAND_2GHZ;
- }
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
-@@ -7189,6 +7189,11 @@ void cfg80211_pmsr_complete(struct wirel
- #define wiphy_info(wiphy, format, args...) \
- dev_info(&(wiphy)->dev, format, ##args)
+@@ -7194,6 +7194,11 @@ void cfg80211_pmsr_complete(struct wirel
+ #define wiphy_warn_ratelimited(wiphy, format, args...) \
+ dev_warn_ratelimited(&(wiphy)->dev, format, ##args)
+#define wiphy_err_ratelimited(wiphy, format, args...) \
+ dev_err_ratelimited(&(wiphy)->dev, format, ##args)
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-@@ -1017,6 +1017,7 @@ struct rt2x00_dev {
+@@ -1016,6 +1016,7 @@ struct rt2x00_dev {
unsigned int extra_tx_headroom;
struct usb_anchor *anchor;
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
-@@ -671,7 +671,7 @@ int rt2x00queue_write_tx_frame(struct da
+@@ -674,7 +674,7 @@ int rt2x00queue_write_tx_frame(struct da
spin_lock(&queue->tx_lock);
if (unlikely(rt2x00queue_full(queue))) {
if (rt2800_entry_txstatus_timeout(rt2x00dev, entry))
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-@@ -981,8 +981,6 @@ struct rt2x00_dev {
+@@ -980,8 +980,6 @@ struct rt2x00_dev {
*/
DECLARE_KFIFO_PTR(txstatus_fifo, u32);
*/
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
-@@ -1039,7 +1039,6 @@ void rt2x00queue_start_queues(struct rt2
+@@ -1042,7 +1042,6 @@ void rt2x00queue_start_queues(struct rt2
*/
tx_queue_for_each(rt2x00dev, queue)
rt2x00queue_start_queue(queue);
+++ /dev/null
-From 746ba11f170603bf1eaade817553a6c2e9135bbe Mon Sep 17 00:00:00 2001
-From: Vijayakumar Durai <vijayakumar.durai1@vivint.com>
-Date: Wed, 27 Mar 2019 11:03:17 +0100
-Subject: [PATCH] rt2x00: do not increment sequence number while
- re-transmitting
-
-Currently rt2x00 devices retransmit the management frames with
-incremented sequence number if hardware is assigning the sequence.
-
-This is HW bug fixed already for non-QOS data frames, but it should
-be fixed for management frames except beacon.
-
-Without fix retransmitted frames have wrong SN:
-
- AlphaNet_e8:fb:36 Vivotek_52:31:51 Authentication, SN=1648, FN=0, Flags=........C Frame is not being retransmitted 1648 1
- AlphaNet_e8:fb:36 Vivotek_52:31:51 Authentication, SN=1649, FN=0, Flags=....R...C Frame is being retransmitted 1649 1
- AlphaNet_e8:fb:36 Vivotek_52:31:51 Authentication, SN=1650, FN=0, Flags=....R...C Frame is being retransmitted 1650 1
-
-With the fix SN stays correctly the same:
-
- 88:6a:e3:e8:f9:a2 8c:f5:a3:88:76:87 Authentication, SN=1450, FN=0, Flags=........C
- 88:6a:e3:e8:f9:a2 8c:f5:a3:88:76:87 Authentication, SN=1450, FN=0, Flags=....R...C
- 88:6a:e3:e8:f9:a2 8c:f5:a3:88:76:87 Authentication, SN=1450, FN=0, Flags=....R...C
-
-Cc: stable@vger.kernel.org
-Signed-off-by: Vijayakumar Durai <vijayakumar.durai1@vivint.com>
-[sgruszka: simplify code, change comments and changelog]
-Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 -
- drivers/net/wireless/ralink/rt2x00/rt2x00mac.c | 10 ----------
- drivers/net/wireless/ralink/rt2x00/rt2x00queue.c | 15 +++++++++------
- 3 files changed, 9 insertions(+), 17 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-@@ -673,7 +673,6 @@ enum rt2x00_state_flags {
- CONFIG_CHANNEL_HT40,
- CONFIG_POWERSAVING,
- CONFIG_HT_DISABLED,
-- CONFIG_QOS_DISABLED,
- CONFIG_MONITORING,
-
- /*
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
-@@ -642,19 +642,9 @@ void rt2x00mac_bss_info_changed(struct i
- rt2x00dev->intf_associated--;
-
- rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated);
--
-- clear_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags);
- }
-
- /*
-- * Check for access point which do not support 802.11e . We have to
-- * generate data frames sequence number in S/W for such AP, because
-- * of H/W bug.
-- */
-- if (changes & BSS_CHANGED_QOS && !bss_conf->qos)
-- set_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags);
--
-- /*
- * When the erp information has changed, we should perform
- * additional configuration steps. For all other changes we are done.
- */
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
-@@ -201,15 +201,18 @@ static void rt2x00queue_create_tx_descri
- if (!rt2x00_has_cap_flag(rt2x00dev, REQUIRE_SW_SEQNO)) {
- /*
- * rt2800 has a H/W (or F/W) bug, device incorrectly increase
-- * seqno on retransmited data (non-QOS) frames. To workaround
-- * the problem let's generate seqno in software if QOS is
-- * disabled.
-+ * seqno on retransmitted data (non-QOS) and management frames.
-+ * To workaround the problem let's generate seqno in software.
-+ * Except for beacons which are transmitted periodically by H/W
-+ * hence hardware has to assign seqno for them.
- */
-- if (test_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags))
-- __clear_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
-- else
-+ if (ieee80211_is_beacon(hdr->frame_control)) {
-+ __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
- /* H/W will generate sequence number */
- return;
-+ }
-+
-+ __clear_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
- }
-
- /*
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_key *key = rx->key;
struct ieee80211_mmie_16 *mmie;
-- u8 aad[GMAC_AAD_LEN], mic[GMAC_MIC_LEN], ipn[6], nonce[GMAC_NONCE_LEN];
-+ u8 aad[20], mic[16], ipn[6], nonce[12];
+- u8 aad[GMAC_AAD_LEN], *mic, ipn[6], nonce[GMAC_NONCE_LEN];
++ u8 aad[20], *mic, ipn[6], nonce[12];
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
if (!ieee80211_is_mgmt(hdr->frame_control))
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
-@@ -3989,6 +3989,12 @@ out:
+@@ -3982,6 +3982,12 @@ out:
netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 1 Mar 2019 14:42:56 +0100
-Subject: [PATCH] mac80211: do not call driver wake_tx_queue op during reconfig
-
-There are several scenarios in which mac80211 can call drv_wake_tx_queue
-after ieee80211_restart_hw has been called and has not yet completed.
-Driver private structs are considered uninitialized until mac80211 has
-uploaded the vifs, stations and keys again, so using private tx queue
-data during that time is not safe.
-
-The driver can also not rely on drv_reconfig_complete to figure out when
-it is safe to accept drv_wake_tx_queue calls again, because it is only
-called after all tx queues are woken again.
-
-To fix this, bail out early in drv_wake_tx_queue if local->in_reconfig
-is set.
-
-Cc: stable@vger.kernel.org
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/driver-ops.h
-+++ b/net/mac80211/driver-ops.h
-@@ -1195,6 +1195,9 @@ static inline void drv_wake_tx_queue(str
- {
- struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->txq.vif);
-
-+ if (local->in_reconfig)
-+ return;
-+
- if (!check_sdata_in_driver(sdata))
- return;
-
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Thu, 8 Mar 2018 21:00:56 +0100
-Subject: [PATCH] mac80211: fix memory accounting with A-MSDU aggregation
-
-fq uses skb->truesize for memory usage tracking. Increments/decrements
-are done on enqueue/dequeue.
-When A-MSDU aggregation is performed on tx side, the packet is
-aggregated with the last packet in the queue belonging to the same flow.
-There are multiple bugs here:
-- The truesize field of the aggregated packet isn't updated, so memory
-usage is underestimated
-- fq->memory_usage isn't adjusted.
-
-Because of the combination of both bugs, this only causes tx issues in
-rare cases, mainly when the A-MSDU head needs to be reallocated.
-
-Fix this by adjusting both truesize of the A-MSDU head and adding the
-truesize delta to fq->memory_usage.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -3221,6 +3221,7 @@ static bool ieee80211_amsdu_aggregate(st
- u8 max_subframes = sta->sta.max_amsdu_subframes;
- int max_frags = local->hw.max_tx_fragments;
- int max_amsdu_len = sta->sta.max_amsdu_len;
-+ int orig_truesize;
- __be16 len;
- void *data;
- bool ret = false;
-@@ -3259,12 +3260,13 @@ static bool ieee80211_amsdu_aggregate(st
- flow = fq_flow_classify(fq, tin, skb, fq_flow_get_default_func);
- head = skb_peek_tail(&flow->queue);
- if (!head || skb_is_gso(head))
-- goto out;
-+ goto unlock;
-
-+ orig_truesize = head->truesize;
- orig_len = head->len;
-
- if (skb->len + head->len > max_amsdu_len)
-- goto out;
-+ goto unlock;
-
- nfrags = 1 + skb_shinfo(skb)->nr_frags;
- nfrags += 1 + skb_shinfo(head)->nr_frags;
-@@ -3325,6 +3327,9 @@ out_recalc:
- fq_recalc_backlog(fq, tin, flow);
- }
- out:
-+ fq->memory_usage += head->truesize - orig_truesize;
-+
-+unlock:
- spin_unlock_bh(&fq->lock);
-
- return ret;
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 13 Mar 2019 18:52:56 +0100
-Subject: [PATCH] mac80211: fix unaligned access in mesh table hash function
-
-The pointer to the last four bytes of the address is not guaranteed to be
-aligned, so we need to use __get_unaligned_cpu32 here
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/mesh_pathtbl.c
-+++ b/net/mac80211/mesh_pathtbl.c
-@@ -23,7 +23,7 @@ static void mesh_path_free_rcu(struct me
- static u32 mesh_table_hash(const void *addr, u32 len, u32 seed)
- {
- /* Use last four bytes of hw addr as hash index */
-- return jhash_1word(*(u32 *)(addr+2), seed);
-+ return jhash_1word(__get_unaligned_cpu32(addr+2), seed);
- }
-
- static const struct rhashtable_params mesh_rht_params = {
if (likely(sta)) {
if (!IS_ERR(sta))
tx->sta = sta;
-@@ -3564,6 +3564,7 @@ begin:
+@@ -3562,6 +3562,7 @@ begin:
tx.local = local;
tx.skb = skb;
tx.sdata = vif_to_sdata(info->control.vif);
if (txq->sta)
tx.sta = container_of(txq->sta, struct sta_info, sta);
-@@ -3590,7 +3591,7 @@ begin:
+@@ -3588,7 +3589,7 @@ begin:
if (tx.key &&
(tx.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))
ieee80211_xmit_fast_finish(sta->sdata, sta, pn_offs,
tx.key, skb);
-@@ -4040,6 +4041,7 @@ ieee80211_build_data_template(struct iee
+@@ -4028,6 +4029,7 @@ ieee80211_build_data_template(struct iee
hdr = (void *)skb->data;
tx.sta = sta_info_get(sdata, hdr->addr1);
tx.skb = skb;
if (!(mshdr->flags & MESH_FLAGS_AE)) {
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
-@@ -2660,7 +2660,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
+@@ -2668,7 +2668,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
struct ieee80211_local *local = rx->local;
struct ieee80211_sub_if_data *sdata = rx->sdata;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
int tailroom = 0;
hdr = (struct ieee80211_hdr *) skb->data;
-@@ -2753,7 +2753,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
+@@ -2761,7 +2761,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
if (sdata->crypto_tx_tailroom_needed_cnt)
tailroom = IEEE80211_ENCRYPT_TAILROOM;
sdata->encrypt_headroom,
tailroom, GFP_ATOMIC);
if (!fwd_skb)
-@@ -2785,6 +2787,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
+@@ -2793,6 +2795,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
return RX_DROP_MONITOR;
}
/* We store the key here so there's no point in using rcu_dereference()
* but that's fine because the code that changes the pointers will call
* this function after doing so. For a single CPU that would be enough,
-@@ -3564,7 +3570,7 @@ begin:
+@@ -3562,7 +3568,7 @@ begin:
tx.local = local;
tx.skb = skb;
tx.sdata = vif_to_sdata(info->control.vif);
if (txq->sta)
tx.sta = container_of(txq->sta, struct sta_info, sta);
-@@ -4041,7 +4047,7 @@ ieee80211_build_data_template(struct iee
+@@ -4029,7 +4035,7 @@ ieee80211_build_data_template(struct iee
hdr = (void *)skb->data;
tx.sta = sta_info_get(sdata, hdr->addr1);
tx.skb = skb;
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 13 Mar 2019 19:09:22 +0100
-Subject: [PATCH] mac80211: rework locking for txq scheduling / airtime
- fairness
-
-Holding the lock around the entire duration of tx scheduling can create
-some nasty lock contention, especially when processing airtime information
-from the tx status or the rx path.
-Improve locking by only holding the active_txq_lock for lookups / scheduling
-list modifications.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -6269,8 +6269,6 @@ struct sk_buff *ieee80211_tx_dequeue(str
- * @hw: pointer as obtained from ieee80211_alloc_hw()
- * @ac: AC number to return packets from.
- *
-- * Should only be called between calls to ieee80211_txq_schedule_start()
-- * and ieee80211_txq_schedule_end().
- * Returns the next txq if successful, %NULL if no queue is eligible. If a txq
- * is returned, it should be returned with ieee80211_return_txq() after the
- * driver has finished scheduling it.
-@@ -6278,51 +6276,41 @@ struct sk_buff *ieee80211_tx_dequeue(str
- struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac);
-
- /**
-- * ieee80211_return_txq - return a TXQ previously acquired by ieee80211_next_txq()
-- *
-- * @hw: pointer as obtained from ieee80211_alloc_hw()
-- * @txq: pointer obtained from station or virtual interface
-- *
-- * Should only be called between calls to ieee80211_txq_schedule_start()
-- * and ieee80211_txq_schedule_end().
-- */
--void ieee80211_return_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
--
--/**
-- * ieee80211_txq_schedule_start - acquire locks for safe scheduling of an AC
-+ * ieee80211_txq_schedule_start - start new scheduling round for TXQs
- *
- * @hw: pointer as obtained from ieee80211_alloc_hw()
- * @ac: AC number to acquire locks for
- *
-- * Acquire locks needed to schedule TXQs from the given AC. Should be called
-- * before ieee80211_next_txq() or ieee80211_return_txq().
-+ * Should be called before ieee80211_next_txq() or ieee80211_return_txq().
- */
--void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac)
-- __acquires(txq_lock);
-+void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac);
-+
-+/* (deprecated) */
-+static inline void ieee80211_txq_schedule_end(struct ieee80211_hw *hw, u8 ac)
-+{
-+}
-
- /**
-- * ieee80211_txq_schedule_end - release locks for safe scheduling of an AC
-+ * ieee80211_schedule_txq - schedule a TXQ for transmission
- *
- * @hw: pointer as obtained from ieee80211_alloc_hw()
-- * @ac: AC number to acquire locks for
-+ * @txq: pointer obtained from station or virtual interface
- *
-- * Release locks previously acquired by ieee80211_txq_schedule_end().
-+ * Schedules a TXQ for transmission if it is not already scheduled.
- */
--void ieee80211_txq_schedule_end(struct ieee80211_hw *hw, u8 ac)
-- __releases(txq_lock);
-+void ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
-
- /**
-- * ieee80211_schedule_txq - schedule a TXQ for transmission
-+ * ieee80211_return_txq - return a TXQ previously acquired by ieee80211_next_txq()
- *
- * @hw: pointer as obtained from ieee80211_alloc_hw()
- * @txq: pointer obtained from station or virtual interface
-- *
-- * Schedules a TXQ for transmission if it is not already scheduled. Takes a
-- * lock, which means it must *not* be called between
-- * ieee80211_txq_schedule_start() and ieee80211_txq_schedule_end()
- */
--void ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
-- __acquires(txq_lock) __releases(txq_lock);
-+static inline void
-+ieee80211_return_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
-+{
-+ ieee80211_schedule_txq(hw, txq);
-+}
-
- /**
- * ieee80211_txq_may_transmit - check whether TXQ is allowed to transmit
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -3658,16 +3658,17 @@ EXPORT_SYMBOL(ieee80211_tx_dequeue);
- struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)
- {
- struct ieee80211_local *local = hw_to_local(hw);
-+ struct ieee80211_txq *ret = NULL;
- struct txq_info *txqi = NULL;
-
-- lockdep_assert_held(&local->active_txq_lock[ac]);
-+ spin_lock_bh(&local->active_txq_lock[ac]);
-
- begin:
- txqi = list_first_entry_or_null(&local->active_txqs[ac],
- struct txq_info,
- schedule_order);
- if (!txqi)
-- return NULL;
-+ goto out;
-
- if (txqi->txq.sta) {
- struct sta_info *sta = container_of(txqi->txq.sta,
-@@ -3684,21 +3685,25 @@ struct ieee80211_txq *ieee80211_next_txq
-
-
- if (txqi->schedule_round == local->schedule_round[ac])
-- return NULL;
-+ goto out;
-
- list_del_init(&txqi->schedule_order);
- txqi->schedule_round = local->schedule_round[ac];
-- return &txqi->txq;
-+ ret = &txqi->txq;
-+
-+out:
-+ spin_unlock_bh(&local->active_txq_lock[ac]);
-+ return ret;
- }
- EXPORT_SYMBOL(ieee80211_next_txq);
-
--void ieee80211_return_txq(struct ieee80211_hw *hw,
-- struct ieee80211_txq *txq)
-+void ieee80211_schedule_txq(struct ieee80211_hw *hw,
-+ struct ieee80211_txq *txq)
- {
- struct ieee80211_local *local = hw_to_local(hw);
- struct txq_info *txqi = to_txq_info(txq);
-
-- lockdep_assert_held(&local->active_txq_lock[txq->ac]);
-+ spin_lock_bh(&local->active_txq_lock[txq->ac]);
-
- if (list_empty(&txqi->schedule_order) &&
- (!skb_queue_empty(&txqi->frags) || txqi->tin.backlog_packets)) {
-@@ -3718,17 +3723,7 @@ void ieee80211_return_txq(struct ieee802
- list_add_tail(&txqi->schedule_order,
- &local->active_txqs[txq->ac]);
- }
--}
--EXPORT_SYMBOL(ieee80211_return_txq);
--
--void ieee80211_schedule_txq(struct ieee80211_hw *hw,
-- struct ieee80211_txq *txq)
-- __acquires(txq_lock) __releases(txq_lock)
--{
-- struct ieee80211_local *local = hw_to_local(hw);
-
-- spin_lock_bh(&local->active_txq_lock[txq->ac]);
-- ieee80211_return_txq(hw, txq);
- spin_unlock_bh(&local->active_txq_lock[txq->ac]);
- }
- EXPORT_SYMBOL(ieee80211_schedule_txq);
-@@ -3741,7 +3736,7 @@ bool ieee80211_txq_may_transmit(struct i
- struct sta_info *sta;
- u8 ac = txq->ac;
-
-- lockdep_assert_held(&local->active_txq_lock[ac]);
-+ spin_lock_bh(&local->active_txq_lock[ac]);
-
- if (!txqi->txq.sta)
- goto out;
-@@ -3771,34 +3766,27 @@ bool ieee80211_txq_may_transmit(struct i
-
- sta->airtime[ac].deficit += sta->airtime_weight;
- list_move_tail(&txqi->schedule_order, &local->active_txqs[ac]);
-+ spin_unlock_bh(&local->active_txq_lock[ac]);
-
- return false;
- out:
- if (!list_empty(&txqi->schedule_order))
- list_del_init(&txqi->schedule_order);
-+ spin_unlock_bh(&local->active_txq_lock[ac]);
-
- return true;
- }
- EXPORT_SYMBOL(ieee80211_txq_may_transmit);
-
- void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac)
-- __acquires(txq_lock)
- {
- struct ieee80211_local *local = hw_to_local(hw);
-
- spin_lock_bh(&local->active_txq_lock[ac]);
- local->schedule_round[ac]++;
--}
--EXPORT_SYMBOL(ieee80211_txq_schedule_start);
--
--void ieee80211_txq_schedule_end(struct ieee80211_hw *hw, u8 ac)
-- __releases(txq_lock)
--{
-- struct ieee80211_local *local = hw_to_local(hw);
--
- spin_unlock_bh(&local->active_txq_lock[ac]);
- }
--EXPORT_SYMBOL(ieee80211_txq_schedule_end);
-+EXPORT_SYMBOL(ieee80211_txq_schedule_start);
-
- void __ieee80211_subif_start_xmit(struct sk_buff *skb,
- struct net_device *dev,
+ fq_flow_get_default_func);
head = skb_peek_tail(&flow->queue);
if (!head || skb_is_gso(head))
- goto unlock;
+ goto out;
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
-@@ -3546,6 +3546,7 @@ struct sk_buff *ieee80211_tx_dequeue(str
+@@ -3544,6 +3544,7 @@ struct sk_buff *ieee80211_tx_dequeue(str
ieee80211_tx_result r;
struct ieee80211_vif *vif = txq->vif;
spin_lock_bh(&fq->lock);
if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags) ||
-@@ -3562,11 +3563,12 @@ struct sk_buff *ieee80211_tx_dequeue(str
+@@ -3560,11 +3561,12 @@ struct sk_buff *ieee80211_tx_dequeue(str
if (skb)
goto out;
hdr = (struct ieee80211_hdr *)skb->data;
info = IEEE80211_SKB_CB(skb);
-@@ -3612,8 +3614,11 @@ begin:
+@@ -3610,8 +3612,11 @@ begin:
skb = __skb_dequeue(&tx.skbs);
}
if (skb_has_frag_list(skb) &&
-@@ -3652,6 +3657,7 @@ begin:
+@@ -3650,6 +3655,7 @@ begin:
}
IEEE80211_SKB_CB(skb)->control.vif = vif;
}
if (encaps_data)
-@@ -3416,7 +3406,6 @@ static bool ieee80211_xmit_fast(struct i
+@@ -3414,7 +3404,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);
struct ethhdr eth;
struct ieee80211_tx_info *info;
struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
-@@ -3468,10 +3457,7 @@ static bool ieee80211_xmit_fast(struct i
+@@ -3466,10 +3455,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'
*/
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sun, 17 Mar 2019 14:26:59 +0100
-Subject: [PATCH] mac80211: make ieee80211_schedule_txq schedule empty TXQs
-
-Currently there is no way for the driver to signal to mac80211 that it should
-schedule a TXQ even if there are no packets on the mac80211 part of that queue.
-This is problematic if the driver has an internal retry queue to deal with
-software A-MPDU retry.
-
-This patch changes the behavior of ieee80211_schedule_txq to always schedule
-the queue, as its only user (ath9k) seems to expect such behavior already:
-it calls this function on tx status and on powersave wakeup whenever its
-internal retry queue is not empty.
-
-Also add an extra argument to ieee80211_return_txq to get the same behavior.
-
-This fixes an issue on ath9k where tx queues with packets to retry (and no
-new packets in mac80211) would not get serviced.
-
-Fixes: 89cea7493a346 ("ath9k: Switch to mac80211 TXQ scheduling and airtime APIs")
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
-Acked-by: Toke Høiland-Jørgensen <toke@redhat.com>
----
- drivers/net/wireless/ath/ath10k/htt_rx.c | 2 +-
- drivers/net/wireless/ath/ath10k/mac.c | 4 ++--
- drivers/net/wireless/ath/ath9k/xmit.c | 5 ++++-
- include/net/mac80211.h | 24 ++++++++++++++++++++----
- net/mac80211/tx.c | 10 ++++++----
- 5 files changed, 33 insertions(+), 12 deletions(-)
-
---- a/drivers/net/wireless/ath/ath10k/htt_rx.c
-+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
-@@ -2728,7 +2728,7 @@ static void ath10k_htt_rx_tx_fetch_ind(s
- num_msdus++;
- num_bytes += ret;
- }
-- ieee80211_return_txq(hw, txq);
-+ ieee80211_return_txq(hw, txq, false);
- ieee80211_txq_schedule_end(hw, txq->ac);
-
- record->num_msdus = cpu_to_le16(num_msdus);
---- a/drivers/net/wireless/ath/ath10k/mac.c
-+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -4089,7 +4089,7 @@ static int ath10k_mac_schedule_txq(struc
- if (ret < 0)
- break;
- }
-- ieee80211_return_txq(hw, txq);
-+ ieee80211_return_txq(hw, txq, false);
- ath10k_htt_tx_txq_update(hw, txq);
- if (ret == -EBUSY)
- break;
-@@ -4374,7 +4374,7 @@ static void ath10k_mac_op_wake_tx_queue(
- if (ret < 0)
- break;
- }
-- ieee80211_return_txq(hw, txq);
-+ ieee80211_return_txq(hw, txq, false);
- ath10k_htt_tx_txq_update(hw, txq);
- out:
- ieee80211_txq_schedule_end(hw, ac);
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -1938,12 +1938,15 @@ void ath_txq_schedule(struct ath_softc *
- goto out;
-
- while ((queue = ieee80211_next_txq(hw, txq->mac80211_qnum))) {
-+ bool force;
-+
- tid = (struct ath_atx_tid *)queue->drv_priv;
-
- ret = ath_tx_sched_aggr(sc, txq, tid);
- ath_dbg(common, QUEUE, "ath_tx_sched_aggr returned %d\n", ret);
-
-- ieee80211_return_txq(hw, queue);
-+ force = !skb_queue_empty(&tid->retry_q);
-+ ieee80211_return_txq(hw, queue, force);
- }
-
- out:
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -6290,26 +6290,42 @@ static inline void ieee80211_txq_schedul
- {
- }
-
-+void __ieee80211_schedule_txq(struct ieee80211_hw *hw,
-+ struct ieee80211_txq *txq, bool force);
-+
- /**
- * ieee80211_schedule_txq - schedule a TXQ for transmission
- *
- * @hw: pointer as obtained from ieee80211_alloc_hw()
- * @txq: pointer obtained from station or virtual interface
- *
-- * Schedules a TXQ for transmission if it is not already scheduled.
-+ * Schedules a TXQ for transmission if it is not already scheduled,
-+ * even if mac80211 does not have any packets buffered.
-+ *
-+ * The driver may call this function if it has buffered packets for
-+ * this TXQ internally.
- */
--void ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
-+static inline void
-+ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
-+{
-+ __ieee80211_schedule_txq(hw, txq, true);
-+}
-
- /**
- * ieee80211_return_txq - return a TXQ previously acquired by ieee80211_next_txq()
- *
- * @hw: pointer as obtained from ieee80211_alloc_hw()
- * @txq: pointer obtained from station or virtual interface
-+ * @force: schedule txq even if mac80211 does not have any buffered packets.
-+ *
-+ * The driver may set force=true if it has buffered packets for this TXQ
-+ * internally.
- */
- static inline void
--ieee80211_return_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
-+ieee80211_return_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq,
-+ bool force)
- {
-- ieee80211_schedule_txq(hw, txq);
-+ __ieee80211_schedule_txq(hw, txq, force);
- }
-
- /**
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -3694,8 +3694,9 @@ out:
- }
- EXPORT_SYMBOL(ieee80211_next_txq);
-
--void ieee80211_schedule_txq(struct ieee80211_hw *hw,
-- struct ieee80211_txq *txq)
-+void __ieee80211_schedule_txq(struct ieee80211_hw *hw,
-+ struct ieee80211_txq *txq,
-+ bool force)
- {
- struct ieee80211_local *local = hw_to_local(hw);
- struct txq_info *txqi = to_txq_info(txq);
-@@ -3703,7 +3704,8 @@ void ieee80211_schedule_txq(struct ieee8
- spin_lock_bh(&local->active_txq_lock[txq->ac]);
-
- if (list_empty(&txqi->schedule_order) &&
-- (!skb_queue_empty(&txqi->frags) || txqi->tin.backlog_packets)) {
-+ (force || !skb_queue_empty(&txqi->frags) ||
-+ txqi->tin.backlog_packets)) {
- /* If airtime accounting is active, always enqueue STAs at the
- * head of the list to ensure that they only get moved to the
- * back by the airtime DRR scheduler once they have a negative
-@@ -3723,7 +3725,7 @@ void ieee80211_schedule_txq(struct ieee8
-
- spin_unlock_bh(&local->active_txq_lock[txq->ac]);
- }
--EXPORT_SYMBOL(ieee80211_schedule_txq);
-+EXPORT_SYMBOL(__ieee80211_schedule_txq);
-
- bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
- struct ieee80211_txq *txq)
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Tue, 19 Mar 2019 11:36:12 +0100
-Subject: [PATCH] mac80211: un-schedule TXQs on powersave start
-
-Once a station enters powersave, its queues should not be returned by
-ieee80211_next_txq() anymore. They will be re-scheduled again after the
-station has woken up again
-
-Fixes: 1866760096bf4 ("mac80211: Add TXQ scheduling API")
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -1568,7 +1568,15 @@ static void sta_ps_start(struct sta_info
- return;
-
- for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) {
-- if (txq_has_queue(sta->sta.txq[tid]))
-+ struct ieee80211_txq *txq = sta->sta.txq[tid];
-+ struct txq_info *txqi = to_txq_info(txq);
-+
-+ spin_lock(&local->active_txq_lock[txq->ac]);
-+ if (!list_empty(&txqi->schedule_order))
-+ list_del_init(&txqi->schedule_order);
-+ spin_unlock(&local->active_txq_lock[txq->ac]);
-+
-+ if (txq_has_queue(txq))
- set_bit(tid, &sta->txq_buffered_tids);
- else
- clear_bit(tid, &sta->txq_buffered_tids);
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
-@@ -3792,6 +3792,7 @@ void __ieee80211_subif_start_xmit(struct
+@@ -3790,6 +3790,7 @@ void __ieee80211_subif_start_xmit(struct
u32 info_flags)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct sta_info *sta;
struct sk_buff *next;
-@@ -3805,7 +3806,15 @@ void __ieee80211_subif_start_xmit(struct
+@@ -3803,7 +3804,15 @@ void __ieee80211_subif_start_xmit(struct
if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
goto out_free;
+++ /dev/null
-From 33d915d9e8ce811d8958915ccd18d71a66c7c495 Mon Sep 17 00:00:00 2001
-From: Manikanta Pubbisetty <mpubbise@codeaurora.org>
-Date: Wed, 8 May 2019 14:55:33 +0530
-Subject: [PATCH] {nl,mac}80211: allow 4addr AP operation on crypto controlled
- devices
-
-As per the current design, in the case of sw crypto controlled devices,
-it is the device which advertises the support for AP/VLAN iftype based
-on it's ability to tranmsit packets encrypted in software
-(In VLAN functionality, group traffic generated for a specific
-VLAN group is always encrypted in software). Commit db3bdcb9c3ff
-("mac80211: allow AP_VLAN operation on crypto controlled devices")
-has introduced this change.
-
-Since 4addr AP operation also uses AP/VLAN iftype, this conditional
-way of advertising AP/VLAN support has broken 4addr AP mode operation on
-crypto controlled devices which do not support VLAN functionality.
-
-In the case of ath10k driver, not all firmwares have support for VLAN
-functionality but all can support 4addr AP operation. Because AP/VLAN
-support is not advertised for these devices, 4addr AP operations are
-also blocked.
-
-Fix this by allowing 4addr operation on devices which do not support
-AP/VLAN iftype but can support 4addr AP operation (decision is based on
-the wiphy flag WIPHY_FLAG_4ADDR_AP).
-
-Cc: stable@vger.kernel.org
-Fixes: db3bdcb9c3ff ("mac80211: allow AP_VLAN operation on crypto controlled devices")
-Signed-off-by: Manikanta Pubbisetty <mpubbise@codeaurora.org>
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
- include/net/cfg80211.h | 3 ++-
- net/mac80211/util.c | 4 +++-
- net/wireless/core.c | 6 +++++-
- net/wireless/nl80211.c | 8 ++++++--
- 4 files changed, 16 insertions(+), 5 deletions(-)
-
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -3767,7 +3767,8 @@ struct cfg80211_ops {
- * on wiphy_new(), but can be changed by the driver if it has a good
- * reason to override the default
- * @WIPHY_FLAG_4ADDR_AP: supports 4addr mode even on AP (with a single station
-- * on a VLAN interface)
-+ * on a VLAN interface). This flag also serves an extra purpose of
-+ * supporting 4ADDR AP mode on devices which do not support AP/VLAN iftype.
- * @WIPHY_FLAG_4ADDR_STATION: supports 4addr mode even as a station
- * @WIPHY_FLAG_CONTROL_PORT_PROTOCOL: This device supports setting the
- * control port protocol ethertype. The device also honours the
---- a/net/mac80211/util.c
-+++ b/net/mac80211/util.c
-@@ -3760,7 +3760,9 @@ int ieee80211_check_combinations(struct
- }
-
- /* Always allow software iftypes */
-- if (local->hw.wiphy->software_iftypes & BIT(iftype)) {
-+ if (local->hw.wiphy->software_iftypes & BIT(iftype) ||
-+ (iftype == NL80211_IFTYPE_AP_VLAN &&
-+ local->hw.wiphy->flags & WIPHY_FLAG_4ADDR_AP)) {
- if (radar_detect)
- return -EINVAL;
- return 0;
---- a/net/wireless/core.c
-+++ b/net/wireless/core.c
-@@ -1412,8 +1412,12 @@ static int cfg80211_netdev_notifier_call
- }
- break;
- case NETDEV_PRE_UP:
-- if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
-+ if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)) &&
-+ !(wdev->iftype == NL80211_IFTYPE_AP_VLAN &&
-+ rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP &&
-+ wdev->use_4addr))
- return notifier_from_errno(-EOPNOTSUPP);
-+
- if (rfkill_blocked(rdev->rfkill))
- return notifier_from_errno(-ERFKILL);
- break;
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -3387,8 +3387,7 @@ static int nl80211_new_interface(struct
- if (info->attrs[NL80211_ATTR_IFTYPE])
- type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
-
-- if (!rdev->ops->add_virtual_intf ||
-- !(rdev->wiphy.interface_modes & (1 << type)))
-+ if (!rdev->ops->add_virtual_intf)
- return -EOPNOTSUPP;
-
- if ((type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN ||
-@@ -3407,6 +3406,11 @@ static int nl80211_new_interface(struct
- return err;
- }
-
-+ if (!(rdev->wiphy.interface_modes & (1 << type)) &&
-+ !(type == NL80211_IFTYPE_AP_VLAN && params.use_4addr &&
-+ rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP))
-+ return -EOPNOTSUPP;
-+
- err = nl80211_parse_mon_options(rdev, type, info, ¶ms);
- if (err < 0)
- return err;