brcmfmac: add CLM download support
PATCH v4 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.
---
v2: Revise commit message to describe in more detail
v3: Add error handling in brcmf_c_get_clm_name function
v4: Correct the length of dload_buf in brcmf_c_download 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
Arend van Spriel
maintainerQuoted 28 lines · Wright Feng
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 inbrcmf_c_get_clm_namefunction
v4: Correct the length ofdload_bufinbrcmf_c_downloadfunction--- .../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(+)
[...]
Quoted 4 lines
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +0
-0
[...]
Quoted 7 lines
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +3
-0@@ -104,12 +106,139 @@ void brcmf_c_set_joinpref_default(struct brcmf_if *ifp)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)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) · line 121
Quoted 10 lines
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +10
-0+{ +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 ; + len = len +8 - (len %8 );
In case len is 8 this will result in 16. So better use roundup() macro from include/linux/kernel.h [1]. However, this means brcmf_fil_iovar_data_set() will read after the allocated buffer space.
By the way, where does the alignment requirement come from?
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) · line 123
Quoted 2 lines
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +2
-0+ + err =brcmf_fil_iovar_data_set (ifp,"clmload" , (void *)dload_buf, len);
The cast is not necessary so please remove.
Regards,
Arend
[1] http://elixir.free-electrons.com/linux/latest/source/include/linux/kernel.h#L90
Quoted 62 lines · Arend van Spriel
Quoted 28 lines · Wright Feng
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 inbrcmf_c_get_clm_namefunction
v4: Correct the length ofdload_bufinbrcmf_c_downloadfunction--- .../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(+)[...]
Quoted 4 lines
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +0
-0[...]
Quoted 7 lines
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +3
-0@@ -104,12 +106,139 @@ void brcmf_c_set_joinpref_default(struct brcmf_if *ifp)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)drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) · line 121
Quoted 10 lines
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +10
-0+{ +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 ; + len = len +8 - (len %8 );In case len is 8 this will result in 16. So better use
roundup()macro frominclude/linux/kernel.h[1]. However, this meansbrcmf_fil_iovar_data_set()will read after the allocated buffer space.
Quoted 2 lines
By the way, where does the alignment requirement come from?
Thanks for pointing this out. I've tried the download process without this alignment. There's no error/failure showed up. Looks like the alignment is not necessary here so I will remove it.
Quoted 4 lines
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) · line 123
Quoted 2 lines
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +2
-0+ + err =brcmf_fil_iovar_data_set (ifp,"clmload" , (void *)dload_buf, len);The cast is not necessary so please remove.
Will do it.
Regards,
Chung-Hsien
Quoted 5 lines
Regards,
Arend[1] http://elixir.free-electrons.com/linux/latest/source/include/linux/kernel.h#L90
Quoted 9 lines · Wright Feng
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.
Not to bikeshed this, but why not just ".clm"? ".clm_blob" seems unnecessary and could feel "unprofessional" to users.
To me simple seems better.
- Steve
Arend van Spriel
maintainerQuoted 11 lines · Steve deRosier
Quoted 9 lines · Wright Feng
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.
Quoted 4 lines
Not to bikeshed this, but why not just ".clm"? ".clm_blob" seems unnecessary and could feel "unprofessional" to users.
To me simple seems better.
Hi Steve,
Glad you ask ;-) It was one of my comments pre-reviewing this "internally"*. The problem with calling it .clm is that it means something else within Broadcom and Cypress for that matter. The .clm_blob is the output of tool compiling the regulatory data according an input specification which uses the .clm extension. It is similar to regdb.txt and regulatory.bin.
Regards,
Arend
* internally does not quite cover Cypress+Broadcom collaboration.