Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[cascardo/linux.git] / drivers / net / wireless / brcm80211 / brcmfmac / firmware.c
1 /*
2  * Copyright (c) 2013 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <linux/kernel.h>
18 #include <linux/slab.h>
19 #include <linux/device.h>
20 #include <linux/firmware.h>
21 #include <linux/module.h>
22
23 #include "debug.h"
24 #include "firmware.h"
25
26 #define BRCMF_FW_MAX_NVRAM_SIZE                 64000
27 #define BRCMF_FW_NVRAM_DEVPATH_LEN              19      /* devpath0=pcie/1/4/ */
28 #define BRCMF_FW_NVRAM_PCIEDEV_LEN              10      /* pcie/1/4/ + \0 */
29
30 char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
31 module_param_string(firmware_path, brcmf_firmware_path,
32                     BRCMF_FW_PATH_LEN, 0440);
33
34 enum nvram_parser_state {
35         IDLE,
36         KEY,
37         VALUE,
38         COMMENT,
39         END
40 };
41
42 /**
43  * struct nvram_parser - internal info for parser.
44  *
45  * @state: current parser state.
46  * @fwnv: input buffer being parsed.
47  * @nvram: output buffer with parse result.
48  * @nvram_len: lenght of parse result.
49  * @line: current line.
50  * @column: current column in line.
51  * @pos: byte offset in input buffer.
52  * @entry: start position of key,value entry.
53  * @multi_dev_v1: detect pcie multi device v1 (compressed).
54  * @multi_dev_v2: detect pcie multi device v2.
55  */
56 struct nvram_parser {
57         enum nvram_parser_state state;
58         const struct firmware *fwnv;
59         u8 *nvram;
60         u32 nvram_len;
61         u32 line;
62         u32 column;
63         u32 pos;
64         u32 entry;
65         bool multi_dev_v1;
66         bool multi_dev_v2;
67 };
68
69 /**
70  * is_nvram_char() - check if char is a valid one for NVRAM entry
71  *
72  * It accepts all printable ASCII chars except for '#' which opens a comment.
73  * Please note that ' ' (space) while accepted is not a valid key name char.
74  */
75 static bool is_nvram_char(char c)
76 {
77         /* comment marker excluded */
78         if (c == '#')
79                 return false;
80
81         /* key and value may have any other readable character */
82         return (c >= 0x20 && c < 0x7f);
83 }
84
85 static bool is_whitespace(char c)
86 {
87         return (c == ' ' || c == '\r' || c == '\n' || c == '\t');
88 }
89
90 static enum nvram_parser_state brcmf_nvram_handle_idle(struct nvram_parser *nvp)
91 {
92         char c;
93
94         c = nvp->fwnv->data[nvp->pos];
95         if (c == '\n')
96                 return COMMENT;
97         if (is_whitespace(c))
98                 goto proceed;
99         if (c == '#')
100                 return COMMENT;
101         if (is_nvram_char(c)) {
102                 nvp->entry = nvp->pos;
103                 return KEY;
104         }
105         brcmf_dbg(INFO, "warning: ln=%d:col=%d: ignoring invalid character\n",
106                   nvp->line, nvp->column);
107 proceed:
108         nvp->column++;
109         nvp->pos++;
110         return IDLE;
111 }
112
113 static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
114 {
115         enum nvram_parser_state st = nvp->state;
116         char c;
117
118         c = nvp->fwnv->data[nvp->pos];
119         if (c == '=') {
120                 /* ignore RAW1 by treating as comment */
121                 if (strncmp(&nvp->fwnv->data[nvp->entry], "RAW1", 4) == 0)
122                         st = COMMENT;
123                 else
124                         st = VALUE;
125                 if (strncmp(&nvp->fwnv->data[nvp->entry], "devpath", 7) == 0)
126                         nvp->multi_dev_v1 = true;
127                 if (strncmp(&nvp->fwnv->data[nvp->entry], "pcie/", 5) == 0)
128                         nvp->multi_dev_v2 = true;
129         } else if (!is_nvram_char(c) || c == ' ') {
130                 brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
131                           nvp->line, nvp->column);
132                 return COMMENT;
133         }
134
135         nvp->column++;
136         nvp->pos++;
137         return st;
138 }
139
140 static enum nvram_parser_state
141 brcmf_nvram_handle_value(struct nvram_parser *nvp)
142 {
143         char c;
144         char *skv;
145         char *ekv;
146         u32 cplen;
147
148         c = nvp->fwnv->data[nvp->pos];
149         if (!is_nvram_char(c)) {
150                 /* key,value pair complete */
151                 ekv = (u8 *)&nvp->fwnv->data[nvp->pos];
152                 skv = (u8 *)&nvp->fwnv->data[nvp->entry];
153                 cplen = ekv - skv;
154                 if (nvp->nvram_len + cplen + 1 >= BRCMF_FW_MAX_NVRAM_SIZE)
155                         return END;
156                 /* copy to output buffer */
157                 memcpy(&nvp->nvram[nvp->nvram_len], skv, cplen);
158                 nvp->nvram_len += cplen;
159                 nvp->nvram[nvp->nvram_len] = '\0';
160                 nvp->nvram_len++;
161                 return IDLE;
162         }
163         nvp->pos++;
164         nvp->column++;
165         return VALUE;
166 }
167
168 static enum nvram_parser_state
169 brcmf_nvram_handle_comment(struct nvram_parser *nvp)
170 {
171         char *eoc, *sol;
172
173         sol = (char *)&nvp->fwnv->data[nvp->pos];
174         eoc = strchr(sol, '\n');
175         if (!eoc) {
176                 eoc = strchr(sol, '\0');
177                 if (!eoc)
178                         return END;
179         }
180
181         /* eat all moving to next line */
182         nvp->line++;
183         nvp->column = 1;
184         nvp->pos += (eoc - sol) + 1;
185         return IDLE;
186 }
187
188 static enum nvram_parser_state brcmf_nvram_handle_end(struct nvram_parser *nvp)
189 {
190         /* final state */
191         return END;
192 }
193
194 static enum nvram_parser_state
195 (*nv_parser_states[])(struct nvram_parser *nvp) = {
196         brcmf_nvram_handle_idle,
197         brcmf_nvram_handle_key,
198         brcmf_nvram_handle_value,
199         brcmf_nvram_handle_comment,
200         brcmf_nvram_handle_end
201 };
202
203 static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
204                                    const struct firmware *nv)
205 {
206         size_t size;
207
208         memset(nvp, 0, sizeof(*nvp));
209         nvp->fwnv = nv;
210         /* Limit size to MAX_NVRAM_SIZE, some files contain lot of comment */
211         if (nv->size > BRCMF_FW_MAX_NVRAM_SIZE)
212                 size = BRCMF_FW_MAX_NVRAM_SIZE;
213         else
214                 size = nv->size;
215         /* Alloc for extra 0 byte + roundup by 4 + length field */
216         size += 1 + 3 + sizeof(u32);
217         nvp->nvram = kzalloc(size, GFP_KERNEL);
218         if (!nvp->nvram)
219                 return -ENOMEM;
220
221         nvp->line = 1;
222         nvp->column = 1;
223         return 0;
224 }
225
226 /* brcmf_fw_strip_multi_v1 :Some nvram files contain settings for multiple
227  * devices. Strip it down for one device, use domain_nr/bus_nr to determine
228  * which data is to be returned. v1 is the version where nvram is stored
229  * compressed and "devpath" maps to index for valid entries.
230  */
231 static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
232                                     u16 bus_nr)
233 {
234         /* Device path with a leading '=' key-value separator */
235         char pcie_path[] = "=pcie/?/?";
236         size_t pcie_len;
237
238         u32 i, j;
239         bool found;
240         u8 *nvram;
241         u8 id;
242
243         nvram = kzalloc(nvp->nvram_len + 1 + 3 + sizeof(u32), GFP_KERNEL);
244         if (!nvram)
245                 goto fail;
246
247         /* min length: devpath0=pcie/1/4/ + 0:x=y */
248         if (nvp->nvram_len < BRCMF_FW_NVRAM_DEVPATH_LEN + 6)
249                 goto fail;
250
251         /* First search for the devpathX and see if it is the configuration
252          * for domain_nr/bus_nr. Search complete nvp
253          */
254         snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr,
255                  bus_nr);
256         pcie_len = strlen(pcie_path);
257         found = false;
258         i = 0;
259         while (i < nvp->nvram_len - BRCMF_FW_NVRAM_DEVPATH_LEN) {
260                 /* Format: devpathX=pcie/Y/Z/
261                  * Y = domain_nr, Z = bus_nr, X = virtual ID
262                  */
263                 if ((strncmp(&nvp->nvram[i], "devpath", 7) == 0) &&
264                     (strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len) == 0)) {
265                         id = nvp->nvram[i + 7] - '0';
266                         found = true;
267                         break;
268                 }
269                 while (nvp->nvram[i] != 0)
270                         i++;
271                 i++;
272         }
273         if (!found)
274                 goto fail;
275
276         /* Now copy all valid entries, release old nvram and assign new one */
277         i = 0;
278         j = 0;
279         while (i < nvp->nvram_len) {
280                 if ((nvp->nvram[i] - '0' == id) && (nvp->nvram[i + 1] == ':')) {
281                         i += 2;
282                         while (nvp->nvram[i] != 0) {
283                                 nvram[j] = nvp->nvram[i];
284                                 i++;
285                                 j++;
286                         }
287                         nvram[j] = 0;
288                         j++;
289                 }
290                 while (nvp->nvram[i] != 0)
291                         i++;
292                 i++;
293         }
294         kfree(nvp->nvram);
295         nvp->nvram = nvram;
296         nvp->nvram_len = j;
297         return;
298
299 fail:
300         kfree(nvram);
301         nvp->nvram_len = 0;
302 }
303
304 /* brcmf_fw_strip_multi_v2 :Some nvram files contain settings for multiple
305  * devices. Strip it down for one device, use domain_nr/bus_nr to determine
306  * which data is to be returned. v2 is the version where nvram is stored
307  * uncompressed, all relevant valid entries are identified by
308  * pcie/domain_nr/bus_nr:
309  */
310 static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr,
311                                     u16 bus_nr)
312 {
313         char prefix[BRCMF_FW_NVRAM_PCIEDEV_LEN];
314         size_t len;
315         u32 i, j;
316         u8 *nvram;
317
318         nvram = kzalloc(nvp->nvram_len + 1 + 3 + sizeof(u32), GFP_KERNEL);
319         if (!nvram)
320                 goto fail;
321
322         /* Copy all valid entries, release old nvram and assign new one.
323          * Valid entries are of type pcie/X/Y/ where X = domain_nr and
324          * Y = bus_nr.
325          */
326         snprintf(prefix, sizeof(prefix), "pcie/%d/%d/", domain_nr, bus_nr);
327         len = strlen(prefix);
328         i = 0;
329         j = 0;
330         while (i < nvp->nvram_len - len) {
331                 if (strncmp(&nvp->nvram[i], prefix, len) == 0) {
332                         i += len;
333                         while (nvp->nvram[i] != 0) {
334                                 nvram[j] = nvp->nvram[i];
335                                 i++;
336                                 j++;
337                         }
338                         nvram[j] = 0;
339                         j++;
340                 }
341                 while (nvp->nvram[i] != 0)
342                         i++;
343                 i++;
344         }
345         kfree(nvp->nvram);
346         nvp->nvram = nvram;
347         nvp->nvram_len = j;
348         return;
349 fail:
350         kfree(nvram);
351         nvp->nvram_len = 0;
352 }
353
354 /* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a fil
355  * and ending in a NUL. Removes carriage returns, empty lines, comment lines,
356  * and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
357  * End of buffer is completed with token identifying length of buffer.
358  */
359 static void *brcmf_fw_nvram_strip(const struct firmware *nv, u32 *new_length,
360                                   u16 domain_nr, u16 bus_nr)
361 {
362         struct nvram_parser nvp;
363         u32 pad;
364         u32 token;
365         __le32 token_le;
366
367         if (brcmf_init_nvram_parser(&nvp, nv) < 0)
368                 return NULL;
369
370         while (nvp.pos < nv->size) {
371                 nvp.state = nv_parser_states[nvp.state](&nvp);
372                 if (nvp.state == END)
373                         break;
374         }
375         if (nvp.multi_dev_v1)
376                 brcmf_fw_strip_multi_v1(&nvp, domain_nr, bus_nr);
377         else if (nvp.multi_dev_v2)
378                 brcmf_fw_strip_multi_v2(&nvp, domain_nr, bus_nr);
379
380         if (nvp.nvram_len == 0) {
381                 kfree(nvp.nvram);
382                 return NULL;
383         }
384
385         pad = nvp.nvram_len;
386         *new_length = roundup(nvp.nvram_len + 1, 4);
387         while (pad != *new_length) {
388                 nvp.nvram[pad] = 0;
389                 pad++;
390         }
391
392         token = *new_length / 4;
393         token = (~token << 16) | (token & 0x0000FFFF);
394         token_le = cpu_to_le32(token);
395
396         memcpy(&nvp.nvram[*new_length], &token_le, sizeof(token_le));
397         *new_length += sizeof(token_le);
398
399         return nvp.nvram;
400 }
401
402 void brcmf_fw_nvram_free(void *nvram)
403 {
404         kfree(nvram);
405 }
406
407 struct brcmf_fw {
408         struct device *dev;
409         u16 flags;
410         const struct firmware *code;
411         const char *nvram_name;
412         u16 domain_nr;
413         u16 bus_nr;
414         void (*done)(struct device *dev, const struct firmware *fw,
415                      void *nvram_image, u32 nvram_len);
416 };
417
418 static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
419 {
420         struct brcmf_fw *fwctx = ctx;
421         u32 nvram_length = 0;
422         void *nvram = NULL;
423
424         brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
425         if (!fw && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
426                 goto fail;
427
428         if (fw) {
429                 nvram = brcmf_fw_nvram_strip(fw, &nvram_length,
430                                              fwctx->domain_nr, fwctx->bus_nr);
431                 release_firmware(fw);
432                 if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
433                         goto fail;
434         }
435
436         fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length);
437         kfree(fwctx);
438         return;
439
440 fail:
441         brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
442         release_firmware(fwctx->code);
443         device_release_driver(fwctx->dev);
444         kfree(fwctx);
445 }
446
447 static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)
448 {
449         struct brcmf_fw *fwctx = ctx;
450         int ret;
451
452         brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
453         if (!fw)
454                 goto fail;
455
456         /* only requested code so done here */
457         if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) {
458                 fwctx->done(fwctx->dev, fw, NULL, 0);
459                 kfree(fwctx);
460                 return;
461         }
462         fwctx->code = fw;
463         ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
464                                       fwctx->dev, GFP_KERNEL, fwctx,
465                                       brcmf_fw_request_nvram_done);
466
467         if (!ret)
468                 return;
469
470         /* when nvram is optional call .done() callback here */
471         if (fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL) {
472                 fwctx->done(fwctx->dev, fw, NULL, 0);
473                 kfree(fwctx);
474                 return;
475         }
476
477         /* failed nvram request */
478         release_firmware(fw);
479 fail:
480         brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
481         device_release_driver(fwctx->dev);
482         kfree(fwctx);
483 }
484
485 int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
486                                 const char *code, const char *nvram,
487                                 void (*fw_cb)(struct device *dev,
488                                               const struct firmware *fw,
489                                               void *nvram_image, u32 nvram_len),
490                                 u16 domain_nr, u16 bus_nr)
491 {
492         struct brcmf_fw *fwctx;
493
494         brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
495         if (!fw_cb || !code)
496                 return -EINVAL;
497
498         if ((flags & BRCMF_FW_REQUEST_NVRAM) && !nvram)
499                 return -EINVAL;
500
501         fwctx = kzalloc(sizeof(*fwctx), GFP_KERNEL);
502         if (!fwctx)
503                 return -ENOMEM;
504
505         fwctx->dev = dev;
506         fwctx->flags = flags;
507         fwctx->done = fw_cb;
508         if (flags & BRCMF_FW_REQUEST_NVRAM)
509                 fwctx->nvram_name = nvram;
510         fwctx->domain_nr = domain_nr;
511         fwctx->bus_nr = bus_nr;
512
513         return request_firmware_nowait(THIS_MODULE, true, code, dev,
514                                        GFP_KERNEL, fwctx,
515                                        brcmf_fw_request_code_done);
516 }
517
518 int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
519                            const char *code, const char *nvram,
520                            void (*fw_cb)(struct device *dev,
521                                          const struct firmware *fw,
522                                          void *nvram_image, u32 nvram_len))
523 {
524         return brcmf_fw_get_firmwares_pcie(dev, flags, code, nvram, fw_cb, 0,
525                                            0);
526 }
527