--- /dev/null
+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 */
--- /dev/null
+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
--- /dev/null
+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,
--- /dev/null
+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;
--- /dev/null
+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);
+
--- /dev/null
+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
--- /dev/null
+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:
+ *
--- /dev/null
+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);
--- /dev/null
+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
+ };
+
+
--- /dev/null
+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_ */
--- /dev/null
+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,
--- /dev/null
+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;
--- /dev/null
+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
--- /dev/null
+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);
+ }
+ }
--- /dev/null
+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;
--- /dev/null
+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, ¶ms->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;
--- /dev/null
+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;
--- /dev/null
+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,
--- /dev/null
+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
--- /dev/null
+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,
--- /dev/null
+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;
--- /dev/null
+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;
+ }
+
}
--- 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>
+
--- 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;