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