mac80211: brcm: backport brcmfmac 5.2 patches
authorRafał Miłecki <rafal@milecki.pl>
Thu, 18 Apr 2019 08:13:13 +0000 (10:13 +0200)
committerRafał Miłecki <rafal@milecki.pl>
Thu, 18 Apr 2019 08:16:10 +0000 (10:16 +0200)
This includes some USB fixes and early work on FullMAC firmware crash
recovery.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
18 files changed:
package/kernel/mac80211/patches/brcm/356-v5.1-0001-brcmfmac-fix-size-of-the-struct-msgbuf_ring_status.patch [new file with mode: 0644]
package/kernel/mac80211/patches/brcm/356-v5.1-0002-brcmfmac-print-firmware-reported-general-status-erro.patch [new file with mode: 0644]
package/kernel/mac80211/patches/brcm/360-v5.2-0001-brcmfmac-support-repeated-brcmf_fw_alloc_request-cal.patch [new file with mode: 0644]
package/kernel/mac80211/patches/brcm/360-v5.2-0002-brcmfmac-add-a-function-designated-for-handling-firm.patch [new file with mode: 0644]
package/kernel/mac80211/patches/brcm/360-v5.2-0003-brcmfmac-reset-PCIe-bus-on-a-firmware-crash.patch [new file with mode: 0644]
package/kernel/mac80211/patches/brcm/361-v5.2-0001-brcmfmac-fix-WARNING-during-USB-disconnect-in-case-o.patch [new file with mode: 0644]
package/kernel/mac80211/patches/brcm/361-v5.2-0002-brcmfmac-fix-NULL-pointer-derefence-during-USB-disco.patch [new file with mode: 0644]
package/kernel/mac80211/patches/brcm/362-v5.2-0001-brcmfmac-fix-race-during-disconnect-when-USB-complet.patch [new file with mode: 0644]
package/kernel/mac80211/patches/brcm/362-v5.2-0002-brcmfmac-remove-pending-parameter-from-brcmf_usb_fre.patch [new file with mode: 0644]
package/kernel/mac80211/patches/brcm/362-v5.2-0003-brcmfmac-remove-unused-variable-i-from-brcmf_usb_fre.patch [new file with mode: 0644]
package/kernel/mac80211/patches/brcm/363-v5.2-brcmfmac-fix-Oops-when-bringing-up-interface-during-.patch [new file with mode: 0644]
package/kernel/mac80211/patches/brcm/364-v5.2-brcmfmac-convert-dev_init_lock-mutex-to-completion.patch [new file with mode: 0644]
package/kernel/mac80211/patches/brcm/365-v5.2-brcmfmac-fix-missing-checks-for-kmemdup.patch [new file with mode: 0644]
package/kernel/mac80211/patches/brcm/366-v5.2-brcmfmac-Use-struct_size-in-kzalloc.patch [new file with mode: 0644]
package/kernel/mac80211/patches/brcm/367-v5.2-brcmfmac-Loading-the-correct-firmware-for-brcm43456.patch [new file with mode: 0644]
package/kernel/mac80211/patches/brcm/368-v5.2-brcmfmac-fix-leak-of-mypkt-on-error-return-path.patch [new file with mode: 0644]
package/kernel/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch
package/kernel/mac80211/patches/brcm/865-brcmfmac-get-RAM-info-right-before-downloading-PCIe-.patch [new file with mode: 0644]

