mac80211: brcmfmac: backport fixes for 4.7 and 4.8
authorRafał Miłecki <zajec5@gmail.com>
Fri, 17 Jun 2016 06:23:06 +0000 (06:23 +0000)
committerRafał Miłecki <zajec5@gmail.com>
Fri, 17 Jun 2016 06:23:06 +0000 (06:23 +0000)
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
SVN-Revision: 49380

package/kernel/mac80211/patches/350-0001-brcmfmac-add-fallback-for-devices-that-do-not-report.patch [new file with mode: 0644]
package/kernel/mac80211/patches/350-0002-brcmfmac-add-eth_type_trans-back-for-PCIe-full-dongl.patch [new file with mode: 0644]
package/kernel/mac80211/patches/351-0001-brcmfmac-testing-the-wrong-variable-in-brcmf_rx_hdrp.patch [new file with mode: 0644]
package/kernel/mac80211/patches/351-0003-brcmfmac-Fix-kernel-oops-in-failed-chip_attach.patch [new file with mode: 0644]
package/kernel/mac80211/patches/351-0004-brcmfmac-Fix-did-not-remove-int-handler-warning.patch [new file with mode: 0644]
package/kernel/mac80211/patches/860-brcmfmac-add-missing-eth_type_trans-call.patch [deleted file]
package/kernel/mac80211/patches/863-brcmfmac-Disable-power-management.patch

