From e52e8480add7607fe9643111d34ac3efdecad29a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 1 Mar 2018 15:08:25 +0100 Subject: [PATCH] mac80211: brcmfmac: backport remaining changes from 4.15 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki --- ...15-brcmfmac-add-CLM-download-support.patch | 434 ++++++++++++++++++ ...driver-unbind-order-of-the-sdio-func.patch | 37 ++ ...fmac-Avoid-build-error-with-make-W-1.patch | 33 ++ ...-load-error-for-legacy-chips-when-us.patch | 40 ++ ...-register-wiphy-s-during-module_init.patch | 2 +- ...e-internal-roaming-engine-by-default.patch | 2 +- 6 files changed, 546 insertions(+), 2 deletions(-) create mode 100644 package/kernel/mac80211/patches/304-v4.15-brcmfmac-add-CLM-download-support.patch create mode 100644 package/kernel/mac80211/patches/305-v4.15-brcmfmac-change-driver-unbind-order-of-the-sdio-func.patch create mode 100644 package/kernel/mac80211/patches/306-v4.15-brcmfmac-Avoid-build-error-with-make-W-1.patch create mode 100644 package/kernel/mac80211/patches/307-v4.15-brcmfmac-fix-CLM-load-error-for-legacy-chips-when-us.patch diff --git a/package/kernel/mac80211/patches/304-v4.15-brcmfmac-add-CLM-download-support.patch b/package/kernel/mac80211/patches/304-v4.15-brcmfmac-add-CLM-download-support.patch new file mode 100644 index 0000000000..2cd5f73126 --- /dev/null +++ b/package/kernel/mac80211/patches/304-v4.15-brcmfmac-add-CLM-download-support.patch @@ -0,0 +1,434 @@ +From fdd0bd88ceaecf729db103ac8836af5805dd2dc1 Mon Sep 17 00:00:00 2001 +From: Chung-Hsien Hsu +Date: Fri, 10 Nov 2017 17:27:15 +0800 +Subject: [PATCH] brcmfmac: add CLM download support + +The firmware for brcmfmac devices includes information regarding +regulatory constraints. For certain devices this information is kept +separately in a binary form that needs to be downloaded to the device. +This patch adds support to download this so-called CLM blob file. It +uses the same naming scheme as the other firmware files with extension +of .clm_blob. + +The CLM blob file is optional. If the file does not exist, the download +process will be bypassed. It will not affect the driver loading. + +Reviewed-by: Arend van Spriel +Signed-off-by: Chung-Hsien Hsu +Signed-off-by: Kalle Valo +--- + .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 10 ++ + .../wireless/broadcom/brcm80211/brcmfmac/common.c | 157 +++++++++++++++++++++ + .../wireless/broadcom/brcm80211/brcmfmac/core.c | 2 + + .../wireless/broadcom/brcm80211/brcmfmac/core.h | 2 + + .../broadcom/brcm80211/brcmfmac/fwil_types.h | 31 ++++ + .../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 19 +++ + .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 19 +++ + .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 18 +++ + 8 files changed, 258 insertions(+) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +@@ -71,6 +71,7 @@ struct brcmf_bus_dcmd { + * @wowl_config: specify if dongle is configured for wowl when going to suspend + * @get_ramsize: obtain size of device memory. + * @get_memdump: obtain device memory dump in provided buffer. ++ * @get_fwname: obtain firmware name. + * + * This structure provides an abstract interface towards the + * bus specific driver. For control messages to common driver +@@ -87,6 +88,8 @@ struct brcmf_bus_ops { + void (*wowl_config)(struct device *dev, bool enabled); + size_t (*get_ramsize)(struct device *dev); + int (*get_memdump)(struct device *dev, void *data, size_t len); ++ int (*get_fwname)(struct device *dev, uint chip, uint chiprev, ++ unsigned char *fw_name); + }; + + +@@ -224,6 +227,13 @@ int brcmf_bus_get_memdump(struct brcmf_b + return bus->ops->get_memdump(bus->dev, data, len); + } + ++static inline ++int brcmf_bus_get_fwname(struct brcmf_bus *bus, uint chip, uint chiprev, ++ unsigned char *fw_name) ++{ ++ return bus->ops->get_fwname(bus->dev, chip, chiprev, fw_name); ++} ++ + /* + * interface functions from common layer + */ +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + #include + #include "core.h" +@@ -28,6 +29,7 @@ + #include "tracepoint.h" + #include "common.h" + #include "of.h" ++#include "firmware.h" + + MODULE_AUTHOR("Broadcom Corporation"); + MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); +@@ -104,12 +106,140 @@ void brcmf_c_set_joinpref_default(struct + brcmf_err("Set join_pref error (%d)\n", err); + } + ++static int brcmf_c_download(struct brcmf_if *ifp, u16 flag, ++ struct brcmf_dload_data_le *dload_buf, ++ u32 len) ++{ ++ s32 err; ++ ++ flag |= (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT); ++ dload_buf->flag = cpu_to_le16(flag); ++ dload_buf->dload_type = cpu_to_le16(DL_TYPE_CLM); ++ dload_buf->len = cpu_to_le32(len); ++ dload_buf->crc = cpu_to_le32(0); ++ len = sizeof(*dload_buf) + len - 1; ++ ++ err = brcmf_fil_iovar_data_set(ifp, "clmload", dload_buf, len); ++ ++ return err; ++} ++ ++static int brcmf_c_get_clm_name(struct brcmf_if *ifp, u8 *clm_name) ++{ ++ struct brcmf_bus *bus = ifp->drvr->bus_if; ++ struct brcmf_rev_info *ri = &ifp->drvr->revinfo; ++ u8 fw_name[BRCMF_FW_NAME_LEN]; ++ u8 *ptr; ++ size_t len; ++ s32 err; ++ ++ memset(fw_name, 0, BRCMF_FW_NAME_LEN); ++ err = brcmf_bus_get_fwname(bus, ri->chipnum, ri->chiprev, fw_name); ++ if (err) { ++ brcmf_err("get firmware name failed (%d)\n", err); ++ goto done; ++ } ++ ++ /* generate CLM blob file name */ ++ ptr = strrchr(fw_name, '.'); ++ if (!ptr) { ++ err = -ENOENT; ++ goto done; ++ } ++ ++ len = ptr - fw_name + 1; ++ if (len + strlen(".clm_blob") > BRCMF_FW_NAME_LEN) { ++ err = -E2BIG; ++ } else { ++ strlcpy(clm_name, fw_name, len); ++ strlcat(clm_name, ".clm_blob", BRCMF_FW_NAME_LEN); ++ } ++done: ++ return err; ++} ++ ++static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) ++{ ++ struct device *dev = ifp->drvr->bus_if->dev; ++ struct brcmf_dload_data_le *chunk_buf; ++ const struct firmware *clm = NULL; ++ u8 clm_name[BRCMF_FW_NAME_LEN]; ++ u32 chunk_len; ++ u32 datalen; ++ u32 cumulative_len; ++ u16 dl_flag = DL_BEGIN; ++ u32 status; ++ s32 err; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ memset(clm_name, 0, BRCMF_FW_NAME_LEN); ++ err = brcmf_c_get_clm_name(ifp, clm_name); ++ if (err) { ++ brcmf_err("get CLM blob file name failed (%d)\n", err); ++ return err; ++ } ++ ++ err = request_firmware(&clm, clm_name, dev); ++ if (err) { ++ if (err == -ENOENT) { ++ brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n"); ++ return 0; ++ } ++ brcmf_err("request CLM blob file failed (%d)\n", err); ++ return err; ++ } ++ ++ chunk_buf = kzalloc(sizeof(*chunk_buf) + MAX_CHUNK_LEN - 1, GFP_KERNEL); ++ if (!chunk_buf) { ++ err = -ENOMEM; ++ goto done; ++ } ++ ++ datalen = clm->size; ++ cumulative_len = 0; ++ do { ++ if (datalen > MAX_CHUNK_LEN) { ++ chunk_len = MAX_CHUNK_LEN; ++ } else { ++ chunk_len = datalen; ++ dl_flag |= DL_END; ++ } ++ memcpy(chunk_buf->data, clm->data + cumulative_len, chunk_len); ++ ++ err = brcmf_c_download(ifp, dl_flag, chunk_buf, chunk_len); ++ ++ dl_flag &= ~DL_BEGIN; ++ ++ cumulative_len += chunk_len; ++ datalen -= chunk_len; ++ } while ((datalen > 0) && (err == 0)); ++ ++ if (err) { ++ brcmf_err("clmload (%zu byte file) failed (%d); ", ++ clm->size, err); ++ /* Retrieve clmload_status and print */ ++ err = brcmf_fil_iovar_int_get(ifp, "clmload_status", &status); ++ if (err) ++ brcmf_err("get clmload_status failed (%d)\n", err); ++ else ++ brcmf_dbg(INFO, "clmload_status=%d\n", status); ++ err = -EIO; ++ } ++ ++ kfree(chunk_buf); ++done: ++ release_firmware(clm); ++ return err; ++} ++ + int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) + { + s8 eventmask[BRCMF_EVENTING_MASK_LEN]; + u8 buf[BRCMF_DCMD_SMLEN]; + struct brcmf_rev_info_le revinfo; + struct brcmf_rev_info *ri; ++ char *clmver; + char *ptr; + s32 err; + +@@ -148,6 +278,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_i + } + ri->result = err; + ++ /* Do any CLM downloading */ ++ err = brcmf_c_process_clm_blob(ifp); ++ if (err < 0) { ++ brcmf_err("download CLM blob file failed, %d\n", err); ++ goto done; ++ } ++ + /* query for 'ver' to get version info from firmware */ + memset(buf, 0, sizeof(buf)); + strcpy(buf, "ver"); +@@ -167,6 +304,26 @@ int brcmf_c_preinit_dcmds(struct brcmf_i + ptr = strrchr(buf, ' ') + 1; + strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver)); + ++ /* Query for 'clmver' to get CLM version info from firmware */ ++ memset(buf, 0, sizeof(buf)); ++ err = brcmf_fil_iovar_data_get(ifp, "clmver", buf, sizeof(buf)); ++ if (err) { ++ brcmf_dbg(TRACE, "retrieving clmver failed, %d\n", err); ++ } else { ++ clmver = (char *)buf; ++ /* store CLM version for adding it to revinfo debugfs file */ ++ memcpy(ifp->drvr->clmver, clmver, sizeof(ifp->drvr->clmver)); ++ ++ /* Replace all newline/linefeed characters with space ++ * character ++ */ ++ ptr = clmver; ++ while ((ptr = strnchr(ptr, '\n', sizeof(buf))) != NULL) ++ *ptr = ' '; ++ ++ brcmf_dbg(INFO, "CLM version = %s\n", clmver); ++ } ++ + /* set mpc */ + err = brcmf_fil_iovar_int_set(ifp, "mpc", 1); + if (err) { +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +@@ -1009,6 +1009,8 @@ static int brcmf_revinfo_read(struct seq + seq_printf(s, "anarev: %u\n", ri->anarev); + seq_printf(s, "nvramrev: %08x\n", ri->nvramrev); + ++ seq_printf(s, "clmver: %s\n", bus_if->drvr->clmver); ++ + return 0; + } + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +@@ -141,6 +141,8 @@ struct brcmf_pub { + struct notifier_block inetaddr_notifier; + struct notifier_block inet6addr_notifier; + struct brcmf_mp_device *settings; ++ ++ u8 clmver[BRCMF_DCMD_SMLEN]; + }; + + /* forward declarations */ +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +@@ -155,6 +155,21 @@ + #define BRCMF_MFP_CAPABLE 1 + #define BRCMF_MFP_REQUIRED 2 + ++/* MAX_CHUNK_LEN is the maximum length for data passing to firmware in each ++ * ioctl. It is relatively small because firmware has small maximum size input ++ * playload restriction for ioctls. ++ */ ++#define MAX_CHUNK_LEN 1400 ++ ++#define DLOAD_HANDLER_VER 1 /* Downloader version */ ++#define DLOAD_FLAG_VER_MASK 0xf000 /* Downloader version mask */ ++#define DLOAD_FLAG_VER_SHIFT 12 /* Downloader version shift */ ++ ++#define DL_BEGIN 0x0002 ++#define DL_END 0x0004 ++ ++#define DL_TYPE_CLM 2 ++ + /* join preference types for join_pref iovar */ + enum brcmf_join_pref_types { + BRCMF_JOIN_PREF_RSSI = 1, +@@ -827,6 +842,22 @@ struct brcmf_pno_macaddr_le { + }; + + /** ++ * struct brcmf_dload_data_le - data passing to firmware for downloading ++ * @flag: flags related to download data. ++ * @dload_type: type of download data. ++ * @len: length in bytes of download data. ++ * @crc: crc of download data. ++ * @data: download data. ++ */ ++struct brcmf_dload_data_le { ++ __le16 flag; ++ __le16 dload_type; ++ __le32 len; ++ __le32 crc; ++ u8 data[1]; ++}; ++ ++/** + * struct brcmf_pno_bssid_le - bssid configuration for PNO scan. + * + * @bssid: BSS network identifier. +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -1350,6 +1350,24 @@ static int brcmf_pcie_get_memdump(struct + return 0; + } + ++static int brcmf_pcie_get_fwname(struct device *dev, u32 chip, u32 chiprev, ++ u8 *fw_name) ++{ ++ struct brcmf_bus *bus_if = dev_get_drvdata(dev); ++ struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie; ++ struct brcmf_pciedev_info *devinfo = buspub->devinfo; ++ int ret = 0; ++ ++ if (devinfo->fw_name[0] != '\0') ++ strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN); ++ else ++ ret = brcmf_fw_map_chip_to_name(chip, chiprev, ++ brcmf_pcie_fwnames, ++ ARRAY_SIZE(brcmf_pcie_fwnames), ++ fw_name, NULL); ++ ++ return ret; ++} + + static const struct brcmf_bus_ops brcmf_pcie_bus_ops = { + .txdata = brcmf_pcie_tx, +@@ -1359,6 +1377,7 @@ static const struct brcmf_bus_ops brcmf_ + .wowl_config = brcmf_pcie_wowl_config, + .get_ramsize = brcmf_pcie_get_ramsize, + .get_memdump = brcmf_pcie_get_memdump, ++ .get_fwname = brcmf_pcie_get_fwname, + }; + + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -3985,6 +3985,24 @@ brcmf_sdio_watchdog(unsigned long data) + } + } + ++static int brcmf_sdio_get_fwname(struct device *dev, u32 chip, u32 chiprev, ++ u8 *fw_name) ++{ ++ struct brcmf_bus *bus_if = dev_get_drvdata(dev); ++ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ int ret = 0; ++ ++ if (sdiodev->fw_name[0] != '\0') ++ strlcpy(fw_name, sdiodev->fw_name, BRCMF_FW_NAME_LEN); ++ else ++ ret = brcmf_fw_map_chip_to_name(chip, chiprev, ++ brcmf_sdio_fwnames, ++ ARRAY_SIZE(brcmf_sdio_fwnames), ++ fw_name, NULL); ++ ++ return ret; ++} ++ + static const struct brcmf_bus_ops brcmf_sdio_bus_ops = { + .stop = brcmf_sdio_bus_stop, + .preinit = brcmf_sdio_bus_preinit, +@@ -3995,6 +4013,7 @@ static const struct brcmf_bus_ops brcmf_ + .wowl_config = brcmf_sdio_wowl_config, + .get_ramsize = brcmf_sdio_bus_get_ramsize, + .get_memdump = brcmf_sdio_bus_get_memdump, ++ .get_fwname = brcmf_sdio_get_fwname, + }; + + static void brcmf_sdio_firmware_callback(struct device *dev, int err, +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +@@ -1128,12 +1128,30 @@ static void brcmf_usb_wowl_config(struct + device_set_wakeup_enable(devinfo->dev, false); + } + ++static int brcmf_usb_get_fwname(struct device *dev, u32 chip, u32 chiprev, ++ u8 *fw_name) ++{ ++ struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); ++ int ret = 0; ++ ++ if (devinfo->fw_name[0] != '\0') ++ strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN); ++ else ++ ret = brcmf_fw_map_chip_to_name(chip, chiprev, ++ brcmf_usb_fwnames, ++ ARRAY_SIZE(brcmf_usb_fwnames), ++ fw_name, NULL); ++ ++ return ret; ++} ++ + static const struct brcmf_bus_ops brcmf_usb_bus_ops = { + .txdata = brcmf_usb_tx, + .stop = brcmf_usb_down, + .txctl = brcmf_usb_tx_ctlpkt, + .rxctl = brcmf_usb_rx_ctlpkt, + .wowl_config = brcmf_usb_wowl_config, ++ .get_fwname = brcmf_usb_get_fwname, + }; + + static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo) diff --git a/package/kernel/mac80211/patches/305-v4.15-brcmfmac-change-driver-unbind-order-of-the-sdio-func.patch b/package/kernel/mac80211/patches/305-v4.15-brcmfmac-change-driver-unbind-order-of-the-sdio-func.patch new file mode 100644 index 0000000000..3649bdda49 --- /dev/null +++ b/package/kernel/mac80211/patches/305-v4.15-brcmfmac-change-driver-unbind-order-of-the-sdio-func.patch @@ -0,0 +1,37 @@ +From 5c3de777bdaf48bd0cfb43097c0d0fb85056cab7 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Sat, 25 Nov 2017 21:39:25 +0100 +Subject: [PATCH] brcmfmac: change driver unbind order of the sdio function + devices + +In the function brcmf_sdio_firmware_callback() the driver is +unbound from the sdio function devices in the error path. +However, the order in which it is done resulted in a use-after-free +issue (see brcmf_ops_sdio_remove() in bcmsdh.c). Hence change +the order and first unbind sdio function #2 device and then +unbind sdio function #1 device. + +Cc: stable@vger.kernel.org # v4.12.x +Fixes: 7a51461fc2da ("brcmfmac: unbind all devices upon failure in firmware callback") +Reported-by: Stefan Wahren +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -4121,8 +4121,8 @@ release: + sdio_release_host(sdiodev->func[1]); + fail: + brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err); +- device_release_driver(dev); + device_release_driver(&sdiodev->func[2]->dev); ++ device_release_driver(dev); + } + + struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) diff --git a/package/kernel/mac80211/patches/306-v4.15-brcmfmac-Avoid-build-error-with-make-W-1.patch b/package/kernel/mac80211/patches/306-v4.15-brcmfmac-Avoid-build-error-with-make-W-1.patch new file mode 100644 index 0000000000..7344580d34 --- /dev/null +++ b/package/kernel/mac80211/patches/306-v4.15-brcmfmac-Avoid-build-error-with-make-W-1.patch @@ -0,0 +1,33 @@ +From 51ef7925e10688c57186d438e784532e063492e4 Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Thu, 23 Nov 2017 17:57:04 +0200 +Subject: [PATCH] brcmfmac: Avoid build error with make W=1 + +When I run make W=1 on gcc (Debian 7.2.0-16) 7.2.0 I got an error for +the first run, all next ones are okay. + + CC [M] drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.o +drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c:2078: error: Cannot parse struct or union! +scripts/Makefile.build:310: recipe for target 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.o' failed + +Seems like something happened with W=1 and wrong kernel doc format. +As a quick fix remove dubious /** in the code. + +Signed-off-by: Andy Shevchenko +Acked-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -2070,7 +2070,7 @@ static int brcmf_sdio_txpkt_hdalign(stru + return head_pad; + } + +-/** ++/* + * struct brcmf_skbuff_cb reserves first two bytes in sk_buff::cb for + * bus layer usage. + */ diff --git a/package/kernel/mac80211/patches/307-v4.15-brcmfmac-fix-CLM-load-error-for-legacy-chips-when-us.patch b/package/kernel/mac80211/patches/307-v4.15-brcmfmac-fix-CLM-load-error-for-legacy-chips-when-us.patch new file mode 100644 index 0000000000..ead5e72145 --- /dev/null +++ b/package/kernel/mac80211/patches/307-v4.15-brcmfmac-fix-CLM-load-error-for-legacy-chips-when-us.patch @@ -0,0 +1,40 @@ +From cc124d5cc8d81985c3511892d7a6d546552ff754 Mon Sep 17 00:00:00 2001 +From: Wright Feng +Date: Tue, 16 Jan 2018 17:26:50 +0800 +Subject: [PATCH] brcmfmac: fix CLM load error for legacy chips when user + helper is enabled + +For legacy chips without CLM blob files, kernel with user helper function +returns -EAGAIN when we request_firmware(), and then driver got failed +when bringing up legacy chips. We expect the CLM blob file for legacy chip +is not existence in firmware path, but the -ENOENT error is transferred to +-EAGAIN in firmware_class.c with user helper. +Because of that, we continue with CLM data currently present in firmware +if getting error from doing request_firmware(). + +Cc: stable@vger.kernel.org # v4.15.y +Reviewed-by: Arend van Spriel +Signed-off-by: Wright Feng +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +@@ -182,12 +182,9 @@ static int brcmf_c_process_clm_blob(stru + + err = request_firmware(&clm, clm_name, dev); + if (err) { +- if (err == -ENOENT) { +- brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n"); +- return 0; +- } +- brcmf_err("request CLM blob file failed (%d)\n", err); +- return err; ++ brcmf_info("no clm_blob available(err=%d), device may have limited channels available\n", ++ err); ++ return 0; + } + + chunk_buf = kzalloc(sizeof(*chunk_buf) + MAX_CHUNK_LEN - 1, GFP_KERNEL); diff --git a/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch b/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch index 599269d9e4..0e98cb50c8 100644 --- a/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch +++ b/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch @@ -13,7 +13,7 @@ Signed-off-by: Rafał Miłecki --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -@@ -1236,6 +1236,7 @@ int __init brcmf_core_init(void) +@@ -1238,6 +1238,7 @@ int __init brcmf_core_init(void) { if (!schedule_work(&brcmf_driver_work)) return -EBUSY; diff --git a/package/kernel/mac80211/patches/864-brcmfmac-do-not-use-internal-roaming-engine-by-default.patch b/package/kernel/mac80211/patches/864-brcmfmac-do-not-use-internal-roaming-engine-by-default.patch index 891c539fbf..0ae012cbeb 100644 --- a/package/kernel/mac80211/patches/864-brcmfmac-do-not-use-internal-roaming-engine-by-default.patch +++ b/package/kernel/mac80211/patches/864-brcmfmac-do-not-use-internal-roaming-engine-by-default.patch @@ -9,7 +9,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c -@@ -69,7 +69,11 @@ static int brcmf_fcmode; +@@ -71,7 +71,11 @@ static int brcmf_fcmode; module_param_named(fcmode, brcmf_fcmode, int, 0); MODULE_PARM_DESC(fcmode, "Mode of firmware signalled flow control"); -- 2.30.2