diff --git a/package/kernel/mac80211/patches/brcm/356-v5.1-0001-brcmfmac-fix-size-of-the-struct-msgbuf_ring_status.patch b/package/kernel/mac80211/patches/brcm/356-v5.1-0001-brcmfmac-fix-size-of-the-struct-msgbuf_ring_status.patch
new file mode 100644 (file)
index 0000000..10834db
--- /dev/null
@@ -0,0 +1,29 @@
+From 0c7051610c577b60b01b3b5aec14d6765e177b0d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Thu, 21 Feb 2019 11:33:24 +0100
+Subject: [PATCH] brcmfmac: fix size of the struct msgbuf_ring_status
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This updates host struct to match the in-firmawre definition. It's a
+cosmetic change as it only applies to the reserved struct space.
+
+Fixes: c988b78244df ("brcmfmac: print firmware reported ring status errors")
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+@@ -139,7 +139,7 @@ struct msgbuf_ring_status {
+       struct msgbuf_common_hdr        msg;
+       struct msgbuf_completion_hdr    compl_hdr;
+       __le16                          write_idx;
+-      __le32                          rsvd0[5];
++      __le16                          rsvd0[5];
+ };
+ struct msgbuf_rx_event {
diff --git a/package/kernel/mac80211/patches/brcm/356-v5.1-0002-brcmfmac-print-firmware-reported-general-status-erro.patch b/package/kernel/mac80211/patches/brcm/356-v5.1-0002-brcmfmac-print-firmware-reported-general-status-erro.patch
new file mode 100644 (file)
index 0000000..313d501
--- /dev/null
@@ -0,0 +1,69 @@
+From c91377495192cda096e52dc09c266b0d05f16d86 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Thu, 21 Feb 2019 11:33:25 +0100
+Subject: [PATCH] brcmfmac: print firmware reported general status errors
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Firmware may report general errors using a special message type. Add
+basic support for it by simply decoding & printing an error number.
+
+A sample situation in which firmware reports a buf error:
+CONSOLE: 027084.733 no host response IOCTL buffer available..so fail the request
+will now produce a "Firmware reported general error: 9" on the host.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ .../broadcom/brcm80211/brcmfmac/msgbuf.c      | 24 +++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+@@ -134,6 +134,14 @@ struct msgbuf_completion_hdr {
+       __le16                          flow_ring_id;
+ };
++/* Data struct for the MSGBUF_TYPE_GEN_STATUS */
++struct msgbuf_gen_status {
++      struct msgbuf_common_hdr        msg;
++      struct msgbuf_completion_hdr    compl_hdr;
++      __le16                          write_idx;
++      __le32                          rsvd0[3];
++};
++
+ /* Data struct for the MSGBUF_TYPE_RING_STATUS */
+ struct msgbuf_ring_status {
+       struct msgbuf_common_hdr        msg;
+@@ -1194,6 +1202,18 @@ brcmf_msgbuf_process_rx_complete(struct
+       brcmf_netif_rx(ifp, skb);
+ }
++static void brcmf_msgbuf_process_gen_status(struct brcmf_msgbuf *msgbuf,
++                                          void *buf)
++{
++      struct msgbuf_gen_status *gen_status = buf;
++      struct brcmf_pub *drvr = msgbuf->drvr;
++      int err;
++
++      err = le16_to_cpu(gen_status->compl_hdr.status);
++      if (err)
++              bphy_err(drvr, "Firmware reported general error: %d\n", err);
++}
++
+ static void brcmf_msgbuf_process_ring_status(struct brcmf_msgbuf *msgbuf,
+                                            void *buf)
+ {
+@@ -1273,6 +1293,10 @@ static void brcmf_msgbuf_process_msgtype
+       msg = (struct msgbuf_common_hdr *)buf;
+       switch (msg->msgtype) {
++      case MSGBUF_TYPE_GEN_STATUS:
++              brcmf_dbg(MSGBUF, "MSGBUF_TYPE_GEN_STATUS\n");
++              brcmf_msgbuf_process_gen_status(msgbuf, buf);
++              break;
+       case MSGBUF_TYPE_RING_STATUS:
+               brcmf_dbg(MSGBUF, "MSGBUF_TYPE_RING_STATUS\n");
+               brcmf_msgbuf_process_ring_status(msgbuf, buf);
diff --git a/package/kernel/mac80211/patches/brcm/360-v5.2-0001-brcmfmac-support-repeated-brcmf_fw_alloc_request-cal.patch b/package/kernel/mac80211/patches/brcm/360-v5.2-0001-brcmfmac-support-repeated-brcmf_fw_alloc_request-cal.patch
new file mode 100644 (file)
index 0000000..ef694f0
--- /dev/null
@@ -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/brcm/360-v5.2-0002-brcmfmac-add-a-function-designated-for-handling-firm.patch b/package/kernel/mac80211/patches/brcm/360-v5.2-0002-brcmfmac-add-a-function-designated-for-handling-firm.patch
new file mode 100644 (file)
index 0000000..595b894
--- /dev/null
@@ -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/brcm/360-v5.2-0003-brcmfmac-reset-PCIe-bus-on-a-firmware-crash.patch b/package/kernel/mac80211/patches/brcm/360-v5.2-0003-brcmfmac-reset-PCIe-bus-on-a-firmware-crash.patch
new file mode 100644 (file)
index 0000000..5617d14
--- /dev/null
@@ -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
+@@ -91,6 +91,7 @@ struct brcmf_bus_ops {
+       int (*get_fwname)(struct device *dev, const char *ext,
+                         unsigned char *fw_name);
+       void (*debugfs_create)(struct device *dev);
++      int (*reset)(struct device *dev);
+ };
+@@ -245,6 +246,15 @@ void brcmf_bus_debugfs_create(struct brc
+       return bus->ops->debugfs_create(bus->dev);
+ }
++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
+@@ -1105,6 +1105,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;
+@@ -1176,6 +1184,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);
+@@ -1302,6 +1312,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/brcm/361-v5.2-0001-brcmfmac-fix-WARNING-during-USB-disconnect-in-case-o.patch b/package/kernel/mac80211/patches/brcm/361-v5.2-0001-brcmfmac-fix-WARNING-during-USB-disconnect-in-case-o.patch
new file mode 100644 (file)
index 0000000..cb4b5c9
--- /dev/null
@@ -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/brcm/361-v5.2-0002-brcmfmac-fix-NULL-pointer-derefence-during-USB-disco.patch b/package/kernel/mac80211/patches/brcm/361-v5.2-0002-brcmfmac-fix-NULL-pointer-derefence-during-USB-disco.patch
new file mode 100644 (file)
index 0000000..e45288b
--- /dev/null
@@ -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/brcm/362-v5.2-0001-brcmfmac-fix-race-during-disconnect-when-USB-complet.patch b/package/kernel/mac80211/patches/brcm/362-v5.2-0001-brcmfmac-fix-race-during-disconnect-when-USB-complet.patch
new file mode 100644 (file)
index 0000000..b6a11d6
--- /dev/null
@@ -0,0 +1,84 @@
+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)
diff --git a/package/kernel/mac80211/patches/brcm/362-v5.2-0002-brcmfmac-remove-pending-parameter-from-brcmf_usb_fre.patch b/package/kernel/mac80211/patches/brcm/362-v5.2-0002-brcmfmac-remove-pending-parameter-from-brcmf_usb_fre.patch
new file mode 100644 (file)
index 0000000..088e731
--- /dev/null
@@ -0,0 +1,54 @@
+From 2b78e5f5223666d403d4fdb30af4ad65c8da3cdb Mon Sep 17 00:00:00 2001
+From: Piotr Figiel <p.figiel@camlintechnologies.com>
+Date: Fri, 8 Mar 2019 15:25:06 +0000
+Subject: [PATCH] brcmfmac: remove pending parameter from brcmf_usb_free_q
+
+brcmf_usb_free_q is no longer called with pending=true thus this boolean
+parameter is no longer needed.
+
+Signed-off-by: Piotr Figiel <p.figiel@camlintechnologies.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ .../wireless/broadcom/brcm80211/brcmfmac/usb.c    | 15 ++++++---------
+ 1 file changed, 6 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+@@ -445,9 +445,10 @@ fail:
+ }
+-static void brcmf_usb_free_q(struct list_head *q, bool pending)
++static void brcmf_usb_free_q(struct list_head *q)
+ {
+       struct brcmf_usbreq *req, *next;
++
+       int i = 0;
+       list_for_each_entry_safe(req, next, q, list) {
+               if (!req->urb) {
+@@ -455,12 +456,8 @@ static void brcmf_usb_free_q(struct list
+                       break;
+               }
+               i++;
+-              if (pending) {
+-                      usb_kill_urb(req->urb);
+-              } else {
+-                      usb_free_urb(req->urb);
+-                      list_del_init(&req->list);
+-              }
++              usb_free_urb(req->urb);
++              list_del_init(&req->list);
+       }
+ }
+@@ -1029,8 +1026,8 @@ static void brcmf_usb_detach(struct brcm
+       brcmf_dbg(USB, "Enter, devinfo %p\n", devinfo);
+       /* free the URBS */
+-      brcmf_usb_free_q(&devinfo->rx_freeq, false);
+-      brcmf_usb_free_q(&devinfo->tx_freeq, false);
++      brcmf_usb_free_q(&devinfo->rx_freeq);
++      brcmf_usb_free_q(&devinfo->tx_freeq);
+       usb_free_urb(devinfo->ctl_urb);
+       usb_free_urb(devinfo->bulk_urb);
diff --git a/package/kernel/mac80211/patches/brcm/362-v5.2-0003-brcmfmac-remove-unused-variable-i-from-brcmf_usb_fre.patch b/package/kernel/mac80211/patches/brcm/362-v5.2-0003-brcmfmac-remove-unused-variable-i-from-brcmf_usb_fre.patch
new file mode 100644 (file)
index 0000000..4c8d073
--- /dev/null
@@ -0,0 +1,29 @@
+From 504f06725d015954a0fcafdf1d90a6795ca8f769 Mon Sep 17 00:00:00 2001
+From: Piotr Figiel <p.figiel@camlintechnologies.com>
+Date: Fri, 8 Mar 2019 15:25:09 +0000
+Subject: [PATCH] brcmfmac: remove unused variable i from brcmf_usb_free_q
+
+Variable i is not used so remove it.
+
+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 | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+@@ -449,13 +449,11 @@ static void brcmf_usb_free_q(struct list
+ {
+       struct brcmf_usbreq *req, *next;
+-      int i = 0;
+       list_for_each_entry_safe(req, next, q, list) {
+               if (!req->urb) {
+                       brcmf_err("bad req\n");
+                       break;
+               }
+-              i++;
+               usb_free_urb(req->urb);
+               list_del_init(&req->list);
+       }
diff --git a/package/kernel/mac80211/patches/brcm/363-v5.2-brcmfmac-fix-Oops-when-bringing-up-interface-during-.patch b/package/kernel/mac80211/patches/brcm/363-v5.2-brcmfmac-fix-Oops-when-bringing-up-interface-during-.patch
new file mode 100644 (file)
index 0000000..01e9bf0
--- /dev/null
@@ -0,0 +1,123 @@
+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)
diff --git a/package/kernel/mac80211/patches/brcm/364-v5.2-brcmfmac-convert-dev_init_lock-mutex-to-completion.patch b/package/kernel/mac80211/patches/brcm/364-v5.2-brcmfmac-convert-dev_init_lock-mutex-to-completion.patch
new file mode 100644 (file)
index 0000000..e6ecd22
--- /dev/null
@@ -0,0 +1,182 @@
+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.
+                */
diff --git a/package/kernel/mac80211/patches/brcm/365-v5.2-brcmfmac-fix-missing-checks-for-kmemdup.patch b/package/kernel/mac80211/patches/brcm/365-v5.2-brcmfmac-fix-missing-checks-for-kmemdup.patch
new file mode 100644 (file)
index 0000000..87974dc
--- /dev/null
@@ -0,0 +1,35 @@
+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
+@@ -5456,6 +5456,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;
+@@ -5472,6 +5474,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;
diff --git a/package/kernel/mac80211/patches/brcm/366-v5.2-brcmfmac-Use-struct_size-in-kzalloc.patch b/package/kernel/mac80211/patches/brcm/366-v5.2-brcmfmac-Use-struct_size-in-kzalloc.patch
new file mode 100644 (file)
index 0000000..d00a9d7
--- /dev/null
@@ -0,0 +1,53 @@
+From 0cf83903aad03dc7f444a47990def48c4a9d3276 Mon Sep 17 00:00:00 2001
+From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
+Date: Wed, 3 Apr 2019 11:46:11 -0500
+Subject: [PATCH] brcmfmac: Use struct_size() in kzalloc()
+
+One of the more common cases of allocation size calculations is finding
+the size of a structure that has a zero-sized array at the end, along
+with memory for some number of elements for that array. For example:
+
+struct foo {
+    int stuff;
+    struct boo entry[];
+};
+
+size = sizeof(struct foo) + count * sizeof(struct boo);
+instance = kzalloc(size, GFP_KERNEL)
+
+Instead of leaving these open-coded and prone to type mistakes, we can
+now use the new struct_size() helper:
+
+instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL)
+
+Notice that, in this case, variable reqsz is not necessary,
+hence it is removed.
+
+This code was detected with the help of Coccinelle.
+
+Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+@@ -711,7 +711,6 @@ brcmf_fw_alloc_request(u32 chip, u32 chi
+       size_t mp_path_len;
+       u32 i, j;
+       char end = '\0';
+-      size_t reqsz;
+       for (i = 0; i < table_size; i++) {
+               if (mapping_table[i].chipid == chip &&
+@@ -726,8 +725,7 @@ brcmf_fw_alloc_request(u32 chip, u32 chi
+               return NULL;
+       }
+-      reqsz = sizeof(*fwreq) + n_fwnames * sizeof(struct brcmf_fw_item);
+-      fwreq = kzalloc(reqsz, GFP_KERNEL);
++      fwreq = kzalloc(struct_size(fwreq, items, n_fwnames), GFP_KERNEL);
+       if (!fwreq)
+               return NULL;
diff --git a/package/kernel/mac80211/patches/brcm/367-v5.2-brcmfmac-Loading-the-correct-firmware-for-brcm43456.patch b/package/kernel/mac80211/patches/brcm/367-v5.2-brcmfmac-Loading-the-correct-firmware-for-brcm43456.patch
new file mode 100644 (file)
index 0000000..d19284e
--- /dev/null
@@ -0,0 +1,35 @@
+From e3062e05e1cfe378bb9b3fa0bef46711372bcf13 Mon Sep 17 00:00:00 2001
+From: Ondrej Jirman <megous@megous.com>
+Date: Sat, 6 Apr 2019 01:45:13 +0200
+Subject: [PATCH] brcmfmac: Loading the correct firmware for brcm43456
+
+SDIO based brcm43456 is currently misdetected as brcm43455 and the wrong
+firmware name is used. Correct the detection and load the correct
+firmware file. Chiprev for brcm43456 is "9".
+
+Signed-off-by: Ondrej Jirman <megous@megous.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -622,6 +622,7 @@ BRCMF_FW_DEF(43430A0, "brcmfmac43430a0-s
+ /* Note the names are not postfixed with a1 for backward compatibility */
+ BRCMF_FW_DEF(43430A1, "brcmfmac43430-sdio");
+ BRCMF_FW_DEF(43455, "brcmfmac43455-sdio");
++BRCMF_FW_DEF(43456, "brcmfmac43456-sdio");
+ BRCMF_FW_DEF(4354, "brcmfmac4354-sdio");
+ BRCMF_FW_DEF(4356, "brcmfmac4356-sdio");
+ BRCMF_FW_DEF(4373, "brcmfmac4373-sdio");
+@@ -642,7 +643,8 @@ static const struct brcmf_firmware_mappi
+       BRCMF_FW_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339),
+       BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0x00000001, 43430A0),
+       BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFE, 43430A1),
+-      BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, 43455),
++      BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0x00000200, 43456),
++      BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFDC0, 43455),
+       BRCMF_FW_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354),
+       BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),
+       BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373),
diff --git a/package/kernel/mac80211/patches/brcm/368-v5.2-brcmfmac-fix-leak-of-mypkt-on-error-return-path.patch b/package/kernel/mac80211/patches/brcm/368-v5.2-brcmfmac-fix-leak-of-mypkt-on-error-return-path.patch
new file mode 100644 (file)
index 0000000..a9a9d74
--- /dev/null
@@ -0,0 +1,41 @@
+From a927e8d8ab57e696800e20cf09a72b7dfe3bbebb Mon Sep 17 00:00:00 2001
+From: Colin Ian King <colin.king@canonical.com>
+Date: Tue, 9 Apr 2019 12:43:33 +0100
+Subject: [PATCH] brcmfmac: fix leak of mypkt on error return path
+
+Currently if the call to brcmf_sdiod_set_backplane_window fails then
+error return path leaks mypkt. Fix this by returning by a new
+error path labelled 'out' that calls brcmu_pkt_buf_free_skb to free
+mypkt.  Also remove redundant check on err before calling
+brcmf_sdiod_skbuff_write.
+
+Addresses-Coverity: ("Resource Leak")
+Fixes: a7c3aa1509e2 ("brcmfmac: Remove brcmf_sdiod_addrprep()")
+Signed-off-by: Colin Ian King <colin.king@canonical.com>
+Reviewed-by: Mukesh Ojha <mojha@codeaurora.org>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -617,15 +617,13 @@ int brcmf_sdiod_send_buf(struct brcmf_sd
+       err = brcmf_sdiod_set_backplane_window(sdiodev, addr);
+       if (err)
+-              return err;
++              goto out;
+       addr &= SBSDIO_SB_OFT_ADDR_MASK;
+       addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+-      if (!err)
+-              err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func2, addr,
+-                                             mypkt);
+-
++      err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func2, addr, mypkt);
++out:
+       brcmu_pkt_buf_free_skb(mypkt);
+       return err;
index e1e054ffe64b43346d2a5d7523b490dc247dfd7b..d431d7e700e8818b66f6dac405dfeed1a9ebea4e 100644 (file)
@@ -13,7 +13,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
 
 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
 
 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1408,6 +1408,7 @@ int __init brcmf_core_init(void)