diff --git a/package/kernel/mac80211/patches/350-0001-brcmfmac-add-fallback-for-devices-that-do-not-report.patch b/package/kernel/mac80211/patches/350-0001-brcmfmac-add-fallback-for-devices-that-do-not-report.patch
new file mode 100644 (file)
index 0000000..7b299d5
--- /dev/null
@@ -0,0 +1,52 @@
+From: Jaap Jan Meijer <jjmeijer88@gmail.com>
+Date: Thu, 12 May 2016 18:25:08 +0200
+Subject: [PATCH] brcmfmac: add fallback for devices that do not report
+ per-chain values
+
+If brcmf_cfg80211_get_station fails to determine the RSSI from the
+per-chain values get the value individually as a fallback.
+
+Fixes: 1f0dc59a6de9 ("brcmfmac: rework .get_station() callback")
+Signed-off-by: Jaap Jan Meijer <jjmeijer88@gmail.com>
+Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -2480,12 +2480,14 @@ brcmf_cfg80211_get_station(struct wiphy
+                          const u8 *mac, struct station_info *sinfo)
+ {
+       struct brcmf_if *ifp = netdev_priv(ndev);
++      struct brcmf_scb_val_le scb_val;
+       s32 err = 0;
+       struct brcmf_sta_info_le sta_info_le;
+       u32 sta_flags;
+       u32 is_tdls_peer;
+       s32 total_rssi;
+       s32 count_rssi;
++      int rssi;
+       u32 i;
+       brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
+@@ -2569,6 +2571,20 @@ brcmf_cfg80211_get_station(struct wiphy
+                       sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
+                       total_rssi /= count_rssi;
+                       sinfo->signal = total_rssi;
++              } else if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
++                      &ifp->vif->sme_state)) {
++                      memset(&scb_val, 0, sizeof(scb_val));
++                      err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,
++                                                   &scb_val, sizeof(scb_val));
++                      if (err) {
++                              brcmf_err("Could not get rssi (%d)\n", err);
++                              goto done;
++                      } else {
++                              rssi = le32_to_cpu(scb_val.val);
++                              sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
++                              sinfo->signal = rssi;
++                              brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);
++                      }
+               }
+       }
+ done:
diff --git a/package/kernel/mac80211/patches/350-0002-brcmfmac-add-eth_type_trans-back-for-PCIe-full-dongl.patch b/package/kernel/mac80211/patches/350-0002-brcmfmac-add-eth_type_trans-back-for-PCIe-full-dongl.patch
new file mode 100644 (file)
index 0000000..db8112d
--- /dev/null
@@ -0,0 +1,87 @@
+From: Franky Lin <franky.lin@broadcom.com>
+Date: Thu, 2 Jun 2016 02:00:27 -0700
+Subject: [PATCH] brcmfmac: add eth_type_trans back for PCIe full dongle
+
+A regression was introduced in commit 9c349892ccc9 ("brcmfmac: revise
+handling events in receive path") which moves eth_type_trans() call
+to brcmf_rx_frame(). Msgbuf layer doesn't use brcmf_rx_frame() but invokes
+brcmf_netif_rx() directly. In such case the Ethernet header was not
+stripped out resulting in null pointer dereference in the networking
+stack.
+
+BUG: unable to handle kernel NULL pointer dereference at 0000000000000048
+IP: [<ffffffff814c3ce6>] enqueue_to_backlog+0x56/0x260
+PGD 0
+Oops: 0000 [#1] PREEMPT SMP
+Modules linked in: fuse ipt_MASQUERADE nf_nat_masquerade_ipv4
+iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 xt_addrtype
+[...]
+rtsx_pci scsi_mod usbcore usb_common i8042 serio nvme nvme_core
+CPU: 7 PID: 1340 Comm: irq/136-brcmf_p Not tainted 4.7.0-rc1-mainline #1
+Hardware name: Dell Inc. XPS 15 9550/0N7TVV, BIOS 01.02.00 04/07/2016
+task: ffff8804a0c5bd00 ti: ffff88049e124000 task.ti: ffff88049e124000
+RIP: 0010:[<ffffffff814c3ce6>] [<ffffffff814c3ce6>]
+enqueue_to_backlog+0x56/0x260
+RSP: 0018:ffff88049e127ca0 EFLAGS: 00010046
+RAX: 0000000000000000 RBX: ffff8804bddd7c40 RCX: 000000000000002f
+RDX: 0000000000000000 RSI: 0000000000000007 RDI: ffff8804bddd7d4c
+RBP: ffff88049e127ce8 R08: 0000000000000000 R09: 0000000000000000
+R10: ffff8804bddd12c0 R11: 000000000000149e R12: 0000000000017c40
+R13: ffff88049e127d08 R14: ffff8804a9bd6d00 R15: ffff8804bddd7d4c
+FS: 0000000000000000(0000) GS:ffff8804bddc0000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 0000000000000048 CR3: 0000000001806000 CR4: 00000000003406e0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+Stack:
+ffff8804bdddad00 ffff8804ad089e00 0000000000000000 0000000000000282
+0000000000000000 ffff8804a9bd6d00 ffff8804a1b27e00 ffff8804a9bd6d00
+ffff88002ee88000 ffff88049e127d28 ffffffff814c3f3b ffffffff81311fc3
+Call Trace:
+[<ffffffff814c3f3b>] netif_rx_internal+0x4b/0x170
+[<ffffffff81311fc3>] ? swiotlb_tbl_unmap_single+0xf3/0x120
+[<ffffffff814c5467>] netif_rx_ni+0x27/0xc0
+[<ffffffffa08519e9>] brcmf_netif_rx+0x49/0x70 [brcmfmac]
+[<ffffffffa08564d4>] brcmf_msgbuf_process_rx+0x2b4/0x570 [brcmfmac]
+[<ffffffff81020017>] ? __xen_set_pgd_hyper+0x57/0xd0
+[<ffffffff810d60b0>] ? irq_forced_thread_fn+0x70/0x70
+[<ffffffffa0857381>] brcmf_proto_msgbuf_rx_trigger+0x31/0xe0 [brcmfmac]
+[<ffffffffa0861e8f>] brcmf_pcie_isr_thread+0x7f/0x110 [brcmfmac]
+[<ffffffff810d60d0>] irq_thread_fn+0x20/0x50
+[<ffffffff810d63ad>] irq_thread+0x12d/0x1c0
+[<ffffffff815d07d5>] ? __schedule+0x2f5/0x7a0
+[<ffffffff810d61d0>] ? wake_threads_waitq+0x30/0x30
+[<ffffffff810d6280>] ? irq_thread_dtor+0xb0/0xb0
+[<ffffffff81098ea8>] kthread+0xd8/0xf0
+[<ffffffff815d4b7f>] ret_from_fork+0x1f/0x40
+[<ffffffff81098dd0>] ? kthread_worker_fn+0x170/0x170
+Code: 1c f5 60 9a 8e 81 9c 58 0f 1f 44 00 00 48 89 45 d0 fa 66 0f 1f
+44 00 00 4c 8d bb 0c 01 00 00 4c 89 ff e8 5e 08 11 00 49 8b 56 20 <48>
+8b 52 48 83 e2 01 74 10 8b 8b 08 01 00 00 8b 15 59 c5 42 00
+RIP [<ffffffff814c3ce6>] enqueue_to_backlog+0x56/0x260
+RSP <ffff88049e127ca0>
+CR2: 0000000000000048
+
+Fixes: 9c349892ccc9 ("brcmfmac: revise handling events in receive path")
+Reported-by: Rafal Milecki <zajec5@gmail.com>
+Reported-by: Grey Christoforo <grey@christoforo.net>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Signed-off-by: Franky Lin <franky.lin@broadcom.com>
+[arend@broadcom.com: rephrased the commit message]
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+@@ -1157,6 +1157,8 @@ brcmf_msgbuf_process_rx_complete(struct
+               brcmu_pkt_buf_free_skb(skb);
+               return;
+       }
++
++      skb->protocol = eth_type_trans(skb, ifp->ndev);
+       brcmf_netif_rx(ifp, skb);
+ }
diff --git a/package/kernel/mac80211/patches/351-0001-brcmfmac-testing-the-wrong-variable-in-brcmf_rx_hdrp.patch b/package/kernel/mac80211/patches/351-0001-brcmfmac-testing-the-wrong-variable-in-brcmf_rx_hdrp.patch
new file mode 100644 (file)
index 0000000..11c65a4
--- /dev/null
@@ -0,0 +1,39 @@
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Tue, 19 Apr 2016 07:25:43 -0700
+Subject: [PATCH] brcmfmac: testing the wrong variable in brcmf_rx_hdrpull()
+
+Smatch complains about this code:
+
+    drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c:335 brcmf_rx_hdrpull()
+    error: we previously assumed '*ifp' could be null (see line 333)
+
+The problem is that we recently changed these from "ifp" to "*ifp" but
+there was one that we didn't update.
+
+-       if (ret || !ifp || !ifp->ndev) {
++       if (ret || !(*ifp) || !(*ifp)->ndev) {
+                if (ret != -ENODATA && ifp)
+                                       ^^^
+-                       ifp->stats.rx_errors++;
++                       (*ifp)->stats.rx_errors++;
+
+I have updated it to *ifp as well.  We always call this function is a
+non-NULL "ifp" pointer, btw.
+
+Fixes: c462ebcdfe42 ('brcmfmac: create common function for handling brcmf_proto_hdrpull()')
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Acked-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -331,7 +331,7 @@ static int brcmf_rx_hdrpull(struct brcmf
+       ret = brcmf_proto_hdrpull(drvr, true, skb, ifp);
+       if (ret || !(*ifp) || !(*ifp)->ndev) {
+-              if (ret != -ENODATA && ifp)
++              if (ret != -ENODATA && *ifp)
+                       (*ifp)->stats.rx_errors++;
+               brcmu_pkt_buf_free_skb(skb);
+               return -ENODATA;
diff --git a/package/kernel/mac80211/patches/351-0003-brcmfmac-Fix-kernel-oops-in-failed-chip_attach.patch b/package/kernel/mac80211/patches/351-0003-brcmfmac-Fix-kernel-oops-in-failed-chip_attach.patch
new file mode 100644 (file)
index 0000000..59f1e42
--- /dev/null
@@ -0,0 +1,88 @@
+From: Christian Daudt <csd@broadcom.com>
+Date: Wed, 11 May 2016 15:06:48 -0700
+Subject: [PATCH] brcmfmac: Fix kernel oops in failed chip_attach
+
+When chip attach fails, brcmf_sdiod_intr_unregister is being called
+but that is too early as sdiodev->settings has not been set yet
+nor has brcmf_sdiod_intr_register been called.
+Change to use oob_irq_requested + newly created sd_irq_requested
+to decide on what to unregister at intr_unregister time.
+
+Steps to reproduce problem:
+- modprobe brcmfmac using buggy FW
+- rmmod brcmfmac
+- modprobe brcmfmac again.
+
+If done with a buggy firmware, brcm_chip_attach will fail on the
+2nd modprobe triggering the call to intr_unregister and the
+kernel oops when attempting to de-reference sdiodev->settings->bus.sdio
+which has not yet been set.
+
+Signed-off-by: Christian Daudt <csd@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -166,6 +166,7 @@ int brcmf_sdiod_intr_register(struct brc
+               sdio_claim_irq(sdiodev->func[1], brcmf_sdiod_ib_irqhandler);
+               sdio_claim_irq(sdiodev->func[2], brcmf_sdiod_dummy_irqhandler);
+               sdio_release_host(sdiodev->func[1]);
++              sdiodev->sd_irq_requested = true;
+       }
+       return 0;
+@@ -173,27 +174,30 @@ int brcmf_sdiod_intr_register(struct brc
+ int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev)
+ {
+-      struct brcmfmac_sdio_pd *pdata;
+-      brcmf_dbg(SDIO, "Entering\n");
++      brcmf_dbg(SDIO, "Entering oob=%d sd=%d\n",
++                sdiodev->oob_irq_requested,
++                sdiodev->sd_irq_requested);
+-      pdata = &sdiodev->settings->bus.sdio;
+-      if (pdata->oob_irq_supported) {
++      if (sdiodev->oob_irq_requested) {
++              struct brcmfmac_sdio_pd *pdata;
++
++              pdata = &sdiodev->settings->bus.sdio;
+               sdio_claim_host(sdiodev->func[1]);
+               brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
+               brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
+               sdio_release_host(sdiodev->func[1]);
+-              if (sdiodev->oob_irq_requested) {
+-                      sdiodev->oob_irq_requested = false;
+-                      if (sdiodev->irq_wake) {
+-                              disable_irq_wake(pdata->oob_irq_nr);
+-                              sdiodev->irq_wake = false;
+-                      }
+-                      free_irq(pdata->oob_irq_nr, &sdiodev->func[1]->dev);
+-                      sdiodev->irq_en = false;
++              sdiodev->oob_irq_requested = false;
++              if (sdiodev->irq_wake) {
++                      disable_irq_wake(pdata->oob_irq_nr);
++                      sdiodev->irq_wake = false;
+               }
+-      } else {
++              free_irq(pdata->oob_irq_nr, &sdiodev->func[1]->dev);
++              sdiodev->irq_en = false;
++      }
++
++      if (sdiodev->sd_irq_requested) {
+               sdio_claim_host(sdiodev->func[1]);
+               sdio_release_irq(sdiodev->func[2]);
+               sdio_release_irq(sdiodev->func[1]);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+@@ -186,6 +186,7 @@ struct brcmf_sdio_dev {
+       struct brcmf_bus *bus_if;
+       struct brcmf_mp_device *settings;
+       bool oob_irq_requested;
++      bool sd_irq_requested;
+       bool irq_en;                    /* irq enable flags */
+       spinlock_t irq_en_lock;
+       bool irq_wake;                  /* irq wake enable flags */
diff --git a/package/kernel/mac80211/patches/351-0004-brcmfmac-Fix-did-not-remove-int-handler-warning.patch b/package/kernel/mac80211/patches/351-0004-brcmfmac-Fix-did-not-remove-int-handler-warning.patch
new file mode 100644 (file)
index 0000000..3aabf59
--- /dev/null
@@ -0,0 +1,83 @@
+From: Christian Daudt <csd@broadcom.com>
+Date: Wed, 11 May 2016 15:06:49 -0700
+Subject: [PATCH] brcmfmac: Fix 'did not remove int handler' warning
+
+brcmf_sdiod_intr_unregister call that removes both func1 and
+func2 interrupt handlers only called when brcmf_ops_sdio_remove
+is called for func 1 (which is the 2nd call) but sdio is expecting
+it to be removed at the end of each sdio_remove call.
+This is causing 'rmmod bcmrfmac' on a 4356-sdio chip to complain
+with:
+WARNING: driver brcmfmac did not remove its interrupt handler!
+
+The modification makes calling brcmf_sdiod_intr_unregister multiple
+times harmless by clearing the variables that track if interrupt
+handlers have been installed, and then calls it on every
+brcmf_ops_sdio_remove call instead of just remove for func 1.
+
+Signed-off-by: Christian Daudt <csd@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -172,7 +172,7 @@ int brcmf_sdiod_intr_register(struct brc
+       return 0;
+ }
+-int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev)
++void brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev)
+ {
+       brcmf_dbg(SDIO, "Entering oob=%d sd=%d\n",
+@@ -195,6 +195,7 @@ int brcmf_sdiod_intr_unregister(struct b
+               }
+               free_irq(pdata->oob_irq_nr, &sdiodev->func[1]->dev);
+               sdiodev->irq_en = false;
++              sdiodev->oob_irq_requested = false;
+       }
+       if (sdiodev->sd_irq_requested) {
+@@ -202,9 +203,8 @@ int brcmf_sdiod_intr_unregister(struct b
+               sdio_release_irq(sdiodev->func[2]);
+               sdio_release_irq(sdiodev->func[1]);
+               sdio_release_host(sdiodev->func[1]);
++              sdiodev->sd_irq_requested = false;
+       }
+-
+-      return 0;
+ }
+ void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
+@@ -1200,12 +1200,17 @@ static void brcmf_ops_sdio_remove(struct
+       brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
+       brcmf_dbg(SDIO, "Function: %d\n", func->num);
+-      if (func->num != 1)
+-              return;
+-
+       bus_if = dev_get_drvdata(&func->dev);
+       if (bus_if) {
+               sdiodev = bus_if->bus_priv.sdio;
++
++              /* start by unregistering irqs */
++              brcmf_sdiod_intr_unregister(sdiodev);
++
++              if (func->num != 1)
++                      return;
++
++              /* only proceed with rest of cleanup if func 1 */
+               brcmf_sdiod_remove(sdiodev);
+               dev_set_drvdata(&sdiodev->func[1]->dev, NULL);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+@@ -294,7 +294,7 @@ struct sdpcmd_regs {
+ /* Register/deregister interrupt handler. */
+ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev);
+-int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev);
++void brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev);
+ /* sdio device register access interface */
+ u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
diff --git a/package/kernel/mac80211/patches/860-brcmfmac-add-missing-eth_type_trans-call.patch b/package/kernel/mac80211/patches/860-brcmfmac-add-missing-eth_type_trans-call.patch
deleted file mode 100644 (file)
index 7100820..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
-Subject: [PATCH] brcmfmac: add missing eth_type_trans call
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-There are 2 protocols supported by brcmfmac and msgbuf one was missing a
-proper skb setup before passing it to the netif. This was triggering
-"NULL pointer dereference".
-
-Fixes: 9c349892ccc9 ("brcmfmac: revise handling events in receive path")
-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
----
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
-@@ -1157,6 +1157,9 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
-               brcmu_pkt_buf_free_skb(skb);
-               return;
-       }
-+
-+      skb->protocol = eth_type_trans(skb, ifp->ndev);
-+
-       brcmf_netif_rx(ifp, skb);
- }
index 1615202..a24601f 100644 (file)
@@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.org>
 
 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -2651,6 +2651,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip
+@@ -2667,6 +2667,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip
         * preference in cfg struct to apply this to
         * FW later while initializing the dongle
         */