mac80211: brcmfmac: add beamforming support
authorRafał Miłecki <zajec5@gmail.com>
Sun, 10 Jan 2016 01:30:13 +0000 (01:30 +0000)
committerRafał Miłecki <zajec5@gmail.com>
Sun, 10 Jan 2016 01:30:13 +0000 (01:30 +0000)
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
SVN-Revision: 48168

24 files changed:
package/kernel/mac80211/patches/373-brcm80211-Add-support-for-brcm4371.patch [new file with mode: 0644]
package/kernel/mac80211/patches/374-0001-brcmfmac-Add-support-for-the-BCM4359-11ac-RSDB-PCIE-.patch [new file with mode: 0644]
package/kernel/mac80211/patches/374-0002-brcmfmac-Simplify-and-fix-usage-of-brcmf_ifname.patch [new file with mode: 0644]
package/kernel/mac80211/patches/374-0003-brcmfmac-Remove-unnecessary-check-from-start_xmit.patch [new file with mode: 0644]
package/kernel/mac80211/patches/374-0004-brcmfmac-Remove-unncessary-variable-irq_requested.patch [new file with mode: 0644]
package/kernel/mac80211/patches/374-0005-brcmfmac-Disable-runtime-pm-for-USB.patch [new file with mode: 0644]
package/kernel/mac80211/patches/374-0006-brcmfmac-Add-RSDB-support.patch [new file with mode: 0644]
package/kernel/mac80211/patches/374-0007-brcmfmac-Use-consistent-naming-for-bsscfgidx.patch [new file with mode: 0644]
package/kernel/mac80211/patches/374-0008-brcmfmac-Use-new-methods-for-pcie-Power-Management.patch [new file with mode: 0644]
package/kernel/mac80211/patches/374-0009-brcmfmac-Add-wowl-wake-indication-report.patch [new file with mode: 0644]
package/kernel/mac80211/patches/375-brcmfmac-constify-brcmf_bus_ops-structures.patch [new file with mode: 0644]
package/kernel/mac80211/patches/376-0001-brcmfmac-Cleanup-ssid-storage.patch [new file with mode: 0644]
package/kernel/mac80211/patches/376-0002-brcmfmac-Return-actual-error-by-fwil.patch [new file with mode: 0644]
package/kernel/mac80211/patches/376-0003-brcmfmac-Change-error-print-on-wlan0-existence.patch [new file with mode: 0644]
package/kernel/mac80211/patches/376-0004-brcmfmac-no-retries-on-rxglom-superframe-errors.patch [new file with mode: 0644]
package/kernel/mac80211/patches/376-0005-brcmfmac-Remove-redundant-parameter-action-from-scan.patch [new file with mode: 0644]
package/kernel/mac80211/patches/376-0006-brcmfmac-Cleanup-roaming-configuration.patch [new file with mode: 0644]
package/kernel/mac80211/patches/376-0007-brcmfmac-Add-beamforming-support.patch [new file with mode: 0644]
package/kernel/mac80211/patches/376-0008-brcmfmac-assure-net_ratelimit-is-declared-before-use.patch [new file with mode: 0644]
package/kernel/mac80211/patches/376-0009-brcmfmac-Unify-methods-to-define-and-map-firmware-fi.patch [new file with mode: 0644]
package/kernel/mac80211/patches/376-0010-brcmfmac-Fix-double-free-on-exception-at-module-load.patch [new file with mode: 0644]
package/kernel/mac80211/patches/377-brcmfmac-only-lock-and-unlock-fws-if-fws-is-not-null.patch [new file with mode: 0644]
package/kernel/mac80211/patches/860-brcmfmac-use-bcm47xx-platform-NVRAM-as-fallback.patch
package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch

diff --git a/package/kernel/mac80211/patches/373-brcm80211-Add-support-for-brcm4371.patch b/package/kernel/mac80211/patches/373-brcm80211-Add-support-for-brcm4371.patch
new file mode 100644 (file)
index 0000000..ea6fad1
--- /dev/null
@@ -0,0 +1,78 @@
+From: Eric Caruso <ejcaruso@google.com>
+Date: Wed, 14 Oct 2015 12:34:11 -0700
+Subject: [PATCH] brcm80211: Add support for brcm4371
+
+This is a new Broadcom chip and we should be able to recognize it.
+
+Signed-off-by: Eric Caruso <ejcaruso@google.com>
+Acked-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+@@ -682,6 +682,7 @@ static u32 brcmf_chip_tcm_rambase(struct
+       case BRCM_CC_43570_CHIP_ID:
+       case BRCM_CC_4358_CHIP_ID:
+       case BRCM_CC_43602_CHIP_ID:
++      case BRCM_CC_4371_CHIP_ID:
+               return 0x180000;
+       case BRCM_CC_4365_CHIP_ID:
+       case BRCM_CC_4366_CHIP_ID:
+--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+@@ -59,6 +59,8 @@ enum brcmf_pcie_state {
+ #define BRCMF_PCIE_4365_NVRAM_NAME            "brcm/brcmfmac4365b-pcie.txt"
+ #define BRCMF_PCIE_4366_FW_NAME                       "brcm/brcmfmac4366b-pcie.bin"
+ #define BRCMF_PCIE_4366_NVRAM_NAME            "brcm/brcmfmac4366b-pcie.txt"
++#define BRCMF_PCIE_4371_FW_NAME                       "brcm/brcmfmac4371-pcie.bin"
++#define BRCMF_PCIE_4371_NVRAM_NAME            "brcm/brcmfmac4371-pcie.txt"
+ #define BRCMF_PCIE_FW_UP_TIMEOUT              2000 /* msec */
+@@ -212,6 +214,8 @@ MODULE_FIRMWARE(BRCMF_PCIE_4365_FW_NAME)
+ MODULE_FIRMWARE(BRCMF_PCIE_4365_NVRAM_NAME);
+ MODULE_FIRMWARE(BRCMF_PCIE_4366_FW_NAME);
+ MODULE_FIRMWARE(BRCMF_PCIE_4366_NVRAM_NAME);
++MODULE_FIRMWARE(BRCMF_PCIE_4371_FW_NAME);
++MODULE_FIRMWARE(BRCMF_PCIE_4371_NVRAM_NAME);
+ struct brcmf_pcie_console {
+@@ -1521,6 +1525,10 @@ static int brcmf_pcie_get_fwnames(struct
+               fw_name = BRCMF_PCIE_4366_FW_NAME;
+               nvram_name = BRCMF_PCIE_4366_NVRAM_NAME;
+               break;
++      case BRCM_CC_4371_CHIP_ID:
++              fw_name = BRCMF_PCIE_4371_FW_NAME;
++              nvram_name = BRCMF_PCIE_4371_NVRAM_NAME;
++              break;
+       default:
+               brcmf_err("Unsupported chip 0x%04x\n", devinfo->ci->chip);
+               return -ENODEV;
+@@ -2060,6 +2068,7 @@ static struct pci_device_id brcmf_pcie_d
+       BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_DEVICE_ID),
+       BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID),
+       BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID),
++      BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID),
+       { /* end: all zeroes */ }
+ };
+--- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
++++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+@@ -50,6 +50,7 @@
+ #define BRCM_CC_43602_CHIP_ID         43602
+ #define BRCM_CC_4365_CHIP_ID          0x4365
+ #define BRCM_CC_4366_CHIP_ID          0x4366
++#define BRCM_CC_4371_CHIP_ID          0x4371
+ /* USB Device IDs */
+ #define BRCM_USB_43143_DEVICE_ID      0xbd1e
+@@ -75,6 +76,7 @@
+ #define BRCM_PCIE_4366_DEVICE_ID      0x43c3
+ #define BRCM_PCIE_4366_2G_DEVICE_ID   0x43c4
+ #define BRCM_PCIE_4366_5G_DEVICE_ID   0x43c5
++#define BRCM_PCIE_4371_DEVICE_ID      0x440d
+ /* brcmsmac IDs */
diff --git a/package/kernel/mac80211/patches/374-0001-brcmfmac-Add-support-for-the-BCM4359-11ac-RSDB-PCIE-.patch b/package/kernel/mac80211/patches/374-0001-brcmfmac-Add-support-for-the-BCM4359-11ac-RSDB-PCIE-.patch
new file mode 100644 (file)
index 0000000..221bae6
--- /dev/null
@@ -0,0 +1,78 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Thu, 29 Oct 2015 20:33:11 +0100
+Subject: [PATCH] brcmfmac: Add support for the BCM4359 11ac RSDB PCIE device.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+@@ -681,6 +681,7 @@ static u32 brcmf_chip_tcm_rambase(struct
+       case BRCM_CC_43569_CHIP_ID:
+       case BRCM_CC_43570_CHIP_ID:
+       case BRCM_CC_4358_CHIP_ID:
++      case BRCM_CC_4359_CHIP_ID:
+       case BRCM_CC_43602_CHIP_ID:
+       case BRCM_CC_4371_CHIP_ID:
+               return 0x180000;
+--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+@@ -55,6 +55,8 @@ enum brcmf_pcie_state {
+ #define BRCMF_PCIE_43570_NVRAM_NAME           "brcm/brcmfmac43570-pcie.txt"
+ #define BRCMF_PCIE_4358_FW_NAME                       "brcm/brcmfmac4358-pcie.bin"
+ #define BRCMF_PCIE_4358_NVRAM_NAME            "brcm/brcmfmac4358-pcie.txt"
++#define BRCMF_PCIE_4359_FW_NAME                       "brcm/brcmfmac4359-pcie.bin"
++#define BRCMF_PCIE_4359_NVRAM_NAME            "brcm/brcmfmac4359-pcie.txt"
+ #define BRCMF_PCIE_4365_FW_NAME                       "brcm/brcmfmac4365b-pcie.bin"
+ #define BRCMF_PCIE_4365_NVRAM_NAME            "brcm/brcmfmac4365b-pcie.txt"
+ #define BRCMF_PCIE_4366_FW_NAME                       "brcm/brcmfmac4366b-pcie.bin"
+@@ -210,6 +212,8 @@ MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME
+ MODULE_FIRMWARE(BRCMF_PCIE_43570_NVRAM_NAME);
+ MODULE_FIRMWARE(BRCMF_PCIE_4358_FW_NAME);
+ MODULE_FIRMWARE(BRCMF_PCIE_4358_NVRAM_NAME);
++MODULE_FIRMWARE(BRCMF_PCIE_4359_FW_NAME);
++MODULE_FIRMWARE(BRCMF_PCIE_4359_NVRAM_NAME);
+ MODULE_FIRMWARE(BRCMF_PCIE_4365_FW_NAME);
+ MODULE_FIRMWARE(BRCMF_PCIE_4365_NVRAM_NAME);
+ MODULE_FIRMWARE(BRCMF_PCIE_4366_FW_NAME);
+@@ -1517,6 +1521,10 @@ static int brcmf_pcie_get_fwnames(struct
+               fw_name = BRCMF_PCIE_4358_FW_NAME;
+               nvram_name = BRCMF_PCIE_4358_NVRAM_NAME;
+               break;
++      case BRCM_CC_4359_CHIP_ID:
++              fw_name = BRCMF_PCIE_4359_FW_NAME;
++              nvram_name = BRCMF_PCIE_4359_NVRAM_NAME;
++              break;
+       case BRCM_CC_4365_CHIP_ID:
+               fw_name = BRCMF_PCIE_4365_FW_NAME;
+               nvram_name = BRCMF_PCIE_4365_NVRAM_NAME;
+@@ -2058,6 +2066,7 @@ static struct pci_device_id brcmf_pcie_d
+       BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID),
+       BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID),
+       BRCMF_PCIE_DEVICE(BRCM_PCIE_4358_DEVICE_ID),
++      BRCMF_PCIE_DEVICE(BRCM_PCIE_4359_DEVICE_ID),
+       BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_DEVICE_ID),
+       BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID),
+       BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID),
+--- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
++++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+@@ -47,6 +47,7 @@
+ #define BRCM_CC_43569_CHIP_ID         43569
+ #define BRCM_CC_43570_CHIP_ID         43570
+ #define BRCM_CC_4358_CHIP_ID          0x4358
++#define BRCM_CC_4359_CHIP_ID          0x4359
+ #define BRCM_CC_43602_CHIP_ID         43602
+ #define BRCM_CC_4365_CHIP_ID          0x4365
+ #define BRCM_CC_4366_CHIP_ID          0x4366
+@@ -66,6 +67,7 @@
+ #define BRCM_PCIE_43567_DEVICE_ID     0x43d3
+ #define BRCM_PCIE_43570_DEVICE_ID     0x43d9
+ #define BRCM_PCIE_4358_DEVICE_ID      0x43e9
++#define BRCM_PCIE_4359_DEVICE_ID      0x43ef
+ #define BRCM_PCIE_43602_DEVICE_ID     0x43ba
+ #define BRCM_PCIE_43602_2G_DEVICE_ID  0x43bb
+ #define BRCM_PCIE_43602_5G_DEVICE_ID  0x43bc
diff --git a/package/kernel/mac80211/patches/374-0002-brcmfmac-Simplify-and-fix-usage-of-brcmf_ifname.patch b/package/kernel/mac80211/patches/374-0002-brcmfmac-Simplify-and-fix-usage-of-brcmf_ifname.patch
new file mode 100644 (file)
index 0000000..331896b
--- /dev/null
@@ -0,0 +1,110 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Thu, 29 Oct 2015 20:33:12 +0100
+Subject: [PATCH] brcmfmac: Simplify and fix usage of brcmf_ifname.
+
+brcmf_ifname is a debug function to return a name related to an ifp,
+but is using a rather complex implementation. It was also used
+wrongly from bcdc as it did not use the bsscfgidx as it was supposed
+to, but bssidx. This patch fixes that bug and simplifies
+brcmf_ifname.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
+@@ -187,7 +187,8 @@ retry:
+               goto retry;
+       if (id != bcdc->reqid) {
+               brcmf_err("%s: unexpected request id %d (expected %d)\n",
+-                        brcmf_ifname(drvr, ifidx), id, bcdc->reqid);
++                        brcmf_ifname(brcmf_get_ifp(drvr, ifidx)), id,
++                        bcdc->reqid);
+               ret = -EINVAL;
+               goto done;
+       }
+@@ -234,7 +235,8 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p
+       if (id != bcdc->reqid) {
+               brcmf_err("%s: unexpected request id %d (expected %d)\n",
+-                        brcmf_ifname(drvr, ifidx), id, bcdc->reqid);
++                        brcmf_ifname(brcmf_get_ifp(drvr, ifidx)), id,
++                        bcdc->reqid);
+               ret = -EINVAL;
+               goto done;
+       }
+@@ -298,13 +300,13 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
+       if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) !=
+           BCDC_PROTO_VER) {
+               brcmf_err("%s: non-BCDC packet received, flags 0x%x\n",
+-                        brcmf_ifname(drvr, tmp_if->ifidx), h->flags);
++                        brcmf_ifname(tmp_if), h->flags);
+               return -EBADE;
+       }
+       if (h->flags & BCDC_FLAG_SUM_GOOD) {
+               brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n",
+-                        brcmf_ifname(drvr, tmp_if->ifidx), h->flags);
++                        brcmf_ifname(tmp_if), h->flags);
+               pktbuf->ip_summed = CHECKSUM_UNNECESSARY;
+       }
+--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+@@ -66,20 +66,13 @@ static int brcmf_p2p_enable;
+ module_param_named(p2pon, brcmf_p2p_enable, int, 0);
+ MODULE_PARM_DESC(p2pon, "enable legacy p2p management functionality");
+-char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
++char *brcmf_ifname(struct brcmf_if *ifp)
+ {
+-      if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
+-              brcmf_err("ifidx %d out of range\n", ifidx);
+-              return "<if_bad>";
+-      }
+-
+-      if (drvr->iflist[ifidx] == NULL) {
+-              brcmf_err("null i/f %d\n", ifidx);
++      if (!ifp)
+               return "<if_null>";
+-      }
+-      if (drvr->iflist[ifidx]->ndev)
+-              return drvr->iflist[ifidx]->ndev->name;
++      if (ifp->ndev)
++              return ifp->ndev->name;
+       return "<if_none>";
+ }
+@@ -237,14 +230,14 @@ static netdev_tx_t brcmf_netdev_start_xm
+               struct sk_buff *skb2;
+               brcmf_dbg(INFO, "%s: insufficient headroom\n",
+-                        brcmf_ifname(drvr, ifp->bssidx));
++                        brcmf_ifname(ifp));
+               drvr->bus_if->tx_realloc++;
+               skb2 = skb_realloc_headroom(skb, drvr->hdrlen);
+               dev_kfree_skb(skb);
+               skb = skb2;
+               if (skb == NULL) {
+                       brcmf_err("%s: skb_realloc_headroom failed\n",
+-                                brcmf_ifname(drvr, ifp->bssidx));
++                                brcmf_ifname(ifp));
+                       ret = -ENOMEM;
+                       goto done;
+               }
+--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
+@@ -205,7 +205,7 @@ struct brcmf_skb_reorder_data {
+ int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp);
+ /* Return pointer to interface name */
+-char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
++char *brcmf_ifname(struct brcmf_if *ifp);
+ struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx);
+ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
+ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
diff --git a/package/kernel/mac80211/patches/374-0003-brcmfmac-Remove-unnecessary-check-from-start_xmit.patch b/package/kernel/mac80211/patches/374-0003-brcmfmac-Remove-unnecessary-check-from-start_xmit.patch
new file mode 100644 (file)
index 0000000..4d60521
--- /dev/null
@@ -0,0 +1,32 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Thu, 29 Oct 2015 20:33:13 +0100
+Subject: [PATCH] brcmfmac: Remove unnecessary check from start_xmit.
+
+The brcmf_netdev_start_xmit checks if the ndev is still valid by
+checking if it still exists in database. This check is not needed
+and therefor removed.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+@@ -217,14 +217,6 @@ static netdev_tx_t brcmf_netdev_start_xm
+               goto done;
+       }
+-      if (!drvr->iflist[ifp->bssidx]) {
+-              brcmf_err("bad ifidx %d\n", ifp->bssidx);
+-              netif_stop_queue(ndev);
+-              dev_kfree_skb(skb);
+-              ret = -ENODEV;
+-              goto done;
+-      }
+-
+       /* Make sure there's enough room for any header */
+       if (skb_headroom(skb) < drvr->hdrlen) {
+               struct sk_buff *skb2;
diff --git a/package/kernel/mac80211/patches/374-0004-brcmfmac-Remove-unncessary-variable-irq_requested.patch b/package/kernel/mac80211/patches/374-0004-brcmfmac-Remove-unncessary-variable-irq_requested.patch
new file mode 100644 (file)
index 0000000..5030297
--- /dev/null
@@ -0,0 +1,49 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Thu, 29 Oct 2015 20:33:14 +0100
+Subject: [PATCH] brcmfmac: Remove unncessary variable irq_requested.
+
+The variable irq_requested is unneeded as the functionality
+it is providing, is also provided by the variable irq_allocated.
+
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+@@ -257,7 +257,6 @@ struct brcmf_pcie_core_info {
+ struct brcmf_pciedev_info {
+       enum brcmf_pcie_state state;
+       bool in_irq;
+-      bool irq_requested;
+       struct pci_dev *pdev;
+       char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
+       char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
+@@ -889,7 +888,6 @@ static int brcmf_pcie_request_irq(struct
+       brcmf_dbg(PCIE, "Enter\n");
+       /* is it a v1 or v2 implementation */
+-      devinfo->irq_requested = false;
+       pci_enable_msi(pdev);
+       if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1) {
+               if (request_threaded_irq(pdev->irq,
+@@ -912,7 +910,6 @@ static int brcmf_pcie_request_irq(struct
+                       return -EIO;
+               }
+       }
+-      devinfo->irq_requested = true;
+       devinfo->irq_allocated = true;
+       return 0;
+ }
+@@ -930,9 +927,6 @@ static void brcmf_pcie_release_irq(struc
+       pdev = devinfo->pdev;
+       brcmf_pcie_intr_disable(devinfo);
+-      if (!devinfo->irq_requested)
+-              return;
+-      devinfo->irq_requested = false;
+       free_irq(pdev->irq, devinfo);
+       pci_disable_msi(pdev);
diff --git a/package/kernel/mac80211/patches/374-0005-brcmfmac-Disable-runtime-pm-for-USB.patch b/package/kernel/mac80211/patches/374-0005-brcmfmac-Disable-runtime-pm-for-USB.patch
new file mode 100644 (file)
index 0000000..f2afb90
--- /dev/null
@@ -0,0 +1,26 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Thu, 29 Oct 2015 20:33:15 +0100
+Subject: [PATCH] brcmfmac: Disable runtime pm for USB.
+
+Currently runtime pm is enabled for USB, but it is not properly
+supported by driver. This patch disables the runtime PM support
+completely for USB, as it currently can result in problems on
+some systems.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+@@ -1504,7 +1504,6 @@ static struct usb_driver brcmf_usbdrvr =
+       .suspend = brcmf_usb_suspend,
+       .resume = brcmf_usb_resume,
+       .reset_resume = brcmf_usb_reset_resume,
+-      .supports_autosuspend = 1,
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0))
+       .disable_hub_initiated_lpm = 1,
+ #endif
diff --git a/package/kernel/mac80211/patches/374-0006-brcmfmac-Add-RSDB-support.patch b/package/kernel/mac80211/patches/374-0006-brcmfmac-Add-RSDB-support.patch
new file mode 100644 (file)
index 0000000..78a95c5
--- /dev/null
@@ -0,0 +1,65 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Thu, 29 Oct 2015 20:33:16 +0100
+Subject: [PATCH] brcmfmac: Add RSDB support.
+
+Broadcom devices with a single 802.11 core can work on two band
+concurrently using VSDB feature, ie. Virtual Simultaneous Dual-Band.
+For devices that are fitted with two 802.11 cores and RF paths the
+driver should support a firmware feature called RSDB, which stands
+for Real Simultaneous Dual-Band. RSDB works almost autonomously in
+firmware except for AP config. When the device supports RSDB then
+the interface should not be brought down when configuring it,
+otherwise the link (if configured) on the other interface will be
+lost.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+[kvalo@codeaurora.org: changed the commit log based on discussion]
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+@@ -4182,7 +4182,9 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+                       }
+               }
+-              if (dev_role == NL80211_IFTYPE_AP) {
++              if ((dev_role == NL80211_IFTYPE_AP) &&
++                  ((ifp->ifidx == 0) ||
++                   !brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB))) {
+                       err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
+                       if (err < 0) {
+                               brcmf_err("BRCMF_C_DOWN error %d\n", err);
+--- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
+@@ -137,6 +137,7 @@ void brcmf_feat_attach(struct brcmf_pub
+       if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID)
+               brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0);
+       brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_P2P, "p2p");
++      brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_RSDB, "rsdb_mode");
+       if (brcmf_feature_disable) {
+               brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n",
+--- a/drivers/net/wireless/brcm80211/brcmfmac/feature.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.h
+@@ -24,13 +24,16 @@
+  * PNO: preferred network offload.
+  * WOWL: Wake-On-WLAN.
+  * P2P: peer-to-peer
++ * RSDB: Real Simultaneous Dual Band
+  */
+ #define BRCMF_FEAT_LIST \
+       BRCMF_FEAT_DEF(MBSS) \
+       BRCMF_FEAT_DEF(MCHAN) \
+       BRCMF_FEAT_DEF(PNO) \
+       BRCMF_FEAT_DEF(WOWL) \
+-      BRCMF_FEAT_DEF(P2P)
++      BRCMF_FEAT_DEF(P2P) \
++      BRCMF_FEAT_DEF(RSDB)
++
+ /*
+  * Quirks:
+  *
diff --git a/package/kernel/mac80211/patches/374-0007-brcmfmac-Use-consistent-naming-for-bsscfgidx.patch b/package/kernel/mac80211/patches/374-0007-brcmfmac-Use-consistent-naming-for-bsscfgidx.patch
new file mode 100644 (file)
index 0000000..d1e7264
--- /dev/null
@@ -0,0 +1,533 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Thu, 29 Oct 2015 20:33:17 +0100
+Subject: [PATCH] brcmfmac: Use consistent naming for bsscfgidx.
+
+The variable bsscfgidx is used in different places with different
+names, e.g. bsscfg, bssidx, bsscfg_idx. This patch cleans this up
+by using bsscfgidx everywhere.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+@@ -775,7 +775,8 @@ brcmf_cfg80211_change_iface(struct wiphy
+       s32 ap = 0;
+       s32 err = 0;
+-      brcmf_dbg(TRACE, "Enter, idx=%d, type=%d\n", ifp->bssidx, type);
++      brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, type=%d\n", ifp->bsscfgidx,
++                type);
+       /* WAR: There are a number of p2p interface related problems which
+        * need to be handled initially (before doing the validate).
+@@ -2920,7 +2921,7 @@ brcmf_cfg80211_escan_handler(struct brcm
+       status = e->status;
+       if (!test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
+-              brcmf_err("scan not ready, bssidx=%d\n", ifp->bssidx);
++              brcmf_err("scan not ready, bsscfgidx=%d\n", ifp->bsscfgidx);
+               return -EPERM;
+       }
+@@ -3876,7 +3877,8 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_c
+       ifp = vif->ifp;
+       saved_ie = &vif->saved_ie;
+-      brcmf_dbg(TRACE, "bssidx %d, pktflag : 0x%02X\n", ifp->bssidx, pktflag);
++      brcmf_dbg(TRACE, "bsscfgidx %d, pktflag : 0x%02X\n", ifp->bsscfgidx,
++                pktflag);
+       iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
+       if (!iovar_ie_buf)
+               return -ENOMEM;
+@@ -4240,7 +4242,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+                       brcmf_err("setting ssid failed %d\n", err);
+                       goto exit;
+               }
+-              bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx);
++              bss_enable.bsscfgidx = cpu_to_le32(ifp->bsscfgidx);
+               bss_enable.enable = cpu_to_le32(1);
+               err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable,
+                                              sizeof(bss_enable));
+@@ -4307,7 +4309,7 @@ static int brcmf_cfg80211_stop_ap(struct
+               if (err < 0)
+                       brcmf_err("BRCMF_C_UP error %d\n", err);
+       } else {
+-              bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx);
++              bss_enable.bsscfgidx = cpu_to_le32(ifp->bsscfgidx);
+               bss_enable.enable = cpu_to_le32(0);
+               err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable,
+                                              sizeof(bss_enable));
+@@ -5093,9 +5095,9 @@ static s32 brcmf_notify_vif_event(struct
+       struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
+       struct brcmf_cfg80211_vif *vif;
+-      brcmf_dbg(TRACE, "Enter: action %u flags %u ifidx %u bsscfg %u\n",
++      brcmf_dbg(TRACE, "Enter: action %u flags %u ifidx %u bsscfgidx %u\n",
+                 ifevent->action, ifevent->flags, ifevent->ifidx,
+-                ifevent->bssidx);
++                ifevent->bsscfgidx);
+       mutex_lock(&event->vif_event_lock);
+       event->action = ifevent->action;
+--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+@@ -80,7 +80,7 @@ char *brcmf_ifname(struct brcmf_if *ifp)
+ struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx)
+ {
+       struct brcmf_if *ifp;
+-      s32 bssidx;
++      s32 bsscfgidx;
+       if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
+               brcmf_err("ifidx %d out of range\n", ifidx);
+@@ -88,9 +88,9 @@ struct brcmf_if *brcmf_get_ifp(struct br
+       }
+       ifp = NULL;
+-      bssidx = drvr->if2bss[ifidx];
+-      if (bssidx >= 0)
+-              ifp = drvr->iflist[bssidx];
++      bsscfgidx = drvr->if2bss[ifidx];
++      if (bsscfgidx >= 0)
++              ifp = drvr->iflist[bsscfgidx];
+       return ifp;
+ }
+@@ -108,7 +108,7 @@ static void _brcmf_set_multicast_list(st
+       ifp = container_of(work, struct brcmf_if, multicast_work);
+-      brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
++      brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
+       ndev = ifp->ndev;
+@@ -168,7 +168,7 @@ _brcmf_set_mac_address(struct work_struc
+       ifp = container_of(work, struct brcmf_if, setmacaddr_work);
+-      brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
++      brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
+       err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
+                                      ETH_ALEN);
+@@ -206,7 +206,7 @@ static netdev_tx_t brcmf_netdev_start_xm
+       struct brcmf_pub *drvr = ifp->drvr;
+       struct ethhdr *eh = (struct ethhdr *)(skb->data);
+-      brcmf_dbg(DATA, "Enter, idx=%d\n", ifp->bssidx);
++      brcmf_dbg(DATA, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
+       /* Can the device send data? */
+       if (drvr->bus_if->state != BRCMF_BUS_UP) {
+@@ -267,8 +267,8 @@ void brcmf_txflowblock_if(struct brcmf_i
+       if (!ifp || !ifp->ndev)
+               return;
+-      brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n",
+-                ifp->bssidx, ifp->netif_stop, reason, state);
++      brcmf_dbg(TRACE, "enter: bsscfgidx=%d stop=0x%X reason=%d state=%d\n",
++                ifp->bsscfgidx, ifp->netif_stop, reason, state);
+       spin_lock_irqsave(&ifp->netif_stop_lock, flags);
+       if (state) {
+@@ -587,7 +587,7 @@ static struct net_device_stats *brcmf_ne
+ {
+       struct brcmf_if *ifp = netdev_priv(ndev);
+-      brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
++      brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
+       return &ifp->stats;
+ }
+@@ -616,7 +616,7 @@ static int brcmf_netdev_stop(struct net_
+ {
+       struct brcmf_if *ifp = netdev_priv(ndev);
+-      brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
++      brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
+       brcmf_cfg80211_down(ndev);
+@@ -632,7 +632,7 @@ static int brcmf_netdev_open(struct net_
+       struct brcmf_bus *bus_if = drvr->bus_if;
+       u32 toe_ol;
+-      brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
++      brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
+       /* If bus is not ready, can't continue */
+       if (bus_if->state != BRCMF_BUS_UP) {
+@@ -674,7 +674,7 @@ int brcmf_net_attach(struct brcmf_if *if
+       struct net_device *ndev;
+       s32 err;
+-      brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx,
++      brcmf_dbg(TRACE, "Enter, bsscfgidx=%d mac=%pM\n", ifp->bsscfgidx,
+                 ifp->mac_addr);
+       ndev = ifp->ndev;
+@@ -706,7 +706,7 @@ int brcmf_net_attach(struct brcmf_if *if
+       return 0;
+ fail:
+-      drvr->iflist[ifp->bssidx] = NULL;
++      drvr->iflist[ifp->bsscfgidx] = NULL;
+       ndev->netdev_ops = NULL;
+       free_netdev(ndev);
+       return -EBADE;
+@@ -724,7 +724,8 @@ void brcmf_net_setcarrier(struct brcmf_i
+ {
+       struct net_device *ndev;
+-      brcmf_dbg(TRACE, "Enter, idx=%d carrier=%d\n", ifp->bssidx, on);
++      brcmf_dbg(TRACE, "Enter, bsscfgidx=%d carrier=%d\n", ifp->bsscfgidx,
++                on);
+       ndev = ifp->ndev;
+       brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_DISCONNECTED, !on);
+@@ -771,7 +772,7 @@ static int brcmf_net_p2p_attach(struct b
+ {
+       struct net_device *ndev;
+-      brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx,
++      brcmf_dbg(TRACE, "Enter, bsscfgidx=%d mac=%pM\n", ifp->bsscfgidx,
+                 ifp->mac_addr);
+       ndev = ifp->ndev;
+@@ -790,21 +791,21 @@ static int brcmf_net_p2p_attach(struct b
+       return 0;
+ fail:
+-      ifp->drvr->iflist[ifp->bssidx] = NULL;
++      ifp->drvr->iflist[ifp->bsscfgidx] = NULL;
+       ndev->netdev_ops = NULL;
+       free_netdev(ndev);
+       return -EBADE;
+ }
+-struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
++struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
+                             bool is_p2pdev, char *name, u8 *mac_addr)
+ {
+       struct brcmf_if *ifp;
+       struct net_device *ndev;
+-      brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifidx);
++      brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", bsscfgidx, ifidx);
+-      ifp = drvr->iflist[bssidx];
++      ifp = drvr->iflist[bsscfgidx];
+       /*
+        * Delete the existing interface before overwriting it
+        * in case we missed the BRCMF_E_IF_DEL event.
+@@ -815,7 +816,7 @@ struct brcmf_if *brcmf_add_if(struct brc
+               if (ifidx) {
+                       netif_stop_queue(ifp->ndev);
+                       brcmf_net_detach(ifp->ndev);
+-                      drvr->iflist[bssidx] = NULL;
++                      drvr->iflist[bsscfgidx] = NULL;
+               } else {
+                       brcmf_err("ignore IF event\n");
+                       return ERR_PTR(-EINVAL);
+@@ -839,15 +840,15 @@ struct brcmf_if *brcmf_add_if(struct brc
+               ndev->destructor = brcmf_cfg80211_free_netdev;
+               ifp = netdev_priv(ndev);
+               ifp->ndev = ndev;
+-              /* store mapping ifidx to bssidx */
++              /* store mapping ifidx to bsscfgidx */
+               if (drvr->if2bss[ifidx] == BRCMF_BSSIDX_INVALID)
+-                      drvr->if2bss[ifidx] = bssidx;
++                      drvr->if2bss[ifidx] = bsscfgidx;
+       }
+       ifp->drvr = drvr;
+-      drvr->iflist[bssidx] = ifp;
++      drvr->iflist[bsscfgidx] = ifp;
+       ifp->ifidx = ifidx;
+-      ifp->bssidx = bssidx;
++      ifp->bsscfgidx = bsscfgidx;
+       init_waitqueue_head(&ifp->pend_8021x_wait);
+       spin_lock_init(&ifp->netif_stop_lock);
+@@ -861,21 +862,22 @@ struct brcmf_if *brcmf_add_if(struct brc
+       return ifp;
+ }
+-static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
++static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx)
+ {
+       struct brcmf_if *ifp;
+-      ifp = drvr->iflist[bssidx];
+-      drvr->iflist[bssidx] = NULL;
++      ifp = drvr->iflist[bsscfgidx];
++      drvr->iflist[bsscfgidx] = NULL;
+       if (!ifp) {
+-              brcmf_err("Null interface, idx=%d\n", bssidx);
++              brcmf_err("Null interface, bsscfgidx=%d\n", bsscfgidx);
+               return;
+       }
+-      brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
+-      if (drvr->if2bss[ifp->ifidx] == bssidx)
++      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;
+       if (ifp->ndev) {
+-              if (bssidx == 0) {
++              if (bsscfgidx == 0) {
+                       if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
+                               rtnl_lock();
+                               brcmf_netdev_stop(ifp->ndev);
+@@ -905,12 +907,12 @@ static void brcmf_del_if(struct brcmf_pu
+ void brcmf_remove_interface(struct brcmf_if *ifp)
+ {
+-      if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bssidx] != ifp))
++      if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bsscfgidx] != ifp))
+               return;
+-      brcmf_dbg(TRACE, "Enter, bssidx=%d, ifidx=%d\n", ifp->bssidx,
++      brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", ifp->bsscfgidx,
+                 ifp->ifidx);
+       brcmf_fws_del_interface(ifp);
+-      brcmf_del_if(ifp->drvr, ifp->bssidx);
++      brcmf_del_if(ifp->drvr, ifp->bsscfgidx);
+ }
+ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr)
+@@ -925,10 +927,10 @@ int brcmf_get_next_free_bsscfgidx(struct
+       highest = 2;
+       for (ifidx = 0; ifidx < BRCMF_MAX_IFS; ifidx++) {
+               if (drvr->iflist[ifidx]) {
+-                      if (drvr->iflist[ifidx]->bssidx == bsscfgidx)
++                      if (drvr->iflist[ifidx]->bsscfgidx == bsscfgidx)
+                               bsscfgidx = highest + 1;
+-                      else if (drvr->iflist[ifidx]->bssidx > highest)
+-                              highest = drvr->iflist[ifidx]->bssidx;
++                      else if (drvr->iflist[ifidx]->bsscfgidx > highest)
++                              highest = drvr->iflist[ifidx]->bsscfgidx;
+               } else {
+                       available = true;
+               }
+--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
+@@ -174,7 +174,7 @@ enum brcmf_netif_stop_reason {
+  * @multicast_work: worker object for multicast provisioning.
+  * @fws_desc: interface specific firmware-signalling descriptor.
+  * @ifidx: interface index in device firmware.
+- * @bssidx: index of bss associated with this interface.
++ * @bsscfgidx: index of bss associated with this interface.
+  * @mac_addr: assigned mac address.
+  * @netif_stop: bitmap indicates reason why netif queues are stopped.
+  * @netif_stop_lock: spinlock for update netif_stop from multiple sources.
+@@ -190,7 +190,7 @@ struct brcmf_if {
+       struct work_struct multicast_work;
+       struct brcmf_fws_mac_descriptor *fws_desc;
+       int ifidx;
+-      s32 bssidx;
++      s32 bsscfgidx;
+       u8 mac_addr[ETH_ALEN];
+       u8 netif_stop;
+       spinlock_t netif_stop_lock;
+@@ -208,7 +208,7 @@ int brcmf_netdev_wait_pend8021x(struct b
+ char *brcmf_ifname(struct brcmf_if *ifp);
+ struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx);
+ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
+-struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
++struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
+                             bool is_p2pdev, char *name, u8 *mac_addr);
+ void brcmf_remove_interface(struct brcmf_if *ifp);
+ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr);
+--- a/drivers/net/wireless/brcm80211/brcmfmac/debug.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.c
+@@ -49,7 +49,7 @@ static int brcmf_debug_psm_watchdog_noti
+                                          const struct brcmf_event_msg *evtmsg,
+                                          void *data)
+ {
+-      brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx);
++      brcmf_dbg(TRACE, "enter: bsscfgidx=%d\n", ifp->bsscfgidx);
+       return brcmf_debug_create_memdump(ifp->drvr->bus_if, data,
+                                         evtmsg->datalen);
+--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+@@ -182,8 +182,8 @@ static void brcmf_fweh_handle_if_event(s
+       bool is_p2pdev;
+       int err = 0;
+-      brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n",
+-                ifevent->action, ifevent->ifidx, ifevent->bssidx,
++      brcmf_dbg(EVENT, "action: %u ifidx: %u bsscfgidx: %u flags: %u role: %u\n",
++                ifevent->action, ifevent->ifidx, ifevent->bsscfgidx,
+                 ifevent->flags, ifevent->role);
+       /* The P2P Device interface event must not be ignored contrary to what
+@@ -204,12 +204,12 @@ static void brcmf_fweh_handle_if_event(s
+               return;
+       }
+-      ifp = drvr->iflist[ifevent->bssidx];
++      ifp = drvr->iflist[ifevent->bsscfgidx];
+       if (ifevent->action == BRCMF_E_IF_ADD) {
+               brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
+                         emsg->addr);
+-              ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx,
++              ifp = brcmf_add_if(drvr, ifevent->bsscfgidx, ifevent->ifidx,
+                                  is_p2pdev, emsg->ifname, emsg->addr);
+               if (IS_ERR(ifp))
+                       return;
+--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
+@@ -219,7 +219,7 @@ struct brcmf_if_event {
+       u8 ifidx;
+       u8 action;
+       u8 flags;
+-      u8 bssidx;
++      u8 bsscfgidx;
+       u8 role;
+ };
+--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
+@@ -293,22 +293,22 @@ brcmf_fil_iovar_int_get(struct brcmf_if
+ }
+ static u32
+-brcmf_create_bsscfg(s32 bssidx, char *name, char *data, u32 datalen, char *buf,
+-                  u32 buflen)
++brcmf_create_bsscfg(s32 bsscfgidx, char *name, char *data, u32 datalen,
++                  char *buf, u32 buflen)
+ {
+       const s8 *prefix = "bsscfg:";
+       s8 *p;
+       u32 prefixlen;
+       u32 namelen;
+       u32 iolen;
+-      __le32 bssidx_le;
++      __le32 bsscfgidx_le;
+-      if (bssidx == 0)
++      if (bsscfgidx == 0)
+               return brcmf_create_iovar(name, data, datalen, buf, buflen);
+       prefixlen = strlen(prefix);
+       namelen = strlen(name) + 1; /* lengh of iovar  name + null */
+-      iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen;
++      iolen = prefixlen + namelen + sizeof(bsscfgidx_le) + datalen;
+       if (buflen < iolen) {
+               brcmf_err("buffer is too short\n");
+@@ -326,9 +326,9 @@ brcmf_create_bsscfg(s32 bssidx, char *na
+       p += namelen;
+       /* bss config index as first data */
+-      bssidx_le = cpu_to_le32(bssidx);
+-      memcpy(p, &bssidx_le, sizeof(bssidx_le));
+-      p += sizeof(bssidx_le);
++      bsscfgidx_le = cpu_to_le32(bsscfgidx);
++      memcpy(p, &bsscfgidx_le, sizeof(bsscfgidx_le));
++      p += sizeof(bsscfgidx_le);
+       /* parameter buffer follows */
+       if (datalen)
+@@ -347,12 +347,12 @@ brcmf_fil_bsscfg_data_set(struct brcmf_i
+       mutex_lock(&drvr->proto_block);
+-      brcmf_dbg(FIL, "ifidx=%d, bssidx=%d, name=%s, len=%d\n", ifp->ifidx,
+-                ifp->bssidx, name, len);
++      brcmf_dbg(FIL, "ifidx=%d, bsscfgidx=%d, name=%s, len=%d\n", ifp->ifidx,
++                ifp->bsscfgidx, name, len);
+       brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+                          min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
+-      buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len,
++      buflen = brcmf_create_bsscfg(ifp->bsscfgidx, name, data, len,
+                                    drvr->proto_buf, sizeof(drvr->proto_buf));
+       if (buflen) {
+               err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
+@@ -376,7 +376,7 @@ brcmf_fil_bsscfg_data_get(struct brcmf_i
+       mutex_lock(&drvr->proto_block);
+-      buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len,
++      buflen = brcmf_create_bsscfg(ifp->bsscfgidx, name, data, len,
+                                    drvr->proto_buf, sizeof(drvr->proto_buf));
+       if (buflen) {
+               err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
+@@ -387,8 +387,8 @@ brcmf_fil_bsscfg_data_get(struct brcmf_i
+               err = -EPERM;
+               brcmf_err("Creating bsscfg failed\n");
+       }
+-      brcmf_dbg(FIL, "ifidx=%d, bssidx=%d, name=%s, len=%d\n", ifp->ifidx,
+-                ifp->bssidx, name, len);
++      brcmf_dbg(FIL, "ifidx=%d, bsscfgidx=%d, name=%s, len=%d\n", ifp->ifidx,
++                ifp->bsscfgidx, name, len);
+       brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+                          min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
+--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
+@@ -170,7 +170,7 @@ struct brcmf_fil_af_params_le {
+ };
+ struct brcmf_fil_bss_enable_le {
+-      __le32 bsscfg_idx;
++      __le32 bsscfgidx;
+       __le32 enable;
+ };
+--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+@@ -719,7 +719,7 @@ static void brcmf_fws_macdesc_init(struc
+       desc->state = BRCMF_FWS_STATE_OPEN;
+       desc->requested_credit = 0;
+       desc->requested_packet = 0;
+-      /* depending on use may need ifp->bssidx instead */
++      /* depending on use may need ifp->bsscfgidx instead */
+       desc->interface_id = ifidx;
+       desc->ac_bitmap = 0xff; /* update this when handling APSD */
+       if (addr)
+@@ -1938,7 +1938,7 @@ void brcmf_fws_reset_interface(struct br
+ {
+       struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc;
+-      brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx);
++      brcmf_dbg(TRACE, "enter: bsscfgidx=%d\n", ifp->bsscfgidx);
+       if (!entry)
+               return;
+--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+@@ -2067,7 +2067,7 @@ static struct wireless_dev *brcmf_p2p_cr
+       struct brcmf_if *p2p_ifp;
+       struct brcmf_if *pri_ifp;
+       int err;
+-      u32 bssidx;
++      u32 bsscfgidx;
+       if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
+               return ERR_PTR(-ENOSPC);
+@@ -2113,13 +2113,13 @@ static struct wireless_dev *brcmf_p2p_cr
+       memcpy(&p2p_vif->wdev.address, p2p->dev_addr, sizeof(p2p->dev_addr));
+       /* verify bsscfg index for P2P discovery */
+-      err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
++      err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bsscfgidx);
+       if (err < 0) {
+               brcmf_err("retrieving discover bsscfg index failed\n");
+               goto fail;
+       }
+-      WARN_ON(p2p_ifp->bssidx != bssidx);
++      WARN_ON(p2p_ifp->bsscfgidx != bsscfgidx);
+       init_completion(&p2p->send_af_done);
+       INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
diff --git a/package/kernel/mac80211/patches/374-0008-brcmfmac-Use-new-methods-for-pcie-Power-Management.patch b/package/kernel/mac80211/patches/374-0008-brcmfmac-Use-new-methods-for-pcie-Power-Management.patch
new file mode 100644 (file)
index 0000000..fb2b85e
--- /dev/null
@@ -0,0 +1,163 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Thu, 29 Oct 2015 20:33:18 +0100
+Subject: [PATCH] brcmfmac: Use new methods for pcie Power Management.
+
+Currently the legacy methods suspend and resume are used for pcie
+devices. This is not the preferable method and is also causing
+issues with some setups when doing hibernate. Changing this to
+use the new PM methods.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+@@ -1388,10 +1388,6 @@ static void brcmf_pcie_wowl_config(struc
+       brcmf_dbg(PCIE, "Configuring WOWL, enabled=%d\n", enabled);
+       devinfo->wowl_enabled = enabled;
+-      if (enabled)
+-              device_set_wakeup_enable(&devinfo->pdev->dev, true);
+-      else
+-              device_set_wakeup_enable(&devinfo->pdev->dev, false);
+ }
+@@ -1961,15 +1957,14 @@ brcmf_pcie_remove(struct pci_dev *pdev)
+ #ifdef CONFIG_PM
+-static int brcmf_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
++static int brcmf_pcie_pm_enter_D3(struct device *dev)
+ {
+       struct brcmf_pciedev_info *devinfo;
+       struct brcmf_bus *bus;
+-      int err;
+-      brcmf_dbg(PCIE, "Enter, state=%d, pdev=%p\n", state.event, pdev);
++      brcmf_err("Enter\n");
+-      bus = dev_get_drvdata(&pdev->dev);
++      bus = dev_get_drvdata(dev);
+       devinfo = bus->bus_priv.pcie->devinfo;
+       brcmf_bus_change_state(bus, BRCMF_BUS_DOWN);
+@@ -1984,62 +1979,45 @@ static int brcmf_pcie_suspend(struct pci
+               brcmf_err("Timeout on response for entering D3 substate\n");
+               return -EIO;
+       }
+-      brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM_IN_USE);
+-      err = pci_save_state(pdev);
+-      if (err)
+-              brcmf_err("pci_save_state failed, err=%d\n", err);
+-      if ((err) || (!devinfo->wowl_enabled)) {
+-              brcmf_chip_detach(devinfo->ci);
+-              devinfo->ci = NULL;
+-              brcmf_pcie_remove(pdev);
+-              return 0;
+-      }
++      devinfo->state = BRCMFMAC_PCIE_STATE_DOWN;
+-      return pci_prepare_to_sleep(pdev);
++      return 0;
+ }
+-static int brcmf_pcie_resume(struct pci_dev *pdev)
++
++static int brcmf_pcie_pm_leave_D3(struct device *dev)
+ {
+       struct brcmf_pciedev_info *devinfo;
+       struct brcmf_bus *bus;
++      struct pci_dev *pdev;
+       int err;
+-      bus = dev_get_drvdata(&pdev->dev);
+-      brcmf_dbg(PCIE, "Enter, pdev=%p, bus=%p\n", pdev, bus);
++      brcmf_err("Enter\n");
+-      err = pci_set_power_state(pdev, PCI_D0);
+-      if (err) {
+-              brcmf_err("pci_set_power_state failed, err=%d\n", err);
+-              goto cleanup;
+-      }
+-      pci_restore_state(pdev);
+-      pci_enable_wake(pdev, PCI_D3hot, false);
+-      pci_enable_wake(pdev, PCI_D3cold, false);
++      bus = dev_get_drvdata(dev);
++      devinfo = bus->bus_priv.pcie->devinfo;
++      brcmf_dbg(PCIE, "Enter, dev=%p, bus=%p\n", dev, bus);
+       /* Check if device is still up and running, if so we are ready */
+-      if (bus) {
+-              devinfo = bus->bus_priv.pcie->devinfo;
+-              if (brcmf_pcie_read_reg32(devinfo,
+-                                        BRCMF_PCIE_PCIE2REG_INTMASK) != 0) {
+-                      if (brcmf_pcie_send_mb_data(devinfo,
+-                                                  BRCMF_H2D_HOST_D0_INFORM))
+-                              goto cleanup;
+-                      brcmf_dbg(PCIE, "Hot resume, continue....\n");
+-                      brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+-                      brcmf_bus_change_state(bus, BRCMF_BUS_UP);
+-                      brcmf_pcie_intr_enable(devinfo);
+-                      return 0;
+-              }
++      if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0) {
++              brcmf_dbg(PCIE, "Try to wakeup device....\n");
++              if (brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM))
++                      goto cleanup;
++              brcmf_dbg(PCIE, "Hot resume, continue....\n");
++              devinfo->state = BRCMFMAC_PCIE_STATE_UP;
++              brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
++              brcmf_bus_change_state(bus, BRCMF_BUS_UP);
++              brcmf_pcie_intr_enable(devinfo);
++              return 0;
+       }
+ cleanup:
+-      if (bus) {
+-              devinfo = bus->bus_priv.pcie->devinfo;
+-              brcmf_chip_detach(devinfo->ci);
+-              devinfo->ci = NULL;
+-              brcmf_pcie_remove(pdev);
+-      }
++      brcmf_chip_detach(devinfo->ci);
++      devinfo->ci = NULL;
++      pdev = devinfo->pdev;
++      brcmf_pcie_remove(pdev);
++
+       err = brcmf_pcie_probe(pdev, NULL);
+       if (err)
+               brcmf_err("probe after resume failed, err=%d\n", err);
+@@ -2048,6 +2026,14 @@ cleanup:
+ }
++static const struct dev_pm_ops brcmf_pciedrvr_pm = {
++      .suspend = brcmf_pcie_pm_enter_D3,
++      .resume = brcmf_pcie_pm_leave_D3,
++      .freeze = brcmf_pcie_pm_enter_D3,
++      .restore = brcmf_pcie_pm_leave_D3,
++};
++
++
+ #endif /* CONFIG_PM */
+@@ -2086,9 +2072,8 @@ static struct pci_driver brcmf_pciedrvr
+       .probe = brcmf_pcie_probe,
+       .remove = brcmf_pcie_remove,
+ #ifdef CONFIG_PM
+-      .suspend = brcmf_pcie_suspend,
+-      .resume = brcmf_pcie_resume
+-#endif /* CONFIG_PM */
++      .driver.pm = &brcmf_pciedrvr_pm,
++#endif
+ };
diff --git a/package/kernel/mac80211/patches/374-0009-brcmfmac-Add-wowl-wake-indication-report.patch b/package/kernel/mac80211/patches/374-0009-brcmfmac-Add-wowl-wake-indication-report.patch
new file mode 100644 (file)
index 0000000..4324cc7
--- /dev/null
@@ -0,0 +1,129 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Thu, 29 Oct 2015 20:33:19 +0100
+Subject: [PATCH] brcmfmac: Add wowl wake indication report.
+
+On wakeup of the system (resume) a wowl wakeup indication report
+can be sent to cfg80211. This patch adds support for this. The
+report specifies if the device was responsible for the wakeup
+and if so, will specify the exact reason.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+@@ -3061,6 +3061,67 @@ static s32 brcmf_config_wowl_pattern(str
+       return ret;
+ }
++#ifdef CPTCFG_PM
++
++static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp)
++{
++      struct brcmf_wowl_wakeind_le wake_ind_le;
++      struct cfg80211_wowlan_wakeup wakeup_data;
++      struct cfg80211_wowlan_wakeup *wakeup;
++      u32 wakeind;
++      s32 err;
++
++      err = brcmf_fil_iovar_data_get(ifp, "wowl_wakeind", &wake_ind_le,
++                                     sizeof(wake_ind_le));
++      if (!err) {
++              brcmf_err("Get wowl_wakeind failed, err = %d\n", err);
++              return;
++      }
++
++      wakeind = le32_to_cpu(wake_ind_le.ucode_wakeind);
++      if (wakeind & (BRCMF_WOWL_MAGIC | BRCMF_WOWL_DIS | BRCMF_WOWL_BCN |
++                     BRCMF_WOWL_RETR | BRCMF_WOWL_NET)) {
++              wakeup = &wakeup_data;
++              memset(&wakeup_data, 0, sizeof(wakeup_data));
++              wakeup_data.pattern_idx = -1;
++
++              if (wakeind & BRCMF_WOWL_MAGIC) {
++                      brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_MAGIC\n");
++                      wakeup_data.magic_pkt = true;
++              }
++              if (wakeind & BRCMF_WOWL_DIS) {
++                      brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_DIS\n");
++                      wakeup_data.disconnect = true;
++              }
++              if (wakeind & BRCMF_WOWL_BCN) {
++                      brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_BCN\n");
++                      wakeup_data.disconnect = true;
++              }
++              if (wakeind & BRCMF_WOWL_RETR) {
++                      brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_RETR\n");
++                      wakeup_data.disconnect = true;
++              }
++              if (wakeind & BRCMF_WOWL_NET) {
++                      brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_NET\n");
++                      /* For now always map to pattern 0, no API to get
++                       * correct information available at the moment.
++                       */
++                      wakeup_data.pattern_idx = 0;
++              }
++      } else {
++              wakeup = NULL;
++      }
++      cfg80211_report_wowlan_wakeup(&ifp->vif->wdev, wakeup, GFP_KERNEL);
++}
++
++#else
++
++static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp)
++{
++}
++
++#endif /* CPTCFG_PM */
++
+ static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
+ {
+       struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+@@ -3070,11 +3131,12 @@ static s32 brcmf_cfg80211_resume(struct
+       brcmf_dbg(TRACE, "Enter\n");
+       if (cfg->wowl_enabled) {
++              brcmf_report_wowl_wakeind(wiphy, ifp);
++              brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0);
++              brcmf_config_wowl_pattern(ifp, "clr", NULL, 0, NULL, 0);
+               brcmf_configure_arp_offload(ifp, true);
+               brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM,
+                                     cfg->pre_wowl_pmmode);
+-              brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0);
+-              brcmf_config_wowl_pattern(ifp, "clr", NULL, 0, NULL, 0);
+               cfg->wowl_enabled = false;
+       }
+       return 0;
+@@ -3108,6 +3170,7 @@ static void brcmf_configure_wowl(struct
+                               wowl->patterns[i].pkt_offset);
+               }
+       }
++      brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", "clear", strlen("clear"));
+       brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config);
+       brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1);
+       brcmf_bus_wowl_config(cfg->pub->bus_if, true);
+--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
+@@ -634,4 +634,16 @@ struct brcmf_assoclist_le {
+       u8 mac[BRCMF_MAX_ASSOCLIST][ETH_ALEN];
+ };
++/**
++ * struct brcmf_wowl_wakeind_le - Wakeup indicators
++ *    Note: note both fields contain same information.
++ *
++ * @pci_wakeind: Whether PCI PMECSR PMEStatus bit was set.
++ * @ucode_wakeind: What wakeup-event indication was set by ucode
++ */
++struct brcmf_wowl_wakeind_le {
++      __le32 pci_wakeind;
++      __le32 ucode_wakeind;
++};
++
+ #endif /* FWIL_TYPES_H_ */
diff --git a/package/kernel/mac80211/patches/375-brcmfmac-constify-brcmf_bus_ops-structures.patch b/package/kernel/mac80211/patches/375-brcmfmac-constify-brcmf_bus_ops-structures.patch
new file mode 100644 (file)
index 0000000..a0cc231
--- /dev/null
@@ -0,0 +1,57 @@
+From: Julia Lawall <Julia.Lawall@lip6.fr>
+Date: Sat, 14 Nov 2015 17:22:07 +0100
+Subject: [PATCH] brcmfmac: constify brcmf_bus_ops structures
+
+The brcmf_bus_ops structures are never modified, so declare them as const.
+
+Done with the help of Coccinelle.
+
+Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
+Acked-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/bus.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/bus.h
+@@ -137,7 +137,7 @@ struct brcmf_bus {
+       bool always_use_fws_queue;
+       bool wowl_supported;
+-      struct brcmf_bus_ops *ops;
++      const struct brcmf_bus_ops *ops;
+       struct brcmf_bus_msgbuf *msgbuf;
+ };
+--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+@@ -1413,7 +1413,7 @@ static int brcmf_pcie_get_memdump(struct
+ }
+-static struct brcmf_bus_ops brcmf_pcie_bus_ops = {
++static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
+       .txdata = brcmf_pcie_tx,
+       .stop = brcmf_pcie_down,
+       .txctl = brcmf_pcie_tx_ctlpkt,
+--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+@@ -4025,7 +4025,7 @@ brcmf_sdio_watchdog(unsigned long data)
+       }
+ }
+-static struct brcmf_bus_ops brcmf_sdio_bus_ops = {
++static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
+       .stop = brcmf_sdio_bus_stop,
+       .preinit = brcmf_sdio_bus_preinit,
+       .txdata = brcmf_sdio_bus_txdata,
+--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+@@ -1163,7 +1163,7 @@ static void brcmf_usb_wowl_config(struct
+               device_set_wakeup_enable(devinfo->dev, false);
+ }
+-static struct brcmf_bus_ops brcmf_usb_bus_ops = {
++static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
+       .txdata = brcmf_usb_tx,
+       .stop = brcmf_usb_down,
+       .txctl = brcmf_usb_tx_ctlpkt,
diff --git a/package/kernel/mac80211/patches/376-0001-brcmfmac-Cleanup-ssid-storage.patch b/package/kernel/mac80211/patches/376-0001-brcmfmac-Cleanup-ssid-storage.patch
new file mode 100644 (file)
index 0000000..83f1ebe
--- /dev/null
@@ -0,0 +1,251 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 25 Nov 2015 11:32:37 +0100
+Subject: [PATCH] brcmfmac: Cleanup ssid storage.
+
+SSIDs used for connect and p2p got stored, but never used.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+@@ -959,7 +959,7 @@ brcmf_run_escan(struct brcmf_cfg80211_in
+               params_size += sizeof(u32) * ((request->n_channels + 1) / 2);
+               /* Allocate space for populating ssids in struct */
+-              params_size += sizeof(struct brcmf_ssid) * request->n_ssids;
++              params_size += sizeof(struct brcmf_ssid_le) * request->n_ssids;
+       }
+       params = kzalloc(params_size, GFP_KERNEL);
+@@ -1291,6 +1291,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *w
+       s32 wsec = 0;
+       s32 bcnprd;
+       u16 chanspec;
++      u32 ssid_len;
+       brcmf_dbg(TRACE, "Enter\n");
+       if (!check_vif_up(ifp->vif))
+@@ -1368,17 +1369,15 @@ brcmf_cfg80211_join_ibss(struct wiphy *w
+       memset(&join_params, 0, sizeof(struct brcmf_join_params));
+       /* SSID */
+-      profile->ssid.SSID_len = min_t(u32, params->ssid_len, 32);
+-      memcpy(profile->ssid.SSID, params->ssid, profile->ssid.SSID_len);
+-      memcpy(join_params.ssid_le.SSID, params->ssid, profile->ssid.SSID_len);
+-      join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len);
++      ssid_len = min_t(u32, params->ssid_len, IEEE80211_MAX_SSID_LEN);
++      memcpy(join_params.ssid_le.SSID, params->ssid, ssid_len);
++      join_params.ssid_le.SSID_len = cpu_to_le32(ssid_len);
+       join_params_size = sizeof(join_params.ssid_le);
+       /* BSSID */
+       if (params->bssid) {
+               memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN);
+-              join_params_size = sizeof(join_params.ssid_le) +
+-                                 BRCMF_ASSOC_PARAMS_FIXED_SIZE;
++              join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE;
+               memcpy(profile->bssid, params->bssid, ETH_ALEN);
+       } else {
+               eth_broadcast_addr(join_params.params_le.bssid);
+@@ -1728,7 +1727,6 @@ brcmf_cfg80211_connect(struct wiphy *wip
+ {
+       struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+       struct brcmf_if *ifp = netdev_priv(ndev);
+-      struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
+       struct ieee80211_channel *chan = sme->channel;
+       struct brcmf_join_params join_params;
+       size_t join_params_size;
+@@ -1739,6 +1737,7 @@ brcmf_cfg80211_connect(struct wiphy *wip
+       struct brcmf_ext_join_params_le *ext_join_params;
+       u16 chanspec;
+       s32 err = 0;
++      u32 ssid_len;
+       brcmf_dbg(TRACE, "Enter\n");
+       if (!check_vif_up(ifp->vif))
+@@ -1824,15 +1823,6 @@ brcmf_cfg80211_connect(struct wiphy *wip
+               goto done;
+       }
+-      profile->ssid.SSID_len = min_t(u32, (u32)sizeof(profile->ssid.SSID),
+-                                     (u32)sme->ssid_len);
+-      memcpy(&profile->ssid.SSID, sme->ssid, profile->ssid.SSID_len);
+-      if (profile->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
+-              profile->ssid.SSID[profile->ssid.SSID_len] = 0;
+-              brcmf_dbg(CONN, "SSID \"%s\", len (%d)\n", profile->ssid.SSID,
+-                        profile->ssid.SSID_len);
+-      }
+-
+       /* Join with specific BSSID and cached SSID
+        * If SSID is zero join based on BSSID only
+        */
+@@ -1845,9 +1835,12 @@ brcmf_cfg80211_connect(struct wiphy *wip
+               err = -ENOMEM;
+               goto done;
+       }
+-      ext_join_params->ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len);
+-      memcpy(&ext_join_params->ssid_le.SSID, sme->ssid,
+-             profile->ssid.SSID_len);
++      ssid_len = min_t(u32, sme->ssid_len, IEEE80211_MAX_SSID_LEN);
++      ext_join_params->ssid_le.SSID_len = cpu_to_le32(ssid_len);
++      memcpy(&ext_join_params->ssid_le.SSID, sme->ssid, ssid_len);
++      if (ssid_len < IEEE80211_MAX_SSID_LEN)
++              brcmf_dbg(CONN, "SSID \"%s\", len (%d)\n",
++                        ext_join_params->ssid_le.SSID, ssid_len);
+       /* Set up join scan parameters */
+       ext_join_params->scan_le.scan_type = -1;
+@@ -1895,8 +1888,8 @@ brcmf_cfg80211_connect(struct wiphy *wip
+       memset(&join_params, 0, sizeof(join_params));
+       join_params_size = sizeof(join_params.ssid_le);
+-      memcpy(&join_params.ssid_le.SSID, sme->ssid, profile->ssid.SSID_len);
+-      join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len);
++      memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid_len);
++      join_params.ssid_le.SSID_len = cpu_to_le32(ssid_len);
+       if (sme->bssid)
+               memcpy(join_params.params_le.bssid, sme->bssid, ETH_ALEN);
+@@ -2775,9 +2768,7 @@ CleanUp:
+ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,
+                                struct brcmf_if *ifp)
+ {
+-      struct brcmf_cfg80211_profile *profile = ndev_to_prof(ifp->ndev);
+       struct brcmf_bss_info_le *bi;
+-      struct brcmf_ssid *ssid;
+       const struct brcmf_tlv *tim;
+       u16 beacon_interval;
+       u8 dtim_period;
+@@ -2789,8 +2780,6 @@ static s32 brcmf_update_bss_info(struct
+       if (brcmf_is_ibssmode(ifp->vif))
+               return err;
+-      ssid = &profile->ssid;
+-
+       *(__le32 *)cfg->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
+       err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
+                                    cfg->extra_buf, WL_EXTRA_BUF_MAX);
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
+@@ -124,13 +124,11 @@ struct brcmf_cfg80211_security {
+ /**
+  * struct brcmf_cfg80211_profile - profile information.
+  *
+- * @ssid: ssid of associated/associating ap.
+  * @bssid: bssid of joined/joining ibss.
+  * @sec: security information.
+  * @key: key information
+  */
+ struct brcmf_cfg80211_profile {
+-      struct brcmf_ssid ssid;
+       u8 bssid[ETH_ALEN];
+       struct brcmf_cfg80211_security sec;
+       struct brcmf_wsec_key key[BRCMF_MAX_DEFAULT_KEYS];
+--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
+@@ -282,14 +282,9 @@ struct brcm_rateset_le {
+       u8 rates[BRCMF_MAXRATES_IN_SET];
+ };
+-struct brcmf_ssid {
+-      u32 SSID_len;
+-      unsigned char SSID[32];
+-};
+-
+ struct brcmf_ssid_le {
+       __le32 SSID_len;
+-      unsigned char SSID[32];
++      unsigned char SSID[IEEE80211_MAX_SSID_LEN];
+ };
+ struct brcmf_scan_params_le {
+--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+@@ -642,7 +642,6 @@ static s32 brcmf_p2p_escan(struct brcmf_
+       struct brcmf_cfg80211_vif *vif;
+       struct brcmf_p2p_scan_le *p2p_params;
+       struct brcmf_scan_params_le *sparams;
+-      struct brcmf_ssid ssid;
+       memsize += num_chans * sizeof(__le16);
+       memblk = kzalloc(memsize, GFP_KERNEL);
+@@ -655,16 +654,16 @@ static s32 brcmf_p2p_escan(struct brcmf_
+               ret = -EINVAL;
+               goto exit;
+       }
++      p2p_params = (struct brcmf_p2p_scan_le *)memblk;
++      sparams = &p2p_params->eparams.params_le;
+       switch (search_state) {
+       case WL_P2P_DISC_ST_SEARCH:
+               /*
+                * If we in SEARCH STATE, we don't need to set SSID explictly
+-               * because dongle use P2P WILDCARD internally by default
++               * because dongle use P2P WILDCARD internally by default, use
++               * null ssid, which it is already due to kzalloc.
+                */
+-              /* use null ssid */
+-              ssid.SSID_len = 0;
+-              memset(ssid.SSID, 0, sizeof(ssid.SSID));
+               break;
+       case WL_P2P_DISC_ST_SCAN:
+               /*
+@@ -673,8 +672,10 @@ static s32 brcmf_p2p_escan(struct brcmf_
+                * P2P WILDCARD because we just do broadcast scan unless
+                * setting SSID.
+                */
+-              ssid.SSID_len = BRCMF_P2P_WILDCARD_SSID_LEN;
+-              memcpy(ssid.SSID, BRCMF_P2P_WILDCARD_SSID, ssid.SSID_len);
++              sparams->ssid_le.SSID_len =
++                              cpu_to_le32(BRCMF_P2P_WILDCARD_SSID_LEN);
++              memcpy(sparams->ssid_le.SSID, BRCMF_P2P_WILDCARD_SSID,
++                     BRCMF_P2P_WILDCARD_SSID_LEN);
+               break;
+       default:
+               brcmf_err(" invalid search state %d\n", search_state);
+@@ -687,11 +688,9 @@ static s32 brcmf_p2p_escan(struct brcmf_
+       /*
+        * set p2p scan parameters.
+        */
+-      p2p_params = (struct brcmf_p2p_scan_le *)memblk;
+       p2p_params->type = 'E';
+       /* determine the scan engine parameters */
+-      sparams = &p2p_params->eparams.params_le;
+       sparams->bss_type = DOT11_BSSTYPE_ANY;
+       if (p2p->cfg->active_scan)
+               sparams->scan_type = 0;
+@@ -699,9 +698,6 @@ static s32 brcmf_p2p_escan(struct brcmf_
+               sparams->scan_type = 1;
+       eth_broadcast_addr(sparams->bssid);
+-      if (ssid.SSID_len)
+-              memcpy(sparams->ssid_le.SSID, ssid.SSID, ssid.SSID_len);
+-      sparams->ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len);
+       sparams->home_time = cpu_to_le32(P2PAPI_SCAN_HOME_TIME_MS);
+       /*
+--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.h
+@@ -112,7 +112,6 @@ struct afx_hdl {
+  * @int_addr: P2P interface address.
+  * @bss_idx: informate for P2P bss types.
+  * @listen_timer: timer for @WL_P2P_DISC_ST_LISTEN discover state.
+- * @ssid: ssid for P2P GO.
+  * @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state.
+  * @remain_on_channel: contains copy of struct used by cfg80211.
+  * @remain_on_channel_cookie: cookie counter for remain on channel cmd
+@@ -133,7 +132,6 @@ struct brcmf_p2p_info {
+       u8 int_addr[ETH_ALEN];
+       struct p2p_bss bss_idx[P2PAPI_BSSCFG_MAX];
+       struct timer_list listen_timer;
+-      struct brcmf_ssid ssid;
+       u8 listen_channel;
+       struct ieee80211_channel remain_on_channel;
+       u32 remain_on_channel_cookie;
diff --git a/package/kernel/mac80211/patches/376-0002-brcmfmac-Return-actual-error-by-fwil.patch b/package/kernel/mac80211/patches/376-0002-brcmfmac-Return-actual-error-by-fwil.patch
new file mode 100644 (file)
index 0000000..8672c18
--- /dev/null
@@ -0,0 +1,31 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 25 Nov 2015 11:32:38 +0100
+Subject: [PATCH] brcmfmac: Return actual error by fwil.
+
+FWIL is always mapping back errors to EBADE. This is not very
+conventient when trying to understand problems by reading logs.
+Some callers print the error code, but that is quite useless
+when the exact error code is not returned. It also makes it
+impossible to differentiate based on error code. This patch
+changes the return of EBADE into the actual error code.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
+@@ -126,7 +126,8 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp,
+       brcmf_dbg(FIL, "Failed: %s (%d)\n",
+                 brcmf_fil_get_errstr((u32)(-err)), err);
+-      return -EBADE;
++
++      return err;
+ }
+ s32
diff --git a/package/kernel/mac80211/patches/376-0003-brcmfmac-Change-error-print-on-wlan0-existence.patch b/package/kernel/mac80211/patches/376-0003-brcmfmac-Change-error-print-on-wlan0-existence.patch
new file mode 100644 (file)
index 0000000..1cfab21
--- /dev/null
@@ -0,0 +1,41 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 25 Nov 2015 11:32:39 +0100
+Subject: [PATCH] brcmfmac: Change error print on wlan0 existence.
+
+During initialization of the device, but also on some other
+moments the driver prints an error that the netdev already exists.
+This is a result of the way the driver is initializing the
+firmware and not really an error. The code is not treating it as
+an error either. This error print has resulted in many questions
+by users and is confusing and incorrect. This patch changes the
+error log into a debug info log.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+@@ -811,14 +811,15 @@ struct brcmf_if *brcmf_add_if(struct brc
+        * in case we missed the BRCMF_E_IF_DEL event.
+        */
+       if (ifp) {
+-              brcmf_err("ERROR: netdev:%s already exists\n",
+-                        ifp->ndev->name);
+               if (ifidx) {
++                      brcmf_err("ERROR: netdev:%s already exists\n",
++                                ifp->ndev->name);
+                       netif_stop_queue(ifp->ndev);
+                       brcmf_net_detach(ifp->ndev);
+                       drvr->iflist[bsscfgidx] = NULL;
+               } else {
+-                      brcmf_err("ignore IF event\n");
++                      brcmf_dbg(INFO, "netdev:%s ignore IF event\n",
++                                ifp->ndev->name);
+                       return ERR_PTR(-EINVAL);
+               }
+       }
diff --git a/package/kernel/mac80211/patches/376-0004-brcmfmac-no-retries-on-rxglom-superframe-errors.patch b/package/kernel/mac80211/patches/376-0004-brcmfmac-no-retries-on-rxglom-superframe-errors.patch
new file mode 100644 (file)
index 0000000..dfc3a98
--- /dev/null
@@ -0,0 +1,76 @@
+From: Franky Lin <frankyl@broadcom.com>
+Date: Wed, 25 Nov 2015 11:32:40 +0100
+Subject: [PATCH] brcmfmac: no retries on rxglom superframe errors
+
+Aborting the current read attempt on the superframe also removes the
+packet from the pipeline. Retries should not be attempted on the next
+packet since it would not be a superframe(either a superframe descriptor
+or other data packet) and should not be handled by brcmf_sdio_rxglom
+
+Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Signed-off-by: Franky Lin <frankyl@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+@@ -460,7 +460,6 @@ struct brcmf_sdio {
+       struct sk_buff *glomd;  /* Packet containing glomming descriptor */
+       struct sk_buff_head glom; /* Packet list for glommed superframe */
+-      uint glomerr;           /* Glom packet read errors */
+       u8 *rxbuf;              /* Buffer for receiving control packets */
+       uint rxblen;            /* Allocated length of rxbuf */
+@@ -1654,20 +1653,15 @@ static u8 brcmf_sdio_rxglom(struct brcmf
+               sdio_release_host(bus->sdiodev->func[1]);
+               bus->sdcnt.f2rxdata++;
+-              /* On failure, kill the superframe, allow a couple retries */
++              /* On failure, kill the superframe */
+               if (errcode < 0) {
+                       brcmf_err("glom read of %d bytes failed: %d\n",
+                                 dlen, errcode);
+                       sdio_claim_host(bus->sdiodev->func[1]);
+-                      if (bus->glomerr++ < 3) {
+-                              brcmf_sdio_rxfail(bus, true, true);
+-                      } else {
+-                              bus->glomerr = 0;
+-                              brcmf_sdio_rxfail(bus, true, false);
+-                              bus->sdcnt.rxglomfail++;
+-                              brcmf_sdio_free_glom(bus);
+-                      }
++                      brcmf_sdio_rxfail(bus, true, false);
++                      bus->sdcnt.rxglomfail++;
++                      brcmf_sdio_free_glom(bus);
+                       sdio_release_host(bus->sdiodev->func[1]);
+                       return 0;
+               }
+@@ -1708,19 +1702,11 @@ static u8 brcmf_sdio_rxglom(struct brcmf
+               }
+               if (errcode) {
+-                      /* Terminate frame on error, request
+-                               a couple retries */
++                      /* Terminate frame on error */
+                       sdio_claim_host(bus->sdiodev->func[1]);
+-                      if (bus->glomerr++ < 3) {
+-                              /* Restore superframe header space */
+-                              skb_push(pfirst, sfdoff);
+-                              brcmf_sdio_rxfail(bus, true, true);
+-                      } else {
+-                              bus->glomerr = 0;
+-                              brcmf_sdio_rxfail(bus, true, false);
+-                              bus->sdcnt.rxglomfail++;
+-                              brcmf_sdio_free_glom(bus);
+-                      }
++                      brcmf_sdio_rxfail(bus, true, false);
++                      bus->sdcnt.rxglomfail++;
++                      brcmf_sdio_free_glom(bus);
+                       sdio_release_host(bus->sdiodev->func[1]);
+                       bus->cur_read.len = 0;
+                       return 0;
diff --git a/package/kernel/mac80211/patches/376-0005-brcmfmac-Remove-redundant-parameter-action-from-scan.patch b/package/kernel/mac80211/patches/376-0005-brcmfmac-Remove-redundant-parameter-action-from-scan.patch
new file mode 100644 (file)
index 0000000..ede1f47
--- /dev/null
@@ -0,0 +1,108 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 25 Nov 2015 11:32:41 +0100
+Subject: [PATCH] brcmfmac: Remove redundant parameter action from scan.
+
+ESCAN is always performed using action start scan. No need to
+pass this parameter on to different functions.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+@@ -945,7 +945,7 @@ static void brcmf_escan_prep(struct brcm
+ static s32
+ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
+-              struct cfg80211_scan_request *request, u16 action)
++              struct cfg80211_scan_request *request)
+ {
+       s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
+                         offsetof(struct brcmf_escan_params_le, params_le);
+@@ -970,7 +970,7 @@ brcmf_run_escan(struct brcmf_cfg80211_in
+       BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN);
+       brcmf_escan_prep(cfg, &params->params_le, request);
+       params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
+-      params->action = cpu_to_le16(action);
++      params->action = cpu_to_le16(WL_ESCAN_ACTION_START);
+       params->sync_id = cpu_to_le16(0x1234);
+       err = brcmf_fil_iovar_data_set(ifp, "escan", params, params_size);
+@@ -1012,7 +1012,7 @@ brcmf_do_escan(struct brcmf_cfg80211_inf
+       results->count = 0;
+       results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE;
+-      err = escan->run(cfg, ifp, request, WL_ESCAN_ACTION_START);
++      err = escan->run(cfg, ifp, request);
+       if (err)
+               brcmf_scan_config_mpc(ifp, 1);
+       return err;
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
+@@ -231,7 +231,7 @@ struct escan_info {
+       struct wiphy *wiphy;
+       struct brcmf_if *ifp;
+       s32 (*run)(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
+-                 struct cfg80211_scan_request *request, u16 action);
++                 struct cfg80211_scan_request *request);
+ };
+ /**
+--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+@@ -625,11 +625,10 @@ exit:
+  * @num_chans: number of channels to scan.
+  * @chanspecs: channel parameters for @num_chans channels.
+  * @search_state: P2P discover state to use.
+- * @action: scan action to pass to firmware.
+  * @bss_type: type of P2P bss.
+  */
+ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
+-                         u16 chanspecs[], s32 search_state, u16 action,
++                         u16 chanspecs[], s32 search_state,
+                          enum p2p_bss_type bss_type)
+ {
+       s32 ret = 0;
+@@ -738,7 +737,7 @@ static s32 brcmf_p2p_escan(struct brcmf_
+       /* set the escan specific parameters */
+       p2p_params->eparams.version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
+-      p2p_params->eparams.action =  cpu_to_le16(action);
++      p2p_params->eparams.action =  cpu_to_le16(WL_ESCAN_ACTION_START);
+       p2p_params->eparams.sync_id = cpu_to_le16(0x1234);
+       /* perform p2p scan on primary device */
+       ret = brcmf_fil_bsscfg_data_set(vif->ifp, "p2p_scan", memblk, memsize);
+@@ -762,8 +761,7 @@ exit:
+  */
+ static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg,
+                              struct brcmf_if *ifp,
+-                             struct cfg80211_scan_request *request,
+-                             u16 action)
++                             struct cfg80211_scan_request *request)
+ {
+       struct brcmf_p2p_info *p2p = &cfg->p2p;
+       s32 err = 0;
+@@ -823,7 +821,7 @@ static s32 brcmf_p2p_run_escan(struct br
+                       num_nodfs++;
+               }
+               err = brcmf_p2p_escan(p2p, num_nodfs, chanspecs, search_state,
+-                                    action, P2PAPI_BSSCFG_DEVICE);
++                                    P2PAPI_BSSCFG_DEVICE);
+               kfree(chanspecs);
+       }
+ exit:
+@@ -1092,8 +1090,7 @@ static s32 brcmf_p2p_act_frm_search(stru
+               default_chan_list[2] = ch.chspec;
+       }
+       err = brcmf_p2p_escan(p2p, channel_cnt, default_chan_list,
+-                            WL_P2P_DISC_ST_SEARCH, WL_ESCAN_ACTION_START,
+-                            P2PAPI_BSSCFG_DEVICE);
++                            WL_P2P_DISC_ST_SEARCH, P2PAPI_BSSCFG_DEVICE);
+       kfree(default_chan_list);
+ exit:
+       return err;
diff --git a/package/kernel/mac80211/patches/376-0006-brcmfmac-Cleanup-roaming-configuration.patch b/package/kernel/mac80211/patches/376-0006-brcmfmac-Cleanup-roaming-configuration.patch
new file mode 100644 (file)
index 0000000..41b8770
--- /dev/null
@@ -0,0 +1,180 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 25 Nov 2015 11:32:42 +0100
+Subject: [PATCH] brcmfmac: Cleanup roaming configuration.
+
+Put all roaming configuration related code in one place and
+configure timeout based upon roaming setting.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+@@ -4755,7 +4755,6 @@ struct brcmf_cfg80211_vif *brcmf_alloc_v
+       vif->wdev.iftype = type;
+       vif->pm_block = pm_block;
+-      vif->roam_off = -1;
+       brcmf_init_prof(&vif->profile);
+@@ -5305,35 +5304,33 @@ static void init_vif_event(struct brcmf_
+       mutex_init(&event->vif_event_lock);
+ }
+-static s32
+-brcmf_dongle_roam(struct brcmf_if *ifp, u32 bcn_timeout)
++static s32 brcmf_dongle_roam(struct brcmf_if *ifp)
+ {
+-      s32 err = 0;
++      s32 err;
++      u32 bcn_timeout;
+       __le32 roamtrigger[2];
+       __le32 roam_delta[2];
+-      /*
+-       * Setup timeout if Beacons are lost and roam is
+-       * off to report link down
+-       */
+-      if (brcmf_roamoff) {
+-              err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout);
+-              if (err) {
+-                      brcmf_err("bcn_timeout error (%d)\n", err);
+-                      goto dongle_rom_out;
+-              }
++      /* Configure beacon timeout value based upon roaming setting */
++      if (brcmf_roamoff)
++              bcn_timeout = BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_OFF;
++      else
++              bcn_timeout = BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_ON;
++      err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout);
++      if (err) {
++              brcmf_err("bcn_timeout error (%d)\n", err);
++              goto roam_setup_done;
+       }
+-      /*
+-       * Enable/Disable built-in roaming to allow supplicant
+-       * to take care of roaming
++      /* Enable/Disable built-in roaming to allow supplicant to take care of
++       * roaming.
+        */
+       brcmf_dbg(INFO, "Internal Roaming = %s\n",
+                 brcmf_roamoff ? "Off" : "On");
+       err = brcmf_fil_iovar_int_set(ifp, "roam_off", !!(brcmf_roamoff));
+       if (err) {
+               brcmf_err("roam_off error (%d)\n", err);
+-              goto dongle_rom_out;
++              goto roam_setup_done;
+       }
+       roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);
+@@ -5342,7 +5339,7 @@ brcmf_dongle_roam(struct brcmf_if *ifp,
+                                    (void *)roamtrigger, sizeof(roamtrigger));
+       if (err) {
+               brcmf_err("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
+-              goto dongle_rom_out;
++              goto roam_setup_done;
+       }
+       roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);
+@@ -5351,10 +5348,10 @@ brcmf_dongle_roam(struct brcmf_if *ifp,
+                                    (void *)roam_delta, sizeof(roam_delta));
+       if (err) {
+               brcmf_err("WLC_SET_ROAM_DELTA error (%d)\n", err);
+-              goto dongle_rom_out;
++              goto roam_setup_done;
+       }
+-dongle_rom_out:
++roam_setup_done:
+       return err;
+ }
+@@ -6069,7 +6066,7 @@ static s32 brcmf_config_dongle(struct br
+       brcmf_dbg(INFO, "power save set to %s\n",
+                 (power_mode ? "enabled" : "disabled"));
+-      err = brcmf_dongle_roam(ifp, WL_BEACON_TIMEOUT);
++      err = brcmf_dongle_roam(ifp);
+       if (err)
+               goto default_conf_out;
+       err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype,
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
+@@ -28,7 +28,6 @@
+ #define WL_EXTRA_BUF_MAX              2048
+ #define WL_ROAM_TRIGGER_LEVEL         -75
+ #define WL_ROAM_DELTA                 20
+-#define WL_BEACON_TIMEOUT             3
+ #define WL_SCAN_CHANNEL_TIME          40
+ #define WL_SCAN_UNASSOC_TIME          40
+@@ -77,6 +76,9 @@
+ #define BRCMF_MAX_DEFAULT_KEYS                4
++/* beacon loss timeout defaults */
++#define BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_ON     2
++#define BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_OFF    4
+ /**
+  * enum brcmf_scan_status - scan engine status
+@@ -178,7 +180,6 @@ struct vif_saved_ie {
+  * @ifp: lower layer interface pointer
+  * @wdev: wireless device.
+  * @profile: profile information.
+- * @roam_off: roaming state.
+  * @sme_state: SME state using enum brcmf_vif_status bits.
+  * @pm_block: power-management blocked.
+  * @list: linked list.
+@@ -189,7 +190,6 @@ struct brcmf_cfg80211_vif {
+       struct brcmf_if *ifp;
+       struct wireless_dev wdev;
+       struct brcmf_cfg80211_profile profile;
+-      s32 roam_off;
+       unsigned long sme_state;
+       bool pm_block;
+       struct vif_saved_ie saved_ie;
+--- a/drivers/net/wireless/brcm80211/brcmfmac/common.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/common.c
+@@ -29,7 +29,6 @@
+ const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+-#define BRCMF_DEFAULT_BCN_TIMEOUT     3
+ #define BRCMF_DEFAULT_SCAN_CHANNEL_TIME       40
+ #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME       40
+@@ -107,26 +106,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_i
+               goto done;
+       }
+-      /*
+-       * Setup timeout if Beacons are lost and roam is off to report
+-       * link down
+-       */
+-      err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout",
+-                                    BRCMF_DEFAULT_BCN_TIMEOUT);
+-      if (err) {
+-              brcmf_err("bcn_timeout error (%d)\n", err);
+-              goto done;
+-      }
+-
+-      /* Enable/Disable build-in roaming to allowed ext supplicant to take
+-       * of romaing
+-       */
+-      err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1);
+-      if (err) {
+-              brcmf_err("roam_off error (%d)\n", err);
+-              goto done;
+-      }
+-
+       /* Setup join_pref to select target by RSSI(with boost on 5GHz) */
+       join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA;
+       join_pref_params[0].len = 2;
diff --git a/package/kernel/mac80211/patches/376-0007-brcmfmac-Add-beamforming-support.patch b/package/kernel/mac80211/patches/376-0007-brcmfmac-Add-beamforming-support.patch
new file mode 100644 (file)
index 0000000..395166b
--- /dev/null
@@ -0,0 +1,115 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 25 Nov 2015 11:32:43 +0100
+Subject: [PATCH] brcmfmac: Add beamforming support.
+
+Some devices support beamforming. This patch enables tx beamforming
+if supported and reports beamforming capabilities per channel if
+supported.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+@@ -5671,7 +5671,8 @@ static __le16 brcmf_get_mcs_map(u32 ncha
+ }
+ static void brcmf_update_vht_cap(struct ieee80211_supported_band *band,
+-                               u32 bw_cap[2], u32 nchain)
++                               u32 bw_cap[2], u32 nchain, u32 txstreams,
++                               u32 txbf_bfe_cap, u32 txbf_bfr_cap)
+ {
+       __le16 mcs_map;
+@@ -5690,6 +5691,25 @@ static void brcmf_update_vht_cap(struct
+       mcs_map = brcmf_get_mcs_map(nchain, IEEE80211_VHT_MCS_SUPPORT_0_9);
+       band->vht_cap.vht_mcs.rx_mcs_map = mcs_map;
+       band->vht_cap.vht_mcs.tx_mcs_map = mcs_map;
++
++      /* Beamforming support information */
++      if (txbf_bfe_cap & BRCMF_TXBF_SU_BFE_CAP)
++              band->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
++      if (txbf_bfe_cap & BRCMF_TXBF_MU_BFE_CAP)
++              band->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
++      if (txbf_bfr_cap & BRCMF_TXBF_SU_BFR_CAP)
++              band->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
++      if (txbf_bfr_cap & BRCMF_TXBF_MU_BFR_CAP)
++              band->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
++
++      if ((txbf_bfe_cap || txbf_bfr_cap) && (txstreams > 1)) {
++              band->vht_cap.cap |=
++                      (2 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);
++              band->vht_cap.cap |= ((txstreams - 1) <<
++                              IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT);
++              band->vht_cap.cap |=
++                      IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
++      }
+ }
+ static int brcmf_setup_wiphybands(struct wiphy *wiphy)
+@@ -5704,6 +5724,9 @@ static int brcmf_setup_wiphybands(struct
+       int err;
+       s32 i;
+       struct ieee80211_supported_band *band;
++      u32 txstreams = 0;
++      u32 txbf_bfe_cap = 0;
++      u32 txbf_bfr_cap = 0;
+       (void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode);
+       err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);
+@@ -5732,6 +5755,14 @@ static int brcmf_setup_wiphybands(struct
+               return err;
+       }
++      if (vhtmode) {
++              (void)brcmf_fil_iovar_int_get(ifp, "txstreams", &txstreams);
++              (void)brcmf_fil_iovar_int_get(ifp, "txbf_bfe_cap",
++                                            &txbf_bfe_cap);
++              (void)brcmf_fil_iovar_int_get(ifp, "txbf_bfr_cap",
++                                            &txbf_bfr_cap);
++      }
++
+       wiphy = cfg_to_wiphy(cfg);
+       for (i = 0; i < ARRAY_SIZE(wiphy->bands); i++) {
+               band = wiphy->bands[i];
+@@ -5741,7 +5772,8 @@ static int brcmf_setup_wiphybands(struct
+               if (nmode)
+                       brcmf_update_ht_cap(band, bw_cap, nchain);
+               if (vhtmode)
+-                      brcmf_update_vht_cap(band, bw_cap, nchain);
++                      brcmf_update_vht_cap(band, bw_cap, nchain, txstreams,
++                                           txbf_bfe_cap, txbf_bfr_cap);
+       }
+       return 0;
+--- a/drivers/net/wireless/brcm80211/brcmfmac/common.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/common.c
+@@ -153,6 +153,9 @@ int brcmf_c_preinit_dcmds(struct brcmf_i
+               goto done;
+       }
++      /* Enable tx beamforming, errors can be ignored (not supported) */
++      (void)brcmf_fil_iovar_int_set(ifp, "txbf", 1);
++
+       /* do bus specific preinit here */
+       err = brcmf_bus_preinit(ifp->drvr->bus_if);
+ done:
+--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
+@@ -121,6 +121,11 @@
+ #define BRCMF_MAX_ASSOCLIST           128
++#define BRCMF_TXBF_SU_BFE_CAP         BIT(0)
++#define BRCMF_TXBF_MU_BFE_CAP         BIT(1)
++#define BRCMF_TXBF_SU_BFR_CAP         BIT(0)
++#define BRCMF_TXBF_MU_BFR_CAP         BIT(1)
++
+ /* join preference types for join_pref iovar */
+ enum brcmf_join_pref_types {
+       BRCMF_JOIN_PREF_RSSI = 1,
diff --git a/package/kernel/mac80211/patches/376-0008-brcmfmac-assure-net_ratelimit-is-declared-before-use.patch b/package/kernel/mac80211/patches/376-0008-brcmfmac-assure-net_ratelimit-is-declared-before-use.patch
new file mode 100644 (file)
index 0000000..d471eb5
--- /dev/null
@@ -0,0 +1,25 @@
+From: Arend van Spriel <arend@broadcom.com>
+Date: Wed, 25 Nov 2015 11:32:45 +0100
+Subject: [PATCH] brcmfmac: assure net_ratelimit() is declared before use
+
+Under some kernel configuration we get build issue with implicit
+declaration of net_ratelimit() function. Fix this by explicitly
+including the file providing the prototype.
+
+Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/debug.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.h
+@@ -17,6 +17,8 @@
+ #ifndef BRCMFMAC_DEBUG_H
+ #define BRCMFMAC_DEBUG_H
++#include <linux/net.h>        /* net_ratelimit() */
++
+ /* message levels */
+ #define BRCMF_TRACE_VAL               0x00000002
+ #define BRCMF_INFO_VAL                0x00000004
diff --git a/package/kernel/mac80211/patches/376-0009-brcmfmac-Unify-methods-to-define-and-map-firmware-fi.patch b/package/kernel/mac80211/patches/376-0009-brcmfmac-Unify-methods-to-define-and-map-firmware-fi.patch
new file mode 100644 (file)
index 0000000..0ec9d10
--- /dev/null
@@ -0,0 +1,664 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 25 Nov 2015 11:32:46 +0100
+Subject: [PATCH] brcmfmac: Unify methods to define and map firmware files.
+
+All bus drivers (sdio, usb and pcie) require firmware files which
+needs to be downloaded to the device, The definitions and mapping
+of device id and revision to firmware and nvram file is done by
+each bus driver. This patch creates common functions and defines
+to simplify and unify the definition of these firmware and nvram
+files and mapping.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+@@ -27,9 +27,9 @@
+ #define BRCMF_FW_NVRAM_DEVPATH_LEN            19      /* devpath0=pcie/1/4/ */
+ #define BRCMF_FW_NVRAM_PCIEDEV_LEN            10      /* pcie/1/4/ + \0 */
+-char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
++static char brcmf_firmware_path[BRCMF_FW_NAME_LEN];
+ module_param_string(alternative_fw_path, brcmf_firmware_path,
+-                  BRCMF_FW_PATH_LEN, 0440);
++                  BRCMF_FW_NAME_LEN, 0440);
+ enum nvram_parser_state {
+       IDLE,
+@@ -531,3 +531,43 @@ int brcmf_fw_get_firmwares(struct device
+                                          0);
+ }
++int brcmf_fw_map_chip_to_name(u32 chip, u32 chiprev,
++                            struct brcmf_firmware_mapping mapping_table[],
++                            u32 table_size, char fw_name[BRCMF_FW_NAME_LEN],
++                            char nvram_name[BRCMF_FW_NAME_LEN])
++{
++      u32 i;
++      char end;
++
++      for (i = 0; i < table_size; i++) {
++              if (mapping_table[i].chipid == chip &&
++                  mapping_table[i].revmask & BIT(chiprev))
++                      break;
++      }
++
++      if (i == table_size) {
++              brcmf_err("Unknown chipid %d [%d]\n", chip, chiprev);
++              return -ENODEV;
++      }
++
++      /* check if firmware path is provided by module parameter */
++      if (brcmf_firmware_path[0] != '\0') {
++              strlcpy(fw_name, brcmf_firmware_path, BRCMF_FW_NAME_LEN);
++              if ((nvram_name) && (mapping_table[i].nvram))
++                      strlcpy(nvram_name, brcmf_firmware_path,
++                              BRCMF_FW_NAME_LEN);
++
++              end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1];
++              if (end != '/') {
++                      strlcat(fw_name, "/", BRCMF_FW_NAME_LEN);
++                      if ((nvram_name) && (mapping_table[i].nvram))
++                              strlcat(nvram_name, "/", BRCMF_FW_NAME_LEN);
++              }
++      }
++      strlcat(fw_name, mapping_table[i].fw, BRCMF_FW_NAME_LEN);
++      if ((nvram_name) && (mapping_table[i].nvram))
++              strlcat(nvram_name, mapping_table[i].nvram, BRCMF_FW_NAME_LEN);
++
++      return 0;
++}
++
+--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.h
+@@ -21,11 +21,51 @@
+ #define BRCMF_FW_REQ_FLAGS            0x00F0
+ #define  BRCMF_FW_REQ_NV_OPTIONAL     0x0010
+-#define       BRCMF_FW_PATH_LEN       256
+-#define       BRCMF_FW_NAME_LEN       32
++#define       BRCMF_FW_NAME_LEN               320
+-extern char brcmf_firmware_path[];
++#define BRCMF_FW_DEFAULT_PATH         "brcm/"
++/**
++ * struct brcmf_firmware_mapping - Used to map chipid/revmask to firmware
++ *    filename and nvram filename. Each bus type implementation should create
++ *    a table of firmware mappings (using the macros defined below).
++ *
++ * @chipid: ID of chip.
++ * @revmask: bitmask of revisions, e.g. 0x10 means rev 4 only, 0xf means rev 0-3
++ * @fw: name of the firmware file.
++ * @nvram: name of nvram file.
++ */
++struct brcmf_firmware_mapping {
++      u32 chipid;
++      u32 revmask;
++      const char *fw;
++      const char *nvram;
++};
++
++#define BRCMF_FW_NVRAM_DEF(fw_nvram_name, fw, nvram) \
++static const char BRCM_ ## fw_nvram_name ## _FIRMWARE_NAME[] = \
++      BRCMF_FW_DEFAULT_PATH fw; \
++static const char BRCM_ ## fw_nvram_name ## _NVRAM_NAME[] = \
++      BRCMF_FW_DEFAULT_PATH nvram; \
++MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw); \
++MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH nvram)
++
++#define BRCMF_FW_DEF(fw_name, fw) \
++static const char BRCM_ ## fw_name ## _FIRMWARE_NAME[] = \
++      BRCMF_FW_DEFAULT_PATH fw; \
++MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw) \
++
++#define BRCMF_FW_NVRAM_ENTRY(chipid, mask, name) \
++      { chipid, mask, \
++        BRCM_ ## name ## _FIRMWARE_NAME, BRCM_ ## name ## _NVRAM_NAME }
++
++#define BRCMF_FW_ENTRY(chipid, mask, name) \
++      { chipid, mask, BRCM_ ## name ## _FIRMWARE_NAME, NULL }
++
++int brcmf_fw_map_chip_to_name(u32 chip, u32 chiprev,
++                            struct brcmf_firmware_mapping mapping_table[],
++                            u32 table_size, char fw_name[BRCMF_FW_NAME_LEN],
++                            char nvram_name[BRCMF_FW_NAME_LEN]);
+ void brcmf_fw_nvram_free(void *nvram);
+ /*
+  * Request firmware(s) asynchronously. When the asynchronous request
+--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+@@ -44,25 +44,29 @@ enum brcmf_pcie_state {
+       BRCMFMAC_PCIE_STATE_UP
+ };
+-
+-#define BRCMF_PCIE_43602_FW_NAME              "brcm/brcmfmac43602-pcie.bin"
+-#define BRCMF_PCIE_43602_NVRAM_NAME           "brcm/brcmfmac43602-pcie.txt"
+-#define BRCMF_PCIE_4350_FW_NAME                       "brcm/brcmfmac4350-pcie.bin"
+-#define BRCMF_PCIE_4350_NVRAM_NAME            "brcm/brcmfmac4350-pcie.txt"
+-#define BRCMF_PCIE_4356_FW_NAME                       "brcm/brcmfmac4356-pcie.bin"
+-#define BRCMF_PCIE_4356_NVRAM_NAME            "brcm/brcmfmac4356-pcie.txt"
+-#define BRCMF_PCIE_43570_FW_NAME              "brcm/brcmfmac43570-pcie.bin"
+-#define BRCMF_PCIE_43570_NVRAM_NAME           "brcm/brcmfmac43570-pcie.txt"
+-#define BRCMF_PCIE_4358_FW_NAME                       "brcm/brcmfmac4358-pcie.bin"
+-#define BRCMF_PCIE_4358_NVRAM_NAME            "brcm/brcmfmac4358-pcie.txt"
+-#define BRCMF_PCIE_4359_FW_NAME                       "brcm/brcmfmac4359-pcie.bin"
+-#define BRCMF_PCIE_4359_NVRAM_NAME            "brcm/brcmfmac4359-pcie.txt"
+-#define BRCMF_PCIE_4365_FW_NAME                       "brcm/brcmfmac4365b-pcie.bin"
+-#define BRCMF_PCIE_4365_NVRAM_NAME            "brcm/brcmfmac4365b-pcie.txt"
+-#define BRCMF_PCIE_4366_FW_NAME                       "brcm/brcmfmac4366b-pcie.bin"
+-#define BRCMF_PCIE_4366_NVRAM_NAME            "brcm/brcmfmac4366b-pcie.txt"
+-#define BRCMF_PCIE_4371_FW_NAME                       "brcm/brcmfmac4371-pcie.bin"
+-#define BRCMF_PCIE_4371_NVRAM_NAME            "brcm/brcmfmac4371-pcie.txt"
++BRCMF_FW_NVRAM_DEF(43602, "brcmfmac43602-pcie.bin", "brcmfmac43602-pcie.txt");
++BRCMF_FW_NVRAM_DEF(4350, "brcmfmac4350-pcie.bin", "brcmfmac4350-pcie.txt");
++BRCMF_FW_NVRAM_DEF(4356, "brcmfmac4356-pcie.bin", "brcmfmac4356-pcie.txt");
++BRCMF_FW_NVRAM_DEF(43570, "brcmfmac43570-pcie.bin", "brcmfmac43570-pcie.txt");
++BRCMF_FW_NVRAM_DEF(4358, "brcmfmac4358-pcie.bin", "brcmfmac4358-pcie.txt");
++BRCMF_FW_NVRAM_DEF(4359, "brcmfmac4359-pcie.bin", "brcmfmac4359-pcie.txt");
++BRCMF_FW_NVRAM_DEF(4365B, "brcmfmac4365b-pcie.bin", "brcmfmac4365b-pcie.txt");
++BRCMF_FW_NVRAM_DEF(4366B, "brcmfmac4366b-pcie.bin", "brcmfmac4366b-pcie.txt");
++BRCMF_FW_NVRAM_DEF(4371, "brcmfmac4371-pcie.bin", "brcmfmac4371-pcie.txt");
++
++static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4350_CHIP_ID, 0xFFFFFFFF, 4350),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43567_CHIP_ID, 0xFFFFFFFF, 43570),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43569_CHIP_ID, 0xFFFFFFFF, 43570),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43570_CHIP_ID, 0xFFFFFFFF, 43570),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFFF, 4365B),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4366_CHIP_ID, 0xFFFFFFFF, 4366B),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),
++};
+ #define BRCMF_PCIE_FW_UP_TIMEOUT              2000 /* msec */
+@@ -202,26 +206,6 @@ enum brcmf_pcie_state {
+ #define BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB 3
+-MODULE_FIRMWARE(BRCMF_PCIE_43602_FW_NAME);
+-MODULE_FIRMWARE(BRCMF_PCIE_43602_NVRAM_NAME);
+-MODULE_FIRMWARE(BRCMF_PCIE_4350_FW_NAME);
+-MODULE_FIRMWARE(BRCMF_PCIE_4350_NVRAM_NAME);
+-MODULE_FIRMWARE(BRCMF_PCIE_4356_FW_NAME);
+-MODULE_FIRMWARE(BRCMF_PCIE_4356_NVRAM_NAME);
+-MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME);
+-MODULE_FIRMWARE(BRCMF_PCIE_43570_NVRAM_NAME);
+-MODULE_FIRMWARE(BRCMF_PCIE_4358_FW_NAME);
+-MODULE_FIRMWARE(BRCMF_PCIE_4358_NVRAM_NAME);
+-MODULE_FIRMWARE(BRCMF_PCIE_4359_FW_NAME);
+-MODULE_FIRMWARE(BRCMF_PCIE_4359_NVRAM_NAME);
+-MODULE_FIRMWARE(BRCMF_PCIE_4365_FW_NAME);
+-MODULE_FIRMWARE(BRCMF_PCIE_4365_NVRAM_NAME);
+-MODULE_FIRMWARE(BRCMF_PCIE_4366_FW_NAME);
+-MODULE_FIRMWARE(BRCMF_PCIE_4366_NVRAM_NAME);
+-MODULE_FIRMWARE(BRCMF_PCIE_4371_FW_NAME);
+-MODULE_FIRMWARE(BRCMF_PCIE_4371_NVRAM_NAME);
+-
+-
+ struct brcmf_pcie_console {
+       u32 base_addr;
+       u32 buf_addr;
+@@ -258,8 +242,8 @@ struct brcmf_pciedev_info {
+       enum brcmf_pcie_state state;
+       bool in_irq;
+       struct pci_dev *pdev;
+-      char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
+-      char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
++      char fw_name[BRCMF_FW_NAME_LEN];
++      char nvram_name[BRCMF_FW_NAME_LEN];
+       void __iomem *regs;
+       void __iomem *tcm;
+       u32 tcm_size;
+@@ -1478,84 +1462,6 @@ brcmf_pcie_init_share_ram_info(struct br
+ }
+-static int brcmf_pcie_get_fwnames(struct brcmf_pciedev_info *devinfo)
+-{
+-      char *fw_name;
+-      char *nvram_name;
+-      uint fw_len, nv_len;
+-      char end;
+-
+-      brcmf_dbg(PCIE, "Enter, chip 0x%04x chiprev %d\n", devinfo->ci->chip,
+-                devinfo->ci->chiprev);
+-
+-      switch (devinfo->ci->chip) {
+-      case BRCM_CC_43602_CHIP_ID:
+-              fw_name = BRCMF_PCIE_43602_FW_NAME;
+-              nvram_name = BRCMF_PCIE_43602_NVRAM_NAME;
+-              break;
+-      case BRCM_CC_4350_CHIP_ID:
+-              fw_name = BRCMF_PCIE_4350_FW_NAME;
+-              nvram_name = BRCMF_PCIE_4350_NVRAM_NAME;
+-              break;
+-      case BRCM_CC_4356_CHIP_ID:
+-              fw_name = BRCMF_PCIE_4356_FW_NAME;
+-              nvram_name = BRCMF_PCIE_4356_NVRAM_NAME;
+-              break;
+-      case BRCM_CC_43567_CHIP_ID:
+-      case BRCM_CC_43569_CHIP_ID:
+-      case BRCM_CC_43570_CHIP_ID:
+-              fw_name = BRCMF_PCIE_43570_FW_NAME;
+-              nvram_name = BRCMF_PCIE_43570_NVRAM_NAME;
+-              break;
+-      case BRCM_CC_4358_CHIP_ID:
+-              fw_name = BRCMF_PCIE_4358_FW_NAME;
+-              nvram_name = BRCMF_PCIE_4358_NVRAM_NAME;
+-              break;
+-      case BRCM_CC_4359_CHIP_ID:
+-              fw_name = BRCMF_PCIE_4359_FW_NAME;
+-              nvram_name = BRCMF_PCIE_4359_NVRAM_NAME;
+-              break;
+-      case BRCM_CC_4365_CHIP_ID:
+-              fw_name = BRCMF_PCIE_4365_FW_NAME;
+-              nvram_name = BRCMF_PCIE_4365_NVRAM_NAME;
+-              break;
+-      case BRCM_CC_4366_CHIP_ID:
+-              fw_name = BRCMF_PCIE_4366_FW_NAME;
+-              nvram_name = BRCMF_PCIE_4366_NVRAM_NAME;
+-              break;
+-      case BRCM_CC_4371_CHIP_ID:
+-              fw_name = BRCMF_PCIE_4371_FW_NAME;
+-              nvram_name = BRCMF_PCIE_4371_NVRAM_NAME;
+-              break;
+-      default:
+-              brcmf_err("Unsupported chip 0x%04x\n", devinfo->ci->chip);
+-              return -ENODEV;
+-      }
+-
+-      fw_len = sizeof(devinfo->fw_name) - 1;
+-      nv_len = sizeof(devinfo->nvram_name) - 1;
+-      /* check if firmware path is provided by module parameter */
+-      if (brcmf_firmware_path[0] != '\0') {
+-              strncpy(devinfo->fw_name, brcmf_firmware_path, fw_len);
+-              strncpy(devinfo->nvram_name, brcmf_firmware_path, nv_len);
+-              fw_len -= strlen(devinfo->fw_name);
+-              nv_len -= strlen(devinfo->nvram_name);
+-
+-              end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1];
+-              if (end != '/') {
+-                      strncat(devinfo->fw_name, "/", fw_len);
+-                      strncat(devinfo->nvram_name, "/", nv_len);
+-                      fw_len--;
+-                      nv_len--;
+-              }
+-      }
+-      strncat(devinfo->fw_name, fw_name, fw_len);
+-      strncat(devinfo->nvram_name, nvram_name, nv_len);
+-
+-      return 0;
+-}
+-
+-
+ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
+                                       const struct firmware *fw, void *nvram,
+                                       u32 nvram_len)
+@@ -1891,7 +1797,10 @@ brcmf_pcie_probe(struct pci_dev *pdev, c
+       bus->wowl_supported = pci_pme_capable(pdev, PCI_D3hot);
+       dev_set_drvdata(&pdev->dev, bus);
+-      ret = brcmf_pcie_get_fwnames(devinfo);
++      ret = brcmf_fw_map_chip_to_name(devinfo->ci->chip, devinfo->ci->chiprev,
++                                      brcmf_pcie_fwnames,
++                                      ARRAY_SIZE(brcmf_pcie_fwnames),
++                                      devinfo->fw_name, devinfo->nvram_name);
+       if (ret)
+               goto fail_bus;
+--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+@@ -596,136 +596,41 @@ static const struct sdiod_drive_str sdio
+       {4,  0x1}
+ };
+-#define BCM43143_FIRMWARE_NAME                "brcm/brcmfmac43143-sdio.bin"
+-#define BCM43143_NVRAM_NAME           "brcm/brcmfmac43143-sdio.txt"
+-#define BCM43241B0_FIRMWARE_NAME      "brcm/brcmfmac43241b0-sdio.bin"
+-#define BCM43241B0_NVRAM_NAME         "brcm/brcmfmac43241b0-sdio.txt"
+-#define BCM43241B4_FIRMWARE_NAME      "brcm/brcmfmac43241b4-sdio.bin"
+-#define BCM43241B4_NVRAM_NAME         "brcm/brcmfmac43241b4-sdio.txt"
+-#define BCM43241B5_FIRMWARE_NAME      "brcm/brcmfmac43241b5-sdio.bin"
+-#define BCM43241B5_NVRAM_NAME         "brcm/brcmfmac43241b5-sdio.txt"
+-#define BCM4329_FIRMWARE_NAME         "brcm/brcmfmac4329-sdio.bin"
+-#define BCM4329_NVRAM_NAME            "brcm/brcmfmac4329-sdio.txt"
+-#define BCM4330_FIRMWARE_NAME         "brcm/brcmfmac4330-sdio.bin"
+-#define BCM4330_NVRAM_NAME            "brcm/brcmfmac4330-sdio.txt"
+-#define BCM4334_FIRMWARE_NAME         "brcm/brcmfmac4334-sdio.bin"
+-#define BCM4334_NVRAM_NAME            "brcm/brcmfmac4334-sdio.txt"
+-#define BCM43340_FIRMWARE_NAME                "brcm/brcmfmac43340-sdio.bin"
+-#define BCM43340_NVRAM_NAME           "brcm/brcmfmac43340-sdio.txt"
+-#define BCM4335_FIRMWARE_NAME         "brcm/brcmfmac4335-sdio.bin"
+-#define BCM4335_NVRAM_NAME            "brcm/brcmfmac4335-sdio.txt"
+-#define BCM43362_FIRMWARE_NAME                "brcm/brcmfmac43362-sdio.bin"
+-#define BCM43362_NVRAM_NAME           "brcm/brcmfmac43362-sdio.txt"
+-#define BCM4339_FIRMWARE_NAME         "brcm/brcmfmac4339-sdio.bin"
+-#define BCM4339_NVRAM_NAME            "brcm/brcmfmac4339-sdio.txt"
+-#define BCM43430_FIRMWARE_NAME                "brcm/brcmfmac43430-sdio.bin"
+-#define BCM43430_NVRAM_NAME           "brcm/brcmfmac43430-sdio.txt"
+-#define BCM43455_FIRMWARE_NAME                "brcm/brcmfmac43455-sdio.bin"
+-#define BCM43455_NVRAM_NAME           "brcm/brcmfmac43455-sdio.txt"
+-#define BCM4354_FIRMWARE_NAME         "brcm/brcmfmac4354-sdio.bin"
+-#define BCM4354_NVRAM_NAME            "brcm/brcmfmac4354-sdio.txt"
+-
+-MODULE_FIRMWARE(BCM43143_FIRMWARE_NAME);
+-MODULE_FIRMWARE(BCM43143_NVRAM_NAME);
+-MODULE_FIRMWARE(BCM43241B0_FIRMWARE_NAME);
+-MODULE_FIRMWARE(BCM43241B0_NVRAM_NAME);
+-MODULE_FIRMWARE(BCM43241B4_FIRMWARE_NAME);
+-MODULE_FIRMWARE(BCM43241B4_NVRAM_NAME);
+-MODULE_FIRMWARE(BCM43241B5_FIRMWARE_NAME);
+-MODULE_FIRMWARE(BCM43241B5_NVRAM_NAME);
+-MODULE_FIRMWARE(BCM4329_FIRMWARE_NAME);
+-MODULE_FIRMWARE(BCM4329_NVRAM_NAME);
+-MODULE_FIRMWARE(BCM4330_FIRMWARE_NAME);
+-MODULE_FIRMWARE(BCM4330_NVRAM_NAME);
+-MODULE_FIRMWARE(BCM4334_FIRMWARE_NAME);
+-MODULE_FIRMWARE(BCM4334_NVRAM_NAME);
+-MODULE_FIRMWARE(BCM43340_FIRMWARE_NAME);
+-MODULE_FIRMWARE(BCM43340_NVRAM_NAME);
+-MODULE_FIRMWARE(BCM4335_FIRMWARE_NAME);
+-MODULE_FIRMWARE(BCM4335_NVRAM_NAME);
+-MODULE_FIRMWARE(BCM43362_FIRMWARE_NAME);
+-MODULE_FIRMWARE(BCM43362_NVRAM_NAME);
+-MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME);
+-MODULE_FIRMWARE(BCM4339_NVRAM_NAME);
+-MODULE_FIRMWARE(BCM43430_FIRMWARE_NAME);
+-MODULE_FIRMWARE(BCM43430_NVRAM_NAME);
+-MODULE_FIRMWARE(BCM43455_FIRMWARE_NAME);
+-MODULE_FIRMWARE(BCM43455_NVRAM_NAME);
+-MODULE_FIRMWARE(BCM4354_FIRMWARE_NAME);
+-MODULE_FIRMWARE(BCM4354_NVRAM_NAME);
+-
+-struct brcmf_firmware_names {
+-      u32 chipid;
+-      u32 revmsk;
+-      const char *bin;
+-      const char *nv;
++BRCMF_FW_NVRAM_DEF(43143, "brcmfmac43143-sdio.bin", "brcmfmac43143-sdio.txt");
++BRCMF_FW_NVRAM_DEF(43241B0, "brcmfmac43241b0-sdio.bin",
++                 "brcmfmac43241b0-sdio.txt");
++BRCMF_FW_NVRAM_DEF(43241B4, "brcmfmac43241b4-sdio.bin",
++                 "brcmfmac43241b4-sdio.txt");
++BRCMF_FW_NVRAM_DEF(43241B5, "brcmfmac43241b5-sdio.bin",
++                 "brcmfmac43241b5-sdio.txt");
++BRCMF_FW_NVRAM_DEF(4329, "brcmfmac4329-sdio.bin", "brcmfmac4329-sdio.txt");
++BRCMF_FW_NVRAM_DEF(4330, "brcmfmac4330-sdio.bin", "brcmfmac4330-sdio.txt");
++BRCMF_FW_NVRAM_DEF(4334, "brcmfmac4334-sdio.bin", "brcmfmac4334-sdio.txt");
++BRCMF_FW_NVRAM_DEF(43340, "brcmfmac43340-sdio.bin", "brcmfmac43340-sdio.txt");
++BRCMF_FW_NVRAM_DEF(4335, "brcmfmac4335-sdio.bin", "brcmfmac4335-sdio.txt");
++BRCMF_FW_NVRAM_DEF(43362, "brcmfmac43362-sdio.bin", "brcmfmac43362-sdio.txt");
++BRCMF_FW_NVRAM_DEF(4339, "brcmfmac4339-sdio.bin", "brcmfmac4339-sdio.txt");
++BRCMF_FW_NVRAM_DEF(43430, "brcmfmac43430-sdio.bin", "brcmfmac43430-sdio.txt");
++BRCMF_FW_NVRAM_DEF(43455, "brcmfmac43455-sdio.bin", "brcmfmac43455-sdio.txt");
++BRCMF_FW_NVRAM_DEF(4354, "brcmfmac4354-sdio.bin", "brcmfmac4354-sdio.txt");
++
++static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43241_CHIP_ID, 0x00000020, 43241B4),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43241_CHIP_ID, 0xFFFFFFC0, 43241B5),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, 4329),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFF, 43430),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, 43455),
++      BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354)
+ };
+-enum brcmf_firmware_type {
+-      BRCMF_FIRMWARE_BIN,
+-      BRCMF_FIRMWARE_NVRAM
+-};
+-
+-#define BRCMF_FIRMWARE_NVRAM(name) \
+-      name ## _FIRMWARE_NAME, name ## _NVRAM_NAME
+-
+-static const struct brcmf_firmware_names brcmf_fwname_data[] = {
+-      { BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43143) },
+-      { BRCM_CC_43241_CHIP_ID, 0x0000001F, BRCMF_FIRMWARE_NVRAM(BCM43241B0) },
+-      { BRCM_CC_43241_CHIP_ID, 0x00000020, BRCMF_FIRMWARE_NVRAM(BCM43241B4) },
+-      { BRCM_CC_43241_CHIP_ID, 0xFFFFFFC0, BRCMF_FIRMWARE_NVRAM(BCM43241B5) },
+-      { BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) },
+-      { BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) },
+-      { BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) },
+-      { BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43340) },
+-      { BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) },
+-      { BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) },
+-      { BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) },
+-      { BRCM_CC_43430_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43430) },
+-      { BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, BRCMF_FIRMWARE_NVRAM(BCM43455) },
+-      { BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) }
+-};
+-
+-static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci,
+-                                struct brcmf_sdio_dev *sdiodev)
+-{
+-      int i;
+-      char end;
+-
+-      for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) {
+-              if (brcmf_fwname_data[i].chipid == ci->chip &&
+-                  brcmf_fwname_data[i].revmsk & BIT(ci->chiprev))
+-                      break;
+-      }
+-
+-      if (i == ARRAY_SIZE(brcmf_fwname_data)) {
+-              brcmf_err("Unknown chipid %d [%d]\n", ci->chip, ci->chiprev);
+-              return -ENODEV;
+-      }
+-
+-      /* check if firmware path is provided by module parameter */
+-      if (brcmf_firmware_path[0] != '\0') {
+-              strlcpy(sdiodev->fw_name, brcmf_firmware_path,
+-                      sizeof(sdiodev->fw_name));
+-              strlcpy(sdiodev->nvram_name, brcmf_firmware_path,
+-                      sizeof(sdiodev->nvram_name));
+-
+-              end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1];
+-              if (end != '/') {
+-                      strlcat(sdiodev->fw_name, "/",
+-                              sizeof(sdiodev->fw_name));
+-                      strlcat(sdiodev->nvram_name, "/",
+-                              sizeof(sdiodev->nvram_name));
+-              }
+-      }
+-      strlcat(sdiodev->fw_name, brcmf_fwname_data[i].bin,
+-              sizeof(sdiodev->fw_name));
+-      strlcat(sdiodev->nvram_name, brcmf_fwname_data[i].nv,
+-              sizeof(sdiodev->nvram_name));
+-
+-      return 0;
+-}
+-
+ static void pkt_align(struct sk_buff *p, int len, int align)
+ {
+       uint datalign;
+@@ -4252,7 +4157,10 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
+       brcmf_sdio_debugfs_create(bus);
+       brcmf_dbg(INFO, "completed!!\n");
+-      ret = brcmf_sdio_get_fwnames(bus->ci, sdiodev);
++      ret = brcmf_fw_map_chip_to_name(bus->ci->chip, bus->ci->chiprev,
++                                      brcmf_sdio_fwnames,
++                                      ARRAY_SIZE(brcmf_sdio_fwnames),
++                                      sdiodev->fw_name, sdiodev->nvram_name);
+       if (ret)
+               goto fail;
+--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h
++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h
+@@ -195,8 +195,8 @@ struct brcmf_sdio_dev {
+       uint max_segment_size;
+       uint txglomsz;
+       struct sg_table sgtable;
+-      char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
+-      char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
++      char fw_name[BRCMF_FW_NAME_LEN];
++      char nvram_name[BRCMF_FW_NAME_LEN];
+       bool wowl_enabled;
+       enum brcmf_sdiod_state state;
+       struct brcmf_sdiod_freezer *freezer;
+--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+@@ -43,10 +43,20 @@
+ #define BRCMF_USB_CBCTL_READ          1
+ #define BRCMF_USB_MAX_PKT_SIZE                1600
+-#define BRCMF_USB_43143_FW_NAME               "brcm/brcmfmac43143.bin"
+-#define BRCMF_USB_43236_FW_NAME               "brcm/brcmfmac43236b.bin"
+-#define BRCMF_USB_43242_FW_NAME               "brcm/brcmfmac43242a.bin"
+-#define BRCMF_USB_43569_FW_NAME               "brcm/brcmfmac43569.bin"
++BRCMF_FW_DEF(43143, "brcmfmac43143.bin");
++BRCMF_FW_DEF(43236B, "brcmfmac43236b.bin");
++BRCMF_FW_DEF(43242A, "brcmfmac43242a.bin");
++BRCMF_FW_DEF(43569, "brcmfmac43569.bin");
++
++static struct brcmf_firmware_mapping brcmf_usb_fwnames[] = {
++      BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
++      BRCMF_FW_ENTRY(BRCM_CC_43235_CHIP_ID, 0x00000008, 43236B),
++      BRCMF_FW_ENTRY(BRCM_CC_43236_CHIP_ID, 0x00000008, 43236B),
++      BRCMF_FW_ENTRY(BRCM_CC_43238_CHIP_ID, 0x00000008, 43236B),
++      BRCMF_FW_ENTRY(BRCM_CC_43242_CHIP_ID, 0xFFFFFFFF, 43242A),
++      BRCMF_FW_ENTRY(BRCM_CC_43566_CHIP_ID, 0xFFFFFFFF, 43569),
++      BRCMF_FW_ENTRY(BRCM_CC_43569_CHIP_ID, 0xFFFFFFFF, 43569)
++};
+ #define TRX_MAGIC             0x30524448      /* "HDR0" */
+ #define TRX_MAX_OFFSET                3               /* Max number of file offsets */
+@@ -139,6 +149,7 @@ struct brcmf_usbdev_info {
+       struct brcmf_usbreq *tx_reqs;
+       struct brcmf_usbreq *rx_reqs;
++      char fw_name[BRCMF_FW_NAME_LEN];
+       const u8 *image;        /* buffer for combine fw and nvram */
+       int image_len;
+@@ -983,45 +994,15 @@ static int brcmf_usb_dlrun(struct brcmf_
+       return 0;
+ }
+-static bool brcmf_usb_chip_support(int chipid, int chiprev)
+-{
+-      switch(chipid) {
+-      case BRCM_CC_43143_CHIP_ID:
+-              return true;
+-      case BRCM_CC_43235_CHIP_ID:
+-      case BRCM_CC_43236_CHIP_ID:
+-      case BRCM_CC_43238_CHIP_ID:
+-              return (chiprev == 3);
+-      case BRCM_CC_43242_CHIP_ID:
+-              return true;
+-      case BRCM_CC_43566_CHIP_ID:
+-      case BRCM_CC_43569_CHIP_ID:
+-              return true;
+-      default:
+-              break;
+-      }
+-      return false;
+-}
+-
+ static int
+ brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
+ {
+-      int devid, chiprev;
+       int err;
+       brcmf_dbg(USB, "Enter\n");
+       if (devinfo == NULL)
+               return -ENODEV;
+-      devid = devinfo->bus_pub.devid;
+-      chiprev = devinfo->bus_pub.chiprev;
+-
+-      if (!brcmf_usb_chip_support(devid, chiprev)) {
+-              brcmf_err("unsupported chip %d rev %d\n",
+-                        devid, chiprev);
+-              return -EINVAL;
+-      }
+-
+       if (!devinfo->image) {
+               brcmf_err("No firmware!\n");
+               return -ENOENT;
+@@ -1071,25 +1052,6 @@ static int check_file(const u8 *headers)
+       return -1;
+ }
+-static const char *brcmf_usb_get_fwname(struct brcmf_usbdev_info *devinfo)
+-{
+-      switch (devinfo->bus_pub.devid) {
+-      case BRCM_CC_43143_CHIP_ID:
+-              return BRCMF_USB_43143_FW_NAME;
+-      case BRCM_CC_43235_CHIP_ID:
+-      case BRCM_CC_43236_CHIP_ID:
+-      case BRCM_CC_43238_CHIP_ID:
+-              return BRCMF_USB_43236_FW_NAME;
+-      case BRCM_CC_43242_CHIP_ID:
+-              return BRCMF_USB_43242_FW_NAME;
+-      case BRCM_CC_43566_CHIP_ID:
+-      case BRCM_CC_43569_CHIP_ID:
+-              return BRCMF_USB_43569_FW_NAME;
+-      default:
+-              return NULL;
+-      }
+-}
+-
+ static
+ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
+@@ -1274,9 +1236,16 @@ static int brcmf_usb_probe_cb(struct brc
+       bus->chip = bus_pub->devid;
+       bus->chiprev = bus_pub->chiprev;
++      ret = brcmf_fw_map_chip_to_name(bus_pub->devid, bus_pub->chiprev,
++                                      brcmf_usb_fwnames,
++                                      ARRAY_SIZE(brcmf_usb_fwnames),
++                                      devinfo->fw_name, NULL);
++      if (ret)
++              goto fail;
++
+       /* request firmware here */
+-      ret = brcmf_fw_get_firmwares(dev, 0, brcmf_usb_get_fwname(devinfo),
+-                                   NULL, brcmf_usb_probe_phase2);
++      ret = brcmf_fw_get_firmwares(dev, 0, devinfo->fw_name, NULL,
++                                   brcmf_usb_probe_phase2);
+       if (ret) {
+               brcmf_err("firmware request failed: %d\n", ret);
+               goto fail;
+@@ -1472,8 +1441,7 @@ static int brcmf_usb_reset_resume(struct
+       brcmf_dbg(USB, "Enter\n");
+-      return brcmf_fw_get_firmwares(&usb->dev, 0,
+-                                    brcmf_usb_get_fwname(devinfo), NULL,
++      return brcmf_fw_get_firmwares(&usb->dev, 0, devinfo->fw_name, NULL,
+                                     brcmf_usb_probe_phase2);
+ }
+@@ -1491,10 +1459,6 @@ static struct usb_device_id brcmf_usb_de
+ };
+ MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table);
+-MODULE_FIRMWARE(BRCMF_USB_43143_FW_NAME);
+-MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME);
+-MODULE_FIRMWARE(BRCMF_USB_43242_FW_NAME);
+-MODULE_FIRMWARE(BRCMF_USB_43569_FW_NAME);
+ static struct usb_driver brcmf_usbdrvr = {
+       .name = KBUILD_MODNAME,
diff --git a/package/kernel/mac80211/patches/376-0010-brcmfmac-Fix-double-free-on-exception-at-module-load.patch b/package/kernel/mac80211/patches/376-0010-brcmfmac-Fix-double-free-on-exception-at-module-load.patch
new file mode 100644 (file)
index 0000000..2174d09
--- /dev/null
@@ -0,0 +1,22 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 25 Nov 2015 11:32:47 +0100
+Subject: [PATCH] brcmfmac: Fix double free on exception at module load.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+@@ -1083,6 +1083,8 @@ fail:
+                       brcmf_net_detach(ifp->ndev);
+               if (p2p_ifp)
+                       brcmf_net_detach(p2p_ifp->ndev);
++              drvr->iflist[0] = NULL;
++              drvr->iflist[1] = NULL;
+               return ret;
+       }
+       return 0;
diff --git a/package/kernel/mac80211/patches/377-brcmfmac-only-lock-and-unlock-fws-if-fws-is-not-null.patch b/package/kernel/mac80211/patches/377-brcmfmac-only-lock-and-unlock-fws-if-fws-is-not-null.patch
new file mode 100644 (file)
index 0000000..8ec1441
--- /dev/null
@@ -0,0 +1,30 @@
+From: Colin Ian King <colin.king@canonical.com>
+Date: Wed, 2 Dec 2015 11:45:10 +0000
+Subject: [PATCH] brcmfmac: only lock and unlock fws if fws is not null
+
+There is a null ptr check for fws to set bcmc_credit_check, however,
+there a lock and unlock on fws should only performed if fwts is
+also not null to also avoid a potential null pointer deference.
+
+Signed-off-by: Colin Ian King <colin.king@canonical.com>
+Acked-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+@@ -1609,10 +1609,11 @@ static int brcmf_fws_notify_bcmc_credit_
+ {
+       struct brcmf_fws_info *fws = ifp->drvr->fws;
+-      brcmf_fws_lock(fws);
+-      if (fws)
++      if (fws) {
++              brcmf_fws_lock(fws);
+               fws->bcmc_credit_check = true;
+-      brcmf_fws_unlock(fws);
++              brcmf_fws_unlock(fws);
++      }
+       return 0;
+ }
index dbfb1585ec9c387eca4602bcd74b1ee3a51e4c1e..44bb779fd145eee63d717634326adcc1b578344c 100644 (file)
@@ -69,9 +69,9 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
        }
 --- a/drivers/net/wireless/brcm80211/brcmfmac/debug.h
 +++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.h
-@@ -17,6 +17,8 @@
- #ifndef BRCMFMAC_DEBUG_H
- #define BRCMFMAC_DEBUG_H
+@@ -19,6 +19,8 @@
+ #include <linux/net.h>        /* net_ratelimit() */
  
 +#include <linux/net.h>
 +
index 7bb6bed585951e063637e20e3db551cc3588af23..14f8a001aff74666e068eb98178774f35e3c5f57 100644 (file)
@@ -13,7 +13,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
 
 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
 +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
-@@ -1236,6 +1236,7 @@ static int __init brcmfmac_module_init(v
+@@ -1226,6 +1226,7 @@ static int __init brcmfmac_module_init(v
  #endif
        if (!schedule_work(&brcmf_driver_work))
                return -EBUSY;