+@@ -1436,6 +1436,7 @@ int __init brcmf_core_init(void)
  {
        if (!schedule_work(&brcmf_driver_work))
                return -EBUSY;
  {
        if (!schedule_work(&brcmf_driver_work))
                return -EBUSY;
diff --git a/package/kernel/mac80211/patches/brcm/865-brcmfmac-get-RAM-info-right-before-downloading-PCIe-.patch b/package/kernel/mac80211/patches/brcm/865-brcmfmac-get-RAM-info-right-before-downloading-PCIe-.patch
new file mode 100644 (file)
index 0000000..88b9807
--- /dev/null
@@ -0,0 +1,70 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Subject: [PATCH] brcmfmac: get RAM info right before downloading PCIe firmware
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It's important as brcmf_chip_get_raminfo() also makes sure that memory
+is properly setup. Without it the firmware could report invalid RAM
+address like 0x04000001.
+
+During a normal brcmfmac lifetime brcmf_chip_get_raminfo() is called on
+probe by the brcmf_chip_recognition(). This change allows implementing
+further improvements like handling errors by resetting a device with
+the brcmf_pcie_reset_device() and redownloading a firmware afterwards.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 6 ++++--
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h | 1 +
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 6 ++++++
+ 3 files changed, 11 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
+@@ -707,8 +707,10 @@ static u32 brcmf_chip_tcm_rambase(struct
+       return 0;
+ }
+-static int brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
++int brcmf_chip_get_raminfo(struct brcmf_chip *pub)
+ {
++      struct brcmf_chip_priv *ci = container_of(pub, struct brcmf_chip_priv,
++                                                pub);
+       struct brcmf_core_priv *mem_core;
+       struct brcmf_core *mem;
+@@ -990,7 +992,7 @@ static int brcmf_chip_recognition(struct
+               brcmf_chip_set_passive(&ci->pub);
+       }
+-      return brcmf_chip_get_raminfo(ci);
++      return brcmf_chip_get_raminfo(&ci->pub);
+ }
+ static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id)
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
+@@ -80,6 +80,7 @@ struct brcmf_buscore_ops {
+       void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec);
+ };
++int brcmf_chip_get_raminfo(struct brcmf_chip *pub);
+ struct brcmf_chip *brcmf_chip_attach(void *ctx,
+                                    const struct brcmf_buscore_ops *ops);
+ void brcmf_chip_detach(struct brcmf_chip *chip);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+@@ -1762,6 +1762,12 @@ static void brcmf_pcie_setup(struct devi
+       nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len;
+       kfree(fwreq);
++      ret = brcmf_chip_get_raminfo(devinfo->ci);
++      if (ret) {
++              brcmf_err(bus, "Failed to get RAM info\n");
++              goto fail;
++      }
++
+       /* Some of the firmwares have the size of the memory of the device
+        * defined inside the firmware. This is because part of the memory in
+        * the device is shared and the devision is determined by FW. Parse