aboutsummaryrefslogtreecommitdiffstats
path: root/package
diff options
context:
space:
mode:
authorRafał Miłecki <rafal@milecki.pl>2019-04-18 12:37:10 +0200
committerRafał Miłecki <rafal@milecki.pl>2019-04-18 12:37:10 +0200
commit2d2e615dee0421e126af9d4ebd49a720e341e3af (patch)
tree402408ae791acd47843f53fb2a46abf0de821b2c /package
parent02aed76968d60d254ab9d0d8768f0c54dbfc6d9d (diff)
downloadupstream-2d2e615dee0421e126af9d4ebd49a720e341e3af.tar.gz
upstream-2d2e615dee0421e126af9d4ebd49a720e341e3af.tar.bz2
upstream-2d2e615dee0421e126af9d4ebd49a720e341e3af.zip
mac80211: brcmfmac: really add early fw crash recovery
Previous commit backported USB fixes instead of firmware crash recovery patches. Fixes: 02aed76968d6 ("mac80211: brcmfmac: early work on FullMAC firmware crash recovery") Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Diffstat (limited to 'package')
-rw-r--r--package/kernel/mac80211/patches/450-v5.2-0001-brcmfmac-support-repeated-brcmf_fw_alloc_request-cal.patch32
-rw-r--r--package/kernel/mac80211/patches/450-v5.2-0002-brcmfmac-add-a-function-designated-for-handling-firm.patch79
-rw-r--r--package/kernel/mac80211/patches/450-v5.2-0003-brcmfmac-reset-PCIe-bus-on-a-firmware-crash.patch153
-rw-r--r--package/kernel/mac80211/patches/451-v5.2-0001-brcmfmac-fix-WARNING-during-USB-disconnect-in-case-o.patch124
-rw-r--r--package/kernel/mac80211/patches/451-v5.2-0002-brcmfmac-fix-NULL-pointer-derefence-during-USB-disco.patch217
-rw-r--r--package/kernel/mac80211/patches/452-v5.2-0001-brcmfmac-fix-race-during-disconnect-when-USB-complet.patch (renamed from package/kernel/mac80211/patches/450-v5.2-0001-brcmfmac-fix-race-during-disconnect-when-USB-complet.patch)0
-rw-r--r--package/kernel/mac80211/patches/452-v5.2-0002-brcmfmac-remove-pending-parameter-from-brcmf_usb_fre.patch (renamed from package/kernel/mac80211/patches/450-v5.2-0002-brcmfmac-remove-pending-parameter-from-brcmf_usb_fre.patch)0
-rw-r--r--package/kernel/mac80211/patches/452-v5.2-0003-brcmfmac-remove-unused-variable-i-from-brcmf_usb_fre.patch (renamed from package/kernel/mac80211/patches/450-v5.2-0003-brcmfmac-remove-unused-variable-i-from-brcmf_usb_fre.patch)0
8 files changed, 605 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/450-v5.2-0001-brcmfmac-support-repeated-brcmf_fw_alloc_request-cal.patch b/package/kernel/mac80211/patches/450-v5.2-0001-brcmfmac-support-repeated-brcmf_fw_alloc_request-cal.patch
new file mode 100644
index 0000000000..ef694f079f
--- /dev/null
+++ b/package/kernel/mac80211/patches/450-v5.2-0001-brcmfmac-support-repeated-brcmf_fw_alloc_request-cal.patch
@@ -0,0 +1,32 @@
+From c9692820710f57c826b2e43a6fb1e4cd307508b0 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Tue, 26 Feb 2019 14:11:16 +0100
+Subject: [PATCH] brcmfmac: support repeated brcmf_fw_alloc_request() calls
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+During a normal brcmfmac lifetime brcmf_fw_alloc_request() is called
+once only during the probe. It's safe to assume provided array is clear.
+
+Further brcmfmac improvements may require calling it multiple times
+though. This patch allows it by fixing invalid firmware paths like:
+brcm/brcmfmac4366c-pcie.binbrcm/brcmfmac4366c-pcie.bin
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+@@ -743,6 +743,7 @@ brcmf_fw_alloc_request(u32 chip, u32 chi
+
+ for (j = 0; j < n_fwnames; j++) {
+ fwreq->items[j].path = fwnames[j].path;
++ fwnames[j].path[0] = '\0';
+ /* check if firmware path is provided by module parameter */
+ if (brcmf_mp_global.firmware_path[0] != '\0') {
+ strlcpy(fwnames[j].path, mp_path,
diff --git a/package/kernel/mac80211/patches/450-v5.2-0002-brcmfmac-add-a-function-designated-for-handling-firm.patch b/package/kernel/mac80211/patches/450-v5.2-0002-brcmfmac-add-a-function-designated-for-handling-firm.patch
new file mode 100644
index 0000000000..595b8948c7
--- /dev/null
+++ b/package/kernel/mac80211/patches/450-v5.2-0002-brcmfmac-add-a-function-designated-for-handling-firm.patch
@@ -0,0 +1,79 @@
+From a2ec87ddbf1637f854ffcfff9d12d392fa30758b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Tue, 26 Feb 2019 14:11:18 +0100
+Subject: [PATCH] brcmfmac: add a function designated for handling firmware
+ fails
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This improves handling PCIe firmware halts by printing a clear error
+message and replaces a similar code in the SDIO bus support.
+
+It will also allow further improvements like trying to recover from a
+firmware crash.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 2 ++
+ .../net/wireless/broadcom/brcm80211/brcmfmac/core.c | 10 ++++++++++
+ .../net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 2 +-
+ .../net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 4 ++--
+ 4 files changed, 15 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+@@ -262,6 +262,8 @@ void brcmf_detach(struct device *dev);
+ void brcmf_dev_reset(struct device *dev);
+ /* Request from bus module to initiate a coredump */
+ void brcmf_dev_coredump(struct device *dev);
++/* Indication that firmware has halted or crashed */
++void brcmf_fw_crashed(struct device *dev);
+
+ /* Configure the "global" bus state used by upper layers */
+ 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
+ brcmf_dbg(TRACE, "failed to create coredump\n");
+ }
+
++void brcmf_fw_crashed(struct device *dev)
++{
++ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
++ struct brcmf_pub *drvr = bus_if->drvr;
++
++ bphy_err(drvr, "Firmware has halted or crashed\n");
++
++ brcmf_dev_coredump(dev);
++}
++
+ void brcmf_detach(struct device *dev)
+ {
+ s32 i;
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+@@ -730,7 +730,7 @@ static void brcmf_pcie_handle_mb_data(st
+ }
+ if (dtoh_mb_data & BRCMF_D2H_DEV_FWHALT) {
+ brcmf_dbg(PCIE, "D2H_MB_DATA: FW HALT\n");
+- brcmf_dev_coredump(&devinfo->pdev->dev);
++ brcmf_fw_crashed(&devinfo->pdev->dev);
+ }
+ }
+
+--- 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
+
+ /* dongle indicates the firmware has halted/crashed */
+ if (hmb_data & HMB_DATA_FWHALT) {
+- brcmf_err("mailbox indicates firmware halted\n");
+- brcmf_dev_coredump(&sdiod->func1->dev);
++ brcmf_dbg(SDIO, "mailbox indicates firmware halted\n");
++ brcmf_fw_crashed(&sdiod->func1->dev);
+ }
+
+ /* Dongle recomposed rx frames, accept them again */
diff --git a/package/kernel/mac80211/patches/450-v5.2-0003-brcmfmac-reset-PCIe-bus-on-a-firmware-crash.patch b/package/kernel/mac80211/patches/450-v5.2-0003-brcmfmac-reset-PCIe-bus-on-a-firmware-crash.patch
new file mode 100644
index 0000000000..0f2fc42954
--- /dev/null
+++ b/package/kernel/mac80211/patches/450-v5.2-0003-brcmfmac-reset-PCIe-bus-on-a-firmware-crash.patch
@@ -0,0 +1,153 @@
+From 4684997d9eea29380000e062755aa6d368d789a3 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Tue, 26 Feb 2019 14:11:19 +0100
+Subject: [PATCH] brcmfmac: reset PCIe bus on a firmware crash
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This includes bus reset & reloading a firmware. It should be sufficient
+for a user space to (setup and) use a wireless device again.
+
+Support for reset on USB & SDIO can be added later.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ .../broadcom/brcm80211/brcmfmac/bus.h | 10 ++++++
+ .../broadcom/brcm80211/brcmfmac/core.c | 12 +++++++
+ .../broadcom/brcm80211/brcmfmac/core.h | 2 ++
+ .../broadcom/brcm80211/brcmfmac/pcie.c | 35 +++++++++++++++++++
+ 4 files changed, 59 insertions(+)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+@@ -90,6 +90,7 @@ struct brcmf_bus_ops {
+ int (*get_memdump)(struct device *dev, void *data, size_t len);
+ int (*get_fwname)(struct device *dev, const char *ext,
+ unsigned char *fw_name);
++ int (*reset)(struct device *dev);
+ };
+
+
+@@ -235,6 +236,15 @@ int brcmf_bus_get_fwname(struct brcmf_bu
+ return bus->ops->get_fwname(bus->dev, ext, fw_name);
+ }
+
++static inline
++int brcmf_bus_reset(struct brcmf_bus *bus)
++{
++ if (!bus->ops->reset)
++ return -EOPNOTSUPP;
++
++ return bus->ops->reset(bus->dev);
++}
++
+ /*
+ * interface functions from common layer
+ */
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -1104,6 +1104,14 @@ static int brcmf_revinfo_read(struct seq
+ return 0;
+ }
+
++static void brcmf_core_bus_reset(struct work_struct *work)
++{
++ struct brcmf_pub *drvr = container_of(work, struct brcmf_pub,
++ bus_reset);
++
++ brcmf_bus_reset(drvr->bus_if);
++}
++
+ static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops)
+ {
+ int ret = -1;
+@@ -1175,6 +1183,8 @@ static int brcmf_bus_started(struct brcm
+ #endif
+ #endif /* CONFIG_INET */
+
++ INIT_WORK(&drvr->bus_reset, brcmf_core_bus_reset);
++
+ /* populate debugfs */
+ brcmf_debugfs_add_entry(drvr, "revinfo", brcmf_revinfo_read);
+ brcmf_feat_debugfs_create(drvr);
+@@ -1300,6 +1310,8 @@ void brcmf_fw_crashed(struct device *dev
+ bphy_err(drvr, "Firmware has halted or crashed\n");
+
+ brcmf_dev_coredump(dev);
++
++ schedule_work(&drvr->bus_reset);
+ }
+
+ void brcmf_detach(struct device *dev)
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+@@ -143,6 +143,8 @@ struct brcmf_pub {
+ struct notifier_block inet6addr_notifier;
+ struct brcmf_mp_device *settings;
+
++ struct work_struct bus_reset;
++
+ u8 clmver[BRCMF_DCMD_SMLEN];
+ };
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+@@ -345,6 +345,10 @@ static const u32 brcmf_ring_itemsize[BRC
+ BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE
+ };
+
++static void brcmf_pcie_setup(struct device *dev, int ret,
++ struct brcmf_fw_request *fwreq);
++static struct brcmf_fw_request *
++brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo);
+
+ static u32
+ brcmf_pcie_read_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset)
+@@ -1409,6 +1413,36 @@ int brcmf_pcie_get_fwname(struct device
+ return 0;
+ }
+
++static int brcmf_pcie_reset(struct device *dev)
++{
++ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
++ struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
++ struct brcmf_pciedev_info *devinfo = buspub->devinfo;
++ struct brcmf_fw_request *fwreq;
++ int err;
++
++ brcmf_detach(dev);
++
++ brcmf_pcie_release_irq(devinfo);
++ brcmf_pcie_release_scratchbuffers(devinfo);
++ brcmf_pcie_release_ringbuffers(devinfo);
++ brcmf_pcie_reset_device(devinfo);
++
++ fwreq = brcmf_pcie_prepare_fw_request(devinfo);
++ if (!fwreq) {
++ dev_err(dev, "Failed to prepare FW request\n");
++ return -ENOMEM;
++ }
++
++ err = brcmf_fw_get_firmwares(dev, fwreq, brcmf_pcie_setup);
++ if (err) {
++ dev_err(dev, "Failed to prepare FW request\n");
++ kfree(fwreq);
++ }
++
++ return err;
++}
++
+ static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
+ .txdata = brcmf_pcie_tx,
+ .stop = brcmf_pcie_down,
+@@ -1418,6 +1452,7 @@ static const struct brcmf_bus_ops brcmf_
+ .get_ramsize = brcmf_pcie_get_ramsize,
+ .get_memdump = brcmf_pcie_get_memdump,
+ .get_fwname = brcmf_pcie_get_fwname,
++ .reset = brcmf_pcie_reset,
+ };
+
+
diff --git a/package/kernel/mac80211/patches/451-v5.2-0001-brcmfmac-fix-WARNING-during-USB-disconnect-in-case-o.patch b/package/kernel/mac80211/patches/451-v5.2-0001-brcmfmac-fix-WARNING-during-USB-disconnect-in-case-o.patch
new file mode 100644
index 0000000000..cb4b5c924f
--- /dev/null
+++ b/package/kernel/mac80211/patches/451-v5.2-0001-brcmfmac-fix-WARNING-during-USB-disconnect-in-case-o.patch
@@ -0,0 +1,124 @@
+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);
diff --git a/package/kernel/mac80211/patches/451-v5.2-0002-brcmfmac-fix-NULL-pointer-derefence-during-USB-disco.patch b/package/kernel/mac80211/patches/451-v5.2-0002-brcmfmac-fix-NULL-pointer-derefence-during-USB-disco.patch
new file mode 100644
index 0000000000..e45288b63b
--- /dev/null
+++ b/package/kernel/mac80211/patches/451-v5.2-0002-brcmfmac-fix-NULL-pointer-derefence-during-USB-disco.patch
@@ -0,0 +1,217 @@
+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,
diff --git a/package/kernel/mac80211/patches/450-v5.2-0001-brcmfmac-fix-race-during-disconnect-when-USB-complet.patch b/package/kernel/mac80211/patches/452-v5.2-0001-brcmfmac-fix-race-during-disconnect-when-USB-complet.patch
index a6d5c34007..a6d5c34007 100644
--- a/package/kernel/mac80211/patches/450-v5.2-0001-brcmfmac-fix-race-during-disconnect-when-USB-complet.patch
+++ b/package/kernel/mac80211/patches/452-v5.2-0001-brcmfmac-fix-race-during-disconnect-when-USB-complet.patch
diff --git a/package/kernel/mac80211/patches/450-v5.2-0002-brcmfmac-remove-pending-parameter-from-brcmf_usb_fre.patch b/package/kernel/mac80211/patches/452-v5.2-0002-brcmfmac-remove-pending-parameter-from-brcmf_usb_fre.patch
index 80ad31ece6..80ad31ece6 100644
--- a/package/kernel/mac80211/patches/450-v5.2-0002-brcmfmac-remove-pending-parameter-from-brcmf_usb_fre.patch
+++ b/package/kernel/mac80211/patches/452-v5.2-0002-brcmfmac-remove-pending-parameter-from-brcmf_usb_fre.patch
diff --git a/package/kernel/mac80211/patches/450-v5.2-0003-brcmfmac-remove-unused-variable-i-from-brcmf_usb_fre.patch b/package/kernel/mac80211/patches/452-v5.2-0003-brcmfmac-remove-unused-variable-i-from-brcmf_usb_fre.patch
index 4c8d073914..4c8d073914 100644
--- a/package/kernel/mac80211/patches/450-v5.2-0003-brcmfmac-remove-unused-variable-i-from-brcmf_usb_fre.patch
+++ b/package/kernel/mac80211/patches/452-v5.2-0003-brcmfmac-remove-unused-variable-i-from-brcmf_usb_fre.patch