brcmfmac: add CLM download support
PATCH v3 1/1 brcmfmac: add CLM download support
From: Chung-Hsien Hsu <[email protected]>
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.
Signed-off-by Chung-Hsien Hsu <[email protected]>
---
v2: Revise commit message to describe in more detail
v3: Add error handling in brcmf_c_get_clm_name function
--- .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 10 ++ .../wireless/broadcom/brcm80211/brcmfmac/common.c | 161 +++++++++++++++++++++ .../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, 262 insertions(+)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +10 -0
@@ -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); };
@@ -214,6 +217,13 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len)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 */
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +161 -0
197 lines not on this page · raw message
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +2 -0
@@ -941,6 +941,8 @@ static int brcmf_revinfo_read(struct seq_file *s, void *data)seq_printf (s,"anarev: %u\n" , ri->anarev);seq_printf (s,"nvramrev: %08x\n" , ri->nvramrev); +seq_printf (s,"clmrev: %s\n" , bus_if->drvr->clmver); +return 0 ; }
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +2 -0
@@ -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 */
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +31 -0
@@ -147,6 +147,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 ,
@@ -835,4 +850,20 @@ struct brcmf_gtk_keyinfo_le { u8 replay_counter[BRCMF_RSN_REPLAY_LEN]; }; +/** +* 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 ]; +}; +#endif /* FWIL_TYPES_H_ */
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +19 -0
@@ -1350,6 +1350,24 @@ static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len)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 int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len) .wowl_config = brcmf_pcie_wowl_config, .get_ramsize = brcmf_pcie_get_ramsize, .get_memdump = brcmf_pcie_get_memdump, + .get_fwname = brcmf_pcie_get_fwname, };
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +19 -0
@@ -3972,6 +3972,24 @@ static void brcmf_sdio_buscore_write32(void *ctx, u32 addr, u32 val) } } +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,
@@ -3982,6 +4000,7 @@ static void brcmf_sdio_buscore_write32(void *ctx, u32 addr, u32 val) .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,
drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +18 -0
@@ -1128,12 +1128,30 @@ static void brcmf_usb_wowl_config(struct device *dev, bool enabled)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)
Signature · 1 line
1.9.1