Skip to content

Commit c9a300b

Browse files
committed
brcmfmac: common: Add support for downloading TxCap blobs
The TxCap blobs are additional data blobs used on Apple devices, and are uploaded analogously to CLM blobs. Add core support for doing this. Acked-by: Linus Walleij <[email protected]> Signed-off-by: Hector Martin <[email protected]>
1 parent c8a97ff commit c9a300b

2 files changed

Lines changed: 70 additions & 24 deletions

File tree

drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ enum brcmf_bus_protocol_type {
5555
/* Firmware blobs that may be available */
5656
enum brcmf_blob_type {
5757
BRCMF_BLOB_CLM,
58+
BRCMF_BLOB_TXCAP,
5859
};
5960

6061
struct brcmf_mp_device;

drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ void brcmf_c_set_joinpref_default(struct brcmf_if *ifp)
101101

102102
static int brcmf_c_download(struct brcmf_if *ifp, u16 flag,
103103
struct brcmf_dload_data_le *dload_buf,
104-
u32 len)
104+
u32 len, const char *var)
105105
{
106106
s32 err;
107107

@@ -111,18 +111,18 @@ static int brcmf_c_download(struct brcmf_if *ifp, u16 flag,
111111
dload_buf->len = cpu_to_le32(len);
112112
dload_buf->crc = cpu_to_le32(0);
113113

114-
err = brcmf_fil_iovar_data_set(ifp, "clmload", dload_buf,
114+
err = brcmf_fil_iovar_data_set(ifp, var, dload_buf,
115115
struct_size(dload_buf, data, len));
116116

117117
return err;
118118
}
119119

120-
static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
120+
static int brcmf_c_download_blob(struct brcmf_if *ifp,
121+
const void *data, size_t size,
122+
const char *loadvar, const char *statvar)
121123
{
122124
struct brcmf_pub *drvr = ifp->drvr;
123-
struct brcmf_bus *bus = drvr->bus_if;
124125
struct brcmf_dload_data_le *chunk_buf;
125-
const struct firmware *clm = NULL;
126126
u32 chunk_len;
127127
u32 datalen;
128128
u32 cumulative_len;
@@ -132,21 +132,14 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
132132

133133
brcmf_dbg(TRACE, "Enter\n");
134134

135-
err = brcmf_bus_get_blob(bus, &clm, BRCMF_BLOB_CLM);
136-
if (err || !clm) {
137-
brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",
138-
err);
139-
return 0;
140-
}
141-
142135
chunk_buf = kzalloc(struct_size(chunk_buf, data, MAX_CHUNK_LEN),
143136
GFP_KERNEL);
144137
if (!chunk_buf) {
145138
err = -ENOMEM;
146-
goto done;
139+
return -ENOMEM;
147140
}
148141

149-
datalen = clm->size;
142+
datalen = size;
150143
cumulative_len = 0;
151144
do {
152145
if (datalen > MAX_CHUNK_LEN) {
@@ -155,9 +148,10 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
155148
chunk_len = datalen;
156149
dl_flag |= DL_END;
157150
}
158-
memcpy(chunk_buf->data, clm->data + cumulative_len, chunk_len);
151+
memcpy(chunk_buf->data, data + cumulative_len, chunk_len);
159152

160-
err = brcmf_c_download(ifp, dl_flag, chunk_buf, chunk_len);
153+
err = brcmf_c_download(ifp, dl_flag, chunk_buf, chunk_len,
154+
loadvar);
161155

162156
dl_flag &= ~DL_BEGIN;
163157

@@ -166,20 +160,64 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
166160
} while ((datalen > 0) && (err == 0));
167161

168162
if (err) {
169-
bphy_err(drvr, "clmload (%zu byte file) failed (%d)\n",
170-
clm->size, err);
171-
/* Retrieve clmload_status and print */
172-
err = brcmf_fil_iovar_int_get(ifp, "clmload_status", &status);
163+
bphy_err(drvr, "%s (%zu byte file) failed (%d)\n",
164+
loadvar, size, err);
165+
/* Retrieve status and print */
166+
err = brcmf_fil_iovar_int_get(ifp, statvar, &status);
173167
if (err)
174-
bphy_err(drvr, "get clmload_status failed (%d)\n", err);
168+
bphy_err(drvr, "get %s failed (%d)\n", statvar, err);
175169
else
176-
brcmf_dbg(INFO, "clmload_status=%d\n", status);
170+
brcmf_dbg(INFO, "%s=%d\n", statvar, status);
177171
err = -EIO;
178172
}
179173

180174
kfree(chunk_buf);
181-
done:
182-
release_firmware(clm);
175+
return err;
176+
}
177+
178+
static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
179+
{
180+
struct brcmf_pub *drvr = ifp->drvr;
181+
struct brcmf_bus *bus = drvr->bus_if;
182+
const struct firmware *fw = NULL;
183+
s32 err;
184+
185+
brcmf_dbg(TRACE, "Enter\n");
186+
187+
err = brcmf_bus_get_blob(bus, &fw, BRCMF_BLOB_CLM);
188+
if (err || !fw) {
189+
brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",
190+
err);
191+
return 0;
192+
}
193+
194+
err = brcmf_c_download_blob(ifp, fw->data, fw->size,
195+
"clmload", "clmload_status");
196+
197+
release_firmware(fw);
198+
return err;
199+
}
200+
201+
static int brcmf_c_process_txcap_blob(struct brcmf_if *ifp)
202+
{
203+
struct brcmf_pub *drvr = ifp->drvr;
204+
struct brcmf_bus *bus = drvr->bus_if;
205+
const struct firmware *fw = NULL;
206+
s32 err;
207+
208+
brcmf_dbg(TRACE, "Enter\n");
209+
210+
err = brcmf_bus_get_blob(bus, &fw, BRCMF_BLOB_TXCAP);
211+
if (err || !fw) {
212+
brcmf_info("no txcap_blob available (err=%d)\n", err);
213+
return 0;
214+
}
215+
216+
brcmf_info("TxCap blob found, loading\n");
217+
err = brcmf_c_download_blob(ifp, fw->data, fw->size,
218+
"txcapload", "txcapload_status");
219+
220+
release_firmware(fw);
183221
return err;
184222
}
185223

@@ -291,6 +329,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
291329
goto done;
292330
}
293331

332+
/* Do TxCap downloading, if needed */
333+
err = brcmf_c_process_txcap_blob(ifp);
334+
if (err < 0) {
335+
bphy_err(drvr, "download TxCap blob file failed, %d\n", err);
336+
goto done;
337+
}
338+
294339
/* query for 'ver' to get version info from firmware */
295340
memset(buf, 0, sizeof(buf));
296341
err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));

0 commit comments

Comments
 (0)