diff options
author | Chung-Hsien Hsu <stanley.hsu@cypress.com> | 2017-11-10 04:27:15 -0500 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2017-11-10 20:04:09 -0500 |
commit | fdd0bd88ceaecf729db103ac8836af5805dd2dc1 (patch) | |
tree | 83676889c062a8f8a96329758dd61d47ba9a8648 | |
parent | 4775ae7afec62e6ae1bc1f99ab57db2a36b8807e (diff) |
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>
8 files changed, 258 insertions, 0 deletions
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index 163ddc49f951..0b76a615708e 100644 --- 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 { | |||
71 | * @wowl_config: specify if dongle is configured for wowl when going to suspend | 71 | * @wowl_config: specify if dongle is configured for wowl when going to suspend |
72 | * @get_ramsize: obtain size of device memory. | 72 | * @get_ramsize: obtain size of device memory. |
73 | * @get_memdump: obtain device memory dump in provided buffer. | 73 | * @get_memdump: obtain device memory dump in provided buffer. |
74 | * @get_fwname: obtain firmware name. | ||
74 | * | 75 | * |
75 | * This structure provides an abstract interface towards the | 76 | * This structure provides an abstract interface towards the |
76 | * bus specific driver. For control messages to common driver | 77 | * bus specific driver. For control messages to common driver |
@@ -87,6 +88,8 @@ struct brcmf_bus_ops { | |||
87 | void (*wowl_config)(struct device *dev, bool enabled); | 88 | void (*wowl_config)(struct device *dev, bool enabled); |
88 | size_t (*get_ramsize)(struct device *dev); | 89 | size_t (*get_ramsize)(struct device *dev); |
89 | int (*get_memdump)(struct device *dev, void *data, size_t len); | 90 | int (*get_memdump)(struct device *dev, void *data, size_t len); |
91 | int (*get_fwname)(struct device *dev, uint chip, uint chiprev, | ||
92 | unsigned char *fw_name); | ||
90 | }; | 93 | }; |
91 | 94 | ||
92 | 95 | ||
@@ -224,6 +227,13 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len) | |||
224 | return bus->ops->get_memdump(bus->dev, data, len); | 227 | return bus->ops->get_memdump(bus->dev, data, len); |
225 | } | 228 | } |
226 | 229 | ||
230 | static inline | ||
231 | int brcmf_bus_get_fwname(struct brcmf_bus *bus, uint chip, uint chiprev, | ||
232 | unsigned char *fw_name) | ||
233 | { | ||
234 | return bus->ops->get_fwname(bus->dev, chip, chiprev, fw_name); | ||
235 | } | ||
236 | |||
227 | /* | 237 | /* |
228 | * interface functions from common layer | 238 | * interface functions from common layer |
229 | */ | 239 | */ |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 7a2b49587b4d..6a59d0609d30 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/string.h> | 18 | #include <linux/string.h> |
19 | #include <linux/netdevice.h> | 19 | #include <linux/netdevice.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/firmware.h> | ||
21 | #include <brcmu_wifi.h> | 22 | #include <brcmu_wifi.h> |
22 | #include <brcmu_utils.h> | 23 | #include <brcmu_utils.h> |
23 | #include "core.h" | 24 | #include "core.h" |
@@ -28,6 +29,7 @@ | |||
28 | #include "tracepoint.h" | 29 | #include "tracepoint.h" |
29 | #include "common.h" | 30 | #include "common.h" |
30 | #include "of.h" | 31 | #include "of.h" |
32 | #include "firmware.h" | ||
31 | 33 | ||
32 | MODULE_AUTHOR("Broadcom Corporation"); | 34 | MODULE_AUTHOR("Broadcom Corporation"); |
33 | MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); | 35 | MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); |
@@ -104,12 +106,140 @@ void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) | |||
104 | brcmf_err("Set join_pref error (%d)\n", err); | 106 | brcmf_err("Set join_pref error (%d)\n", err); |
105 | } | 107 | } |
106 | 108 | ||
109 | static int brcmf_c_download(struct brcmf_if *ifp, u16 flag, | ||
110 | struct brcmf_dload_data_le *dload_buf, | ||
111 | u32 len) | ||
112 | { | ||
113 | s32 err; | ||
114 | |||
115 | flag |= (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT); | ||
116 | dload_buf->flag = cpu_to_le16(flag); | ||
117 | dload_buf->dload_type = cpu_to_le16(DL_TYPE_CLM); | ||
118 | dload_buf->len = cpu_to_le32(len); | ||
119 | dload_buf->crc = cpu_to_le32(0); | ||
120 | len = sizeof(*dload_buf) + len - 1; | ||
121 | |||
122 | err = brcmf_fil_iovar_data_set(ifp, "clmload", dload_buf, len); | ||
123 | |||
124 | return err; | ||
125 | } | ||
126 | |||
127 | static int brcmf_c_get_clm_name(struct brcmf_if *ifp, u8 *clm_name) | ||
128 | { | ||
129 | struct brcmf_bus *bus = ifp->drvr->bus_if; | ||
130 | struct brcmf_rev_info *ri = &ifp->drvr->revinfo; | ||
131 | u8 fw_name[BRCMF_FW_NAME_LEN]; | ||
132 | u8 *ptr; | ||
133 | size_t len; | ||
134 | s32 err; | ||
135 | |||
136 | memset(fw_name, 0, BRCMF_FW_NAME_LEN); | ||
137 | err = brcmf_bus_get_fwname(bus, ri->chipnum, ri->chiprev, fw_name); | ||
138 | if (err) { | ||
139 | brcmf_err("get firmware name failed (%d)\n", err); | ||
140 | goto done; | ||
141 | } | ||
142 | |||
143 | /* generate CLM blob file name */ | ||
144 | ptr = strrchr(fw_name, '.'); | ||
145 | if (!ptr) { | ||
146 | err = -ENOENT; | ||
147 | goto done; | ||
148 | } | ||
149 | |||
150 | len = ptr - fw_name + 1; | ||
151 | if (len + strlen(".clm_blob") > BRCMF_FW_NAME_LEN) { | ||
152 | err = -E2BIG; | ||
153 | } else { | ||
154 | strlcpy(clm_name, fw_name, len); | ||
155 | strlcat(clm_name, ".clm_blob", BRCMF_FW_NAME_LEN); | ||
156 | } | ||
157 | done: | ||
158 | return err; | ||
159 | } | ||
160 | |||
161 | static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) | ||
162 | { | ||
163 | struct device *dev = ifp->drvr->bus_if->dev; | ||
164 | struct brcmf_dload_data_le *chunk_buf; | ||
165 | const struct firmware *clm = NULL; | ||
166 | u8 clm_name[BRCMF_FW_NAME_LEN]; | ||
167 | u32 chunk_len; | ||
168 | u32 datalen; | ||
169 | u32 cumulative_len; | ||
170 | u16 dl_flag = DL_BEGIN; | ||
171 | u32 status; | ||
172 | s32 err; | ||
173 | |||
174 | brcmf_dbg(TRACE, "Enter\n"); | ||
175 | |||
176 | memset(clm_name, 0, BRCMF_FW_NAME_LEN); | ||
177 | err = brcmf_c_get_clm_name(ifp, clm_name); | ||
178 | if (err) { | ||
179 | brcmf_err("get CLM blob file name failed (%d)\n", err); | ||
180 | return err; | ||
181 | } | ||
182 | |||
183 | err = request_firmware(&clm, clm_name, dev); | ||
184 | if (err) { | ||
185 | if (err == -ENOENT) { | ||
186 | brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n"); | ||
187 | return 0; | ||
188 | } | ||
189 | brcmf_err("request CLM blob file failed (%d)\n", err); | ||
190 | return err; | ||
191 | } | ||
192 | |||
193 | chunk_buf = kzalloc(sizeof(*chunk_buf) + MAX_CHUNK_LEN - 1, GFP_KERNEL); | ||
194 | if (!chunk_buf) { | ||
195 | err = -ENOMEM; | ||
196 | goto done; | ||
197 | } | ||
198 | |||
199 | datalen = clm->size; | ||
200 | cumulative_len = 0; | ||
201 | do { | ||
202 | if (datalen > MAX_CHUNK_LEN) { | ||
203 | chunk_len = MAX_CHUNK_LEN; | ||
204 | } else { | ||
205 | chunk_len = datalen; | ||
206 | dl_flag |= DL_END; | ||
207 | } | ||
208 | memcpy(chunk_buf->data, clm->data + cumulative_len, chunk_len); | ||
209 | |||
210 | err = brcmf_c_download(ifp, dl_flag, chunk_buf, chunk_len); | ||
211 | |||
212 | dl_flag &= ~DL_BEGIN; | ||
213 | |||
214 | cumulative_len += chunk_len; | ||
215 | datalen -= chunk_len; | ||
216 | } while ((datalen > 0) && (err == 0)); | ||
217 | |||
218 | if (err) { | ||
219 | brcmf_err("clmload (%zu byte file) failed (%d); ", | ||
220 | clm->size, err); | ||
221 | /* Retrieve clmload_status and print */ | ||
222 | err = brcmf_fil_iovar_int_get(ifp, "clmload_status", &status); | ||
223 | if (err) | ||
224 | brcmf_err("get clmload_status failed (%d)\n", err); | ||
225 | else | ||
226 | brcmf_dbg(INFO, "clmload_status=%d\n", status); | ||
227 | err = -EIO; | ||
228 | } | ||
229 | |||
230 | kfree(chunk_buf); | ||
231 | done: | ||
232 | release_firmware(clm); | ||
233 | return err; | ||
234 | } | ||
235 | |||
107 | int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | 236 | int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) |
108 | { | 237 | { |
109 | s8 eventmask[BRCMF_EVENTING_MASK_LEN]; | 238 | s8 eventmask[BRCMF_EVENTING_MASK_LEN]; |
110 | u8 buf[BRCMF_DCMD_SMLEN]; | 239 | u8 buf[BRCMF_DCMD_SMLEN]; |
111 | struct brcmf_rev_info_le revinfo; | 240 | struct brcmf_rev_info_le revinfo; |
112 | struct brcmf_rev_info *ri; | 241 | struct brcmf_rev_info *ri; |
242 | char *clmver; | ||
113 | char *ptr; | 243 | char *ptr; |
114 | s32 err; | 244 | s32 err; |
115 | 245 | ||
@@ -148,6 +278,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | |||
148 | } | 278 | } |
149 | ri->result = err; | 279 | ri->result = err; |
150 | 280 | ||
281 | /* Do any CLM downloading */ | ||
282 | err = brcmf_c_process_clm_blob(ifp); | ||
283 | if (err < 0) { | ||
284 | brcmf_err("download CLM blob file failed, %d\n", err); | ||
285 | goto done; | ||
286 | } | ||
287 | |||
151 | /* query for 'ver' to get version info from firmware */ | 288 | /* query for 'ver' to get version info from firmware */ |
152 | memset(buf, 0, sizeof(buf)); | 289 | memset(buf, 0, sizeof(buf)); |
153 | strcpy(buf, "ver"); | 290 | strcpy(buf, "ver"); |
@@ -167,6 +304,26 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | |||
167 | ptr = strrchr(buf, ' ') + 1; | 304 | ptr = strrchr(buf, ' ') + 1; |
168 | strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver)); | 305 | strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver)); |
169 | 306 | ||
307 | /* Query for 'clmver' to get CLM version info from firmware */ | ||
308 | memset(buf, 0, sizeof(buf)); | ||
309 | err = brcmf_fil_iovar_data_get(ifp, "clmver", buf, sizeof(buf)); | ||
310 | if (err) { | ||
311 | brcmf_dbg(TRACE, "retrieving clmver failed, %d\n", err); | ||
312 | } else { | ||
313 | clmver = (char *)buf; | ||
314 | /* store CLM version for adding it to revinfo debugfs file */ | ||
315 | memcpy(ifp->drvr->clmver, clmver, sizeof(ifp->drvr->clmver)); | ||
316 | |||
317 | /* Replace all newline/linefeed characters with space | ||
318 | * character | ||
319 | */ | ||
320 | ptr = clmver; | ||
321 | while ((ptr = strnchr(ptr, '\n', sizeof(buf))) != NULL) | ||
322 | *ptr = ' '; | ||
323 | |||
324 | brcmf_dbg(INFO, "CLM version = %s\n", clmver); | ||
325 | } | ||
326 | |||
170 | /* set mpc */ | 327 | /* set mpc */ |
171 | err = brcmf_fil_iovar_int_set(ifp, "mpc", 1); | 328 | err = brcmf_fil_iovar_int_set(ifp, "mpc", 1); |
172 | if (err) { | 329 | if (err) { |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 9c7536daf8f7..930e423f83a8 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | |||
@@ -988,6 +988,8 @@ static int brcmf_revinfo_read(struct seq_file *s, void *data) | |||
988 | seq_printf(s, "anarev: %u\n", ri->anarev); | 988 | seq_printf(s, "anarev: %u\n", ri->anarev); |
989 | seq_printf(s, "nvramrev: %08x\n", ri->nvramrev); | 989 | seq_printf(s, "nvramrev: %08x\n", ri->nvramrev); |
990 | 990 | ||
991 | seq_printf(s, "clmver: %s\n", bus_if->drvr->clmver); | ||
992 | |||
991 | return 0; | 993 | return 0; |
992 | } | 994 | } |
993 | 995 | ||
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index 17085712bae2..df8a1ecb9924 100644 --- 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 { | |||
141 | struct notifier_block inetaddr_notifier; | 141 | struct notifier_block inetaddr_notifier; |
142 | struct notifier_block inet6addr_notifier; | 142 | struct notifier_block inet6addr_notifier; |
143 | struct brcmf_mp_device *settings; | 143 | struct brcmf_mp_device *settings; |
144 | |||
145 | u8 clmver[BRCMF_DCMD_SMLEN]; | ||
144 | }; | 146 | }; |
145 | 147 | ||
146 | /* forward declarations */ | 148 | /* forward declarations */ |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h index e0d22fedb2b4..4b290705e3e6 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h | |||
@@ -155,6 +155,21 @@ | |||
155 | #define BRCMF_MFP_CAPABLE 1 | 155 | #define BRCMF_MFP_CAPABLE 1 |
156 | #define BRCMF_MFP_REQUIRED 2 | 156 | #define BRCMF_MFP_REQUIRED 2 |
157 | 157 | ||
158 | /* MAX_CHUNK_LEN is the maximum length for data passing to firmware in each | ||
159 | * ioctl. It is relatively small because firmware has small maximum size input | ||
160 | * playload restriction for ioctls. | ||
161 | */ | ||
162 | #define MAX_CHUNK_LEN 1400 | ||
163 | |||
164 | #define DLOAD_HANDLER_VER 1 /* Downloader version */ | ||
165 | #define DLOAD_FLAG_VER_MASK 0xf000 /* Downloader version mask */ | ||
166 | #define DLOAD_FLAG_VER_SHIFT 12 /* Downloader version shift */ | ||
167 | |||
168 | #define DL_BEGIN 0x0002 | ||
169 | #define DL_END 0x0004 | ||
170 | |||
171 | #define DL_TYPE_CLM 2 | ||
172 | |||
158 | /* join preference types for join_pref iovar */ | 173 | /* join preference types for join_pref iovar */ |
159 | enum brcmf_join_pref_types { | 174 | enum brcmf_join_pref_types { |
160 | BRCMF_JOIN_PREF_RSSI = 1, | 175 | BRCMF_JOIN_PREF_RSSI = 1, |
@@ -827,6 +842,22 @@ struct brcmf_pno_macaddr_le { | |||
827 | }; | 842 | }; |
828 | 843 | ||
829 | /** | 844 | /** |
845 | * struct brcmf_dload_data_le - data passing to firmware for downloading | ||
846 | * @flag: flags related to download data. | ||
847 | * @dload_type: type of download data. | ||
848 | * @len: length in bytes of download data. | ||
849 | * @crc: crc of download data. | ||
850 | * @data: download data. | ||
851 | */ | ||
852 | struct brcmf_dload_data_le { | ||
853 | __le16 flag; | ||
854 | __le16 dload_type; | ||
855 | __le32 len; | ||
856 | __le32 crc; | ||
857 | u8 data[1]; | ||
858 | }; | ||
859 | |||
860 | /** | ||
830 | * struct brcmf_pno_bssid_le - bssid configuration for PNO scan. | 861 | * struct brcmf_pno_bssid_le - bssid configuration for PNO scan. |
831 | * | 862 | * |
832 | * @bssid: BSS network identifier. | 863 | * @bssid: BSS network identifier. |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index e6e9b00b79d7..3c87157f5b85 100644 --- 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 device *dev, void *data, size_t len) | |||
1350 | return 0; | 1350 | return 0; |
1351 | } | 1351 | } |
1352 | 1352 | ||
1353 | static int brcmf_pcie_get_fwname(struct device *dev, u32 chip, u32 chiprev, | ||
1354 | u8 *fw_name) | ||
1355 | { | ||
1356 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
1357 | struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie; | ||
1358 | struct brcmf_pciedev_info *devinfo = buspub->devinfo; | ||
1359 | int ret = 0; | ||
1360 | |||
1361 | if (devinfo->fw_name[0] != '\0') | ||
1362 | strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN); | ||
1363 | else | ||
1364 | ret = brcmf_fw_map_chip_to_name(chip, chiprev, | ||
1365 | brcmf_pcie_fwnames, | ||
1366 | ARRAY_SIZE(brcmf_pcie_fwnames), | ||
1367 | fw_name, NULL); | ||
1368 | |||
1369 | return ret; | ||
1370 | } | ||
1353 | 1371 | ||
1354 | static const struct brcmf_bus_ops brcmf_pcie_bus_ops = { | 1372 | static const struct brcmf_bus_ops brcmf_pcie_bus_ops = { |
1355 | .txdata = brcmf_pcie_tx, | 1373 | .txdata = brcmf_pcie_tx, |
@@ -1359,6 +1377,7 @@ static const struct brcmf_bus_ops brcmf_pcie_bus_ops = { | |||
1359 | .wowl_config = brcmf_pcie_wowl_config, | 1377 | .wowl_config = brcmf_pcie_wowl_config, |
1360 | .get_ramsize = brcmf_pcie_get_ramsize, | 1378 | .get_ramsize = brcmf_pcie_get_ramsize, |
1361 | .get_memdump = brcmf_pcie_get_memdump, | 1379 | .get_memdump = brcmf_pcie_get_memdump, |
1380 | .get_fwname = brcmf_pcie_get_fwname, | ||
1362 | }; | 1381 | }; |
1363 | 1382 | ||
1364 | 1383 | ||
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 00de73d9e152..b2256aa76eb6 100644 --- 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) | |||
3985 | } | 3985 | } |
3986 | } | 3986 | } |
3987 | 3987 | ||
3988 | static int brcmf_sdio_get_fwname(struct device *dev, u32 chip, u32 chiprev, | ||
3989 | u8 *fw_name) | ||
3990 | { | ||
3991 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
3992 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | ||
3993 | int ret = 0; | ||
3994 | |||
3995 | if (sdiodev->fw_name[0] != '\0') | ||
3996 | strlcpy(fw_name, sdiodev->fw_name, BRCMF_FW_NAME_LEN); | ||
3997 | else | ||
3998 | ret = brcmf_fw_map_chip_to_name(chip, chiprev, | ||
3999 | brcmf_sdio_fwnames, | ||
4000 | ARRAY_SIZE(brcmf_sdio_fwnames), | ||
4001 | fw_name, NULL); | ||
4002 | |||
4003 | return ret; | ||
4004 | } | ||
4005 | |||
3988 | static const struct brcmf_bus_ops brcmf_sdio_bus_ops = { | 4006 | static const struct brcmf_bus_ops brcmf_sdio_bus_ops = { |
3989 | .stop = brcmf_sdio_bus_stop, | 4007 | .stop = brcmf_sdio_bus_stop, |
3990 | .preinit = brcmf_sdio_bus_preinit, | 4008 | .preinit = brcmf_sdio_bus_preinit, |
@@ -3995,6 +4013,7 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = { | |||
3995 | .wowl_config = brcmf_sdio_wowl_config, | 4013 | .wowl_config = brcmf_sdio_wowl_config, |
3996 | .get_ramsize = brcmf_sdio_bus_get_ramsize, | 4014 | .get_ramsize = brcmf_sdio_bus_get_ramsize, |
3997 | .get_memdump = brcmf_sdio_bus_get_memdump, | 4015 | .get_memdump = brcmf_sdio_bus_get_memdump, |
4016 | .get_fwname = brcmf_sdio_get_fwname, | ||
3998 | }; | 4017 | }; |
3999 | 4018 | ||
4000 | static void brcmf_sdio_firmware_callback(struct device *dev, int err, | 4019 | static void brcmf_sdio_firmware_callback(struct device *dev, int err, |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index 11ffaa01599e..b27170c12482 100644 --- 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 *dev, bool enabled) | |||
1128 | device_set_wakeup_enable(devinfo->dev, false); | 1128 | device_set_wakeup_enable(devinfo->dev, false); |
1129 | } | 1129 | } |
1130 | 1130 | ||
1131 | static int brcmf_usb_get_fwname(struct device *dev, u32 chip, u32 chiprev, | ||
1132 | u8 *fw_name) | ||
1133 | { | ||
1134 | struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); | ||
1135 | int ret = 0; | ||
1136 | |||
1137 | if (devinfo->fw_name[0] != '\0') | ||
1138 | strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN); | ||
1139 | else | ||
1140 | ret = brcmf_fw_map_chip_to_name(chip, chiprev, | ||
1141 | brcmf_usb_fwnames, | ||
1142 | ARRAY_SIZE(brcmf_usb_fwnames), | ||
1143 | fw_name, NULL); | ||
1144 | |||
1145 | return ret; | ||
1146 | } | ||
1147 | |||
1131 | static const struct brcmf_bus_ops brcmf_usb_bus_ops = { | 1148 | static const struct brcmf_bus_ops brcmf_usb_bus_ops = { |
1132 | .txdata = brcmf_usb_tx, | 1149 | .txdata = brcmf_usb_tx, |
1133 | .stop = brcmf_usb_down, | 1150 | .stop = brcmf_usb_down, |
1134 | .txctl = brcmf_usb_tx_ctlpkt, | 1151 | .txctl = brcmf_usb_tx_ctlpkt, |
1135 | .rxctl = brcmf_usb_rx_ctlpkt, | 1152 | .rxctl = brcmf_usb_rx_ctlpkt, |
1136 | .wowl_config = brcmf_usb_wowl_config, | 1153 | .wowl_config = brcmf_usb_wowl_config, |
1154 | .get_fwname = brcmf_usb_get_fwname, | ||
1137 | }; | 1155 | }; |
1138 | 1156 | ||
1139 | static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo) | 1157 | static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo) |