diff options
Diffstat (limited to 'package/kernel/mac80211/patches/304-v4.15-brcmfmac-add-CLM-download-support.patch')
-rw-r--r-- | package/kernel/mac80211/patches/304-v4.15-brcmfmac-add-CLM-download-support.patch | 434 |
1 files changed, 0 insertions, 434 deletions
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 deleted file mode 100644 index 2cd5f73126..0000000000 --- a/package/kernel/mac80211/patches/304-v4.15-brcmfmac-add-CLM-download-support.patch +++ /dev/null @@ -1,434 +0,0 @@ -From fdd0bd88ceaecf729db103ac8836af5805dd2dc1 Mon Sep 17 00:00:00 2001 -From: Chung-Hsien Hsu <stanley.hsu@cypress.com> -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 <arend.vanspriel@broadcom.com> -Signed-off-by: Chung-Hsien Hsu <stanley.hsu@cypress.com> -Signed-off-by: Kalle Valo <kvalo@codeaurora.org> ---- - .../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 <linux/string.h> - #include <linux/netdevice.h> - #include <linux/module.h> -+#include <linux/firmware.h> - #include <brcmu_wifi.h> - #include <brcmu_utils.h> - #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) |