327-v4.17-0007-brcmfmac-pass-struct-in-brcmf_fw_get_firmwares.patch 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. From d09ae51a4b676151edaf572bcd5f272b5532639f Mon Sep 17 00:00:00 2001
  2. From: Arend Van Spriel <[email protected]>
  3. Date: Thu, 22 Mar 2018 21:28:26 +0100
  4. Subject: [PATCH] brcmfmac: pass struct in brcmf_fw_get_firmwares()
  5. Make the function brcmf_fw_get_firmwares() a bit more easy to extend
  6. using a structure to pass the request parameters.
  7. Reviewed-by: Hante Meuleman <[email protected]>
  8. Reviewed-by: Pieter-Paul Giesberts <[email protected]>
  9. Reviewed-by: Franky Lin <[email protected]>
  10. Signed-off-by: Arend van Spriel <[email protected]>
  11. Signed-off-by: Kalle Valo <[email protected]>
  12. ---
  13. .../broadcom/brcm80211/brcmfmac/firmware.c | 175 ++++++++++++++-------
  14. .../broadcom/brcm80211/brcmfmac/firmware.h | 43 +++--
  15. .../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 38 ++++-
  16. .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 32 +++-
  17. .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 43 ++++-
  18. 5 files changed, 245 insertions(+), 86 deletions(-)
  19. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
  20. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
  21. @@ -438,18 +438,31 @@ void brcmf_fw_nvram_free(void *nvram)
  22. struct brcmf_fw {
  23. struct device *dev;
  24. - u16 flags;
  25. - const struct firmware *code;
  26. - const char *nvram_name;
  27. - u16 domain_nr;
  28. - u16 bus_nr;
  29. - void (*done)(struct device *dev, int err, const struct firmware *fw,
  30. - void *nvram_image, u32 nvram_len);
  31. + struct brcmf_fw_request *req;
  32. + u32 curpos;
  33. + void (*done)(struct device *dev, int err, struct brcmf_fw_request *req);
  34. };
  35. +static void brcmf_fw_request_done(const struct firmware *fw, void *ctx);
  36. +
  37. +static void brcmf_fw_free_request(struct brcmf_fw_request *req)
  38. +{
  39. + struct brcmf_fw_item *item;
  40. + int i;
  41. +
  42. + for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) {
  43. + if (item->type == BRCMF_FW_TYPE_BINARY)
  44. + release_firmware(item->binary);
  45. + else if (item->type == BRCMF_FW_TYPE_NVRAM)
  46. + brcmf_fw_nvram_free(item->nv_data.data);
  47. + }
  48. + kfree(req);
  49. +}
  50. +
  51. static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
  52. {
  53. struct brcmf_fw *fwctx = ctx;
  54. + struct brcmf_fw_item *cur;
  55. u32 nvram_length = 0;
  56. void *nvram = NULL;
  57. u8 *data = NULL;
  58. @@ -457,83 +470,150 @@ static void brcmf_fw_request_nvram_done(
  59. bool raw_nvram;
  60. brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
  61. +
  62. + cur = &fwctx->req->items[fwctx->curpos];
  63. +
  64. if (fw && fw->data) {
  65. data = (u8 *)fw->data;
  66. data_len = fw->size;
  67. raw_nvram = false;
  68. } else {
  69. data = bcm47xx_nvram_get_contents(&data_len);
  70. - if (!data && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
  71. + if (!data && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
  72. goto fail;
  73. raw_nvram = true;
  74. }
  75. if (data)
  76. nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length,
  77. - fwctx->domain_nr, fwctx->bus_nr);
  78. + fwctx->req->domain_nr,
  79. + fwctx->req->bus_nr);
  80. if (raw_nvram)
  81. bcm47xx_nvram_release_contents(data);
  82. release_firmware(fw);
  83. - if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
  84. + if (!nvram && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
  85. goto fail;
  86. - fwctx->done(fwctx->dev, 0, fwctx->code, nvram, nvram_length);
  87. - kfree(fwctx);
  88. + brcmf_dbg(TRACE, "nvram %p len %d\n", nvram, nvram_length);
  89. + cur->nv_data.data = nvram;
  90. + cur->nv_data.len = nvram_length;
  91. return;
  92. fail:
  93. brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
  94. - release_firmware(fwctx->code);
  95. - fwctx->done(fwctx->dev, -ENOENT, NULL, NULL, 0);
  96. + fwctx->done(fwctx->dev, -ENOENT, NULL);
  97. + brcmf_fw_free_request(fwctx->req);
  98. kfree(fwctx);
  99. }
  100. -static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)
  101. +static int brcmf_fw_request_next_item(struct brcmf_fw *fwctx, bool async)
  102. +{
  103. + struct brcmf_fw_item *cur;
  104. + const struct firmware *fw = NULL;
  105. + int ret;
  106. +
  107. + cur = &fwctx->req->items[fwctx->curpos];
  108. +
  109. + brcmf_dbg(TRACE, "%srequest for %s\n", async ? "async " : "",
  110. + cur->path);
  111. +
  112. + if (async)
  113. + ret = request_firmware_nowait(THIS_MODULE, true, cur->path,
  114. + fwctx->dev, GFP_KERNEL, fwctx,
  115. + brcmf_fw_request_done);
  116. + else
  117. + ret = request_firmware(&fw, cur->path, fwctx->dev);
  118. +
  119. + if (ret < 0) {
  120. + brcmf_fw_request_done(NULL, fwctx);
  121. + } else if (!async && fw) {
  122. + brcmf_dbg(TRACE, "firmware %s %sfound\n", cur->path,
  123. + fw ? "" : "not ");
  124. + if (cur->type == BRCMF_FW_TYPE_BINARY)
  125. + cur->binary = fw;
  126. + else if (cur->type == BRCMF_FW_TYPE_NVRAM)
  127. + brcmf_fw_request_nvram_done(fw, fwctx);
  128. + else
  129. + release_firmware(fw);
  130. +
  131. + return -EAGAIN;
  132. + }
  133. + return 0;
  134. +}
  135. +
  136. +static void brcmf_fw_request_done(const struct firmware *fw, void *ctx)
  137. {
  138. struct brcmf_fw *fwctx = ctx;
  139. + struct brcmf_fw_item *cur;
  140. int ret = 0;
  141. - brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
  142. - if (!fw) {
  143. + cur = &fwctx->req->items[fwctx->curpos];
  144. +
  145. + brcmf_dbg(TRACE, "enter: firmware %s %sfound\n", cur->path,
  146. + fw ? "" : "not ");
  147. +
  148. + if (fw) {
  149. + if (cur->type == BRCMF_FW_TYPE_BINARY)
  150. + cur->binary = fw;
  151. + else if (cur->type == BRCMF_FW_TYPE_NVRAM)
  152. + brcmf_fw_request_nvram_done(fw, fwctx);
  153. + else
  154. + release_firmware(fw);
  155. + } else if (cur->type == BRCMF_FW_TYPE_NVRAM) {
  156. + brcmf_fw_request_nvram_done(NULL, fwctx);
  157. + } else if (!(cur->flags & BRCMF_FW_REQF_OPTIONAL)) {
  158. ret = -ENOENT;
  159. goto fail;
  160. }
  161. - /* only requested code so done here */
  162. - if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM))
  163. - goto done;
  164. -
  165. - fwctx->code = fw;
  166. - ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
  167. - fwctx->dev, GFP_KERNEL, fwctx,
  168. - brcmf_fw_request_nvram_done);
  169. - /* pass NULL to nvram callback for bcm47xx fallback */
  170. - if (ret)
  171. - brcmf_fw_request_nvram_done(NULL, fwctx);
  172. + do {
  173. + if (++fwctx->curpos == fwctx->req->n_items) {
  174. + ret = 0;
  175. + goto done;
  176. + }
  177. +
  178. + ret = brcmf_fw_request_next_item(fwctx, false);
  179. + } while (ret == -EAGAIN);
  180. +
  181. return;
  182. fail:
  183. - brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
  184. + brcmf_dbg(TRACE, "failed err=%d: dev=%s, fw=%s\n", ret,
  185. + dev_name(fwctx->dev), cur->path);
  186. + brcmf_fw_free_request(fwctx->req);
  187. + fwctx->req = NULL;
  188. done:
  189. - fwctx->done(fwctx->dev, ret, fw, NULL, 0);
  190. + fwctx->done(fwctx->dev, ret, fwctx->req);
  191. kfree(fwctx);
  192. }
  193. -int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
  194. - const char *code, const char *nvram,
  195. - void (*fw_cb)(struct device *dev, int err,
  196. - const struct firmware *fw,
  197. - void *nvram_image, u32 nvram_len),
  198. - u16 domain_nr, u16 bus_nr)
  199. +static bool brcmf_fw_request_is_valid(struct brcmf_fw_request *req)
  200. +{
  201. + struct brcmf_fw_item *item;
  202. + int i;
  203. +
  204. + if (!req->n_items)
  205. + return false;
  206. +
  207. + for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) {
  208. + if (!item->path)
  209. + return false;
  210. + }
  211. + return true;
  212. +}
  213. +
  214. +int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
  215. + void (*fw_cb)(struct device *dev, int err,
  216. + struct brcmf_fw_request *req))
  217. {
  218. struct brcmf_fw *fwctx;
  219. brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
  220. - if (!fw_cb || !code)
  221. + if (!fw_cb)
  222. return -EINVAL;
  223. - if ((flags & BRCMF_FW_REQUEST_NVRAM) && !nvram)
  224. + if (!brcmf_fw_request_is_valid(req))
  225. return -EINVAL;
  226. fwctx = kzalloc(sizeof(*fwctx), GFP_KERNEL);
  227. @@ -541,26 +621,11 @@ int brcmf_fw_get_firmwares_pcie(struct d
  228. return -ENOMEM;
  229. fwctx->dev = dev;
  230. - fwctx->flags = flags;
  231. + fwctx->req = req;
  232. fwctx->done = fw_cb;
  233. - if (flags & BRCMF_FW_REQUEST_NVRAM)
  234. - fwctx->nvram_name = nvram;
  235. - fwctx->domain_nr = domain_nr;
  236. - fwctx->bus_nr = bus_nr;
  237. -
  238. - return request_firmware_nowait(THIS_MODULE, true, code, dev,
  239. - GFP_KERNEL, fwctx,
  240. - brcmf_fw_request_code_done);
  241. -}
  242. -int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
  243. - const char *code, const char *nvram,
  244. - void (*fw_cb)(struct device *dev, int err,
  245. - const struct firmware *fw,
  246. - void *nvram_image, u32 nvram_len))
  247. -{
  248. - return brcmf_fw_get_firmwares_pcie(dev, flags, code, nvram, fw_cb, 0,
  249. - 0);
  250. + brcmf_fw_request_next_item(fwctx, true);
  251. + return 0;
  252. }
  253. static void brcmf_fw_get_full_name(char fw_name[BRCMF_FW_NAME_LEN],
  254. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
  255. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
  256. @@ -16,10 +16,7 @@
  257. #ifndef BRCMFMAC_FIRMWARE_H
  258. #define BRCMFMAC_FIRMWARE_H
  259. -#define BRCMF_FW_REQUEST 0x000F
  260. -#define BRCMF_FW_REQUEST_NVRAM 0x0001
  261. -#define BRCMF_FW_REQ_FLAGS 0x00F0
  262. -#define BRCMF_FW_REQ_NV_OPTIONAL 0x0010
  263. +#define BRCMF_FW_REQF_OPTIONAL 0x0001
  264. #define BRCMF_FW_NAME_LEN 320
  265. @@ -54,21 +51,39 @@ int brcmf_fw_map_chip_to_name(u32 chip,
  266. u32 table_size, char fw_name[BRCMF_FW_NAME_LEN],
  267. char nvram_name[BRCMF_FW_NAME_LEN]);
  268. void brcmf_fw_nvram_free(void *nvram);
  269. +
  270. +enum brcmf_fw_type {
  271. + BRCMF_FW_TYPE_BINARY,
  272. + BRCMF_FW_TYPE_NVRAM
  273. +};
  274. +
  275. +struct brcmf_fw_item {
  276. + const char *path;
  277. + enum brcmf_fw_type type;
  278. + u16 flags;
  279. + union {
  280. + const struct firmware *binary;
  281. + struct {
  282. + void *data;
  283. + u32 len;
  284. + } nv_data;
  285. + };
  286. +};
  287. +
  288. +struct brcmf_fw_request {
  289. + u16 domain_nr;
  290. + u16 bus_nr;
  291. + u32 n_items;
  292. + struct brcmf_fw_item items[0];
  293. +};
  294. +
  295. /*
  296. * Request firmware(s) asynchronously. When the asynchronous request
  297. * fails it will not use the callback, but call device_release_driver()
  298. * instead which will call the driver .remove() callback.
  299. */
  300. -int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
  301. - const char *code, const char *nvram,
  302. - void (*fw_cb)(struct device *dev, int err,
  303. - const struct firmware *fw,
  304. - void *nvram_image, u32 nvram_len),
  305. - u16 domain_nr, u16 bus_nr);
  306. -int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
  307. - const char *code, const char *nvram,
  308. +int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
  309. void (*fw_cb)(struct device *dev, int err,
  310. - const struct firmware *fw,
  311. - void *nvram_image, u32 nvram_len));
  312. + struct brcmf_fw_request *req));
  313. #endif /* BRCMFMAC_FIRMWARE_H */
  314. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
  315. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
  316. @@ -1651,15 +1651,19 @@ static const struct brcmf_buscore_ops br
  317. .write32 = brcmf_pcie_buscore_write32,
  318. };
  319. +#define BRCMF_PCIE_FW_CODE 0
  320. +#define BRCMF_PCIE_FW_NVRAM 1
  321. +
  322. static void brcmf_pcie_setup(struct device *dev, int ret,
  323. - const struct firmware *fw,
  324. - void *nvram, u32 nvram_len)
  325. + struct brcmf_fw_request *fwreq)
  326. {
  327. + const struct firmware *fw;
  328. + void *nvram;
  329. struct brcmf_bus *bus;
  330. struct brcmf_pciedev *pcie_bus_dev;
  331. struct brcmf_pciedev_info *devinfo;
  332. struct brcmf_commonring **flowrings;
  333. - u32 i;
  334. + u32 i, nvram_len;
  335. /* check firmware loading result */
  336. if (ret)
  337. @@ -1670,6 +1674,11 @@ static void brcmf_pcie_setup(struct devi
  338. devinfo = pcie_bus_dev->devinfo;
  339. brcmf_pcie_attach(devinfo);
  340. + fw = fwreq->items[BRCMF_PCIE_FW_CODE].binary;
  341. + nvram = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.data;
  342. + nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len;
  343. + kfree(fwreq);
  344. +
  345. /* Some of the firmwares have the size of the memory of the device
  346. * defined inside the firmware. This is because part of the memory in
  347. * the device is shared and the devision is determined by FW. Parse
  348. @@ -1730,6 +1739,7 @@ static int
  349. brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
  350. {
  351. int ret;
  352. + struct brcmf_fw_request *fwreq;
  353. struct brcmf_pciedev_info *devinfo;
  354. struct brcmf_pciedev *pcie_bus_dev;
  355. struct brcmf_bus *bus;
  356. @@ -1800,12 +1810,26 @@ brcmf_pcie_probe(struct pci_dev *pdev, c
  357. if (ret)
  358. goto fail_bus;
  359. - ret = brcmf_fw_get_firmwares_pcie(bus->dev, BRCMF_FW_REQUEST_NVRAM |
  360. - BRCMF_FW_REQ_NV_OPTIONAL,
  361. - devinfo->fw_name, devinfo->nvram_name,
  362. - brcmf_pcie_setup, domain_nr, bus_nr);
  363. + fwreq = kzalloc(sizeof(*fwreq) + 2 * sizeof(struct brcmf_fw_item),
  364. + GFP_KERNEL);
  365. + if (!fwreq) {
  366. + ret = -ENOMEM;
  367. + goto fail_bus;
  368. + }
  369. +
  370. + fwreq->items[BRCMF_PCIE_FW_CODE].path = devinfo->fw_name;
  371. + fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
  372. + fwreq->items[BRCMF_PCIE_FW_NVRAM].path = devinfo->nvram_name;
  373. + fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
  374. + fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
  375. + fwreq->n_items = 2;
  376. + fwreq->domain_nr = domain_nr;
  377. + fwreq->bus_nr = bus_nr;
  378. + ret = brcmf_fw_get_firmwares(bus->dev, fwreq, brcmf_pcie_setup);
  379. if (ret == 0)
  380. return 0;
  381. +
  382. + kfree(fwreq);
  383. fail_bus:
  384. kfree(bus->msgbuf);
  385. kfree(bus);
  386. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
  387. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
  388. @@ -4031,14 +4031,19 @@ static const struct brcmf_bus_ops brcmf_
  389. .get_fwname = brcmf_sdio_get_fwname,
  390. };
  391. +#define BRCMF_SDIO_FW_CODE 0
  392. +#define BRCMF_SDIO_FW_NVRAM 1
  393. +
  394. static void brcmf_sdio_firmware_callback(struct device *dev, int err,
  395. - const struct firmware *code,
  396. - void *nvram, u32 nvram_len)
  397. + struct brcmf_fw_request *fwreq)
  398. {
  399. struct brcmf_bus *bus_if = dev_get_drvdata(dev);
  400. struct brcmf_sdio_dev *sdiod = bus_if->bus_priv.sdio;
  401. struct brcmf_sdio *bus = sdiod->bus;
  402. struct brcmf_core *core = bus->sdio_core;
  403. + const struct firmware *code;
  404. + void *nvram;
  405. + u32 nvram_len;
  406. u8 saveclk;
  407. brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
  408. @@ -4046,6 +4051,11 @@ static void brcmf_sdio_firmware_callback
  409. if (err)
  410. goto fail;
  411. + code = fwreq->items[BRCMF_SDIO_FW_CODE].binary;
  412. + nvram = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.data;
  413. + nvram_len = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.len;
  414. + kfree(fwreq);
  415. +
  416. /* try to download image and nvram to the dongle */
  417. bus->alp_only = true;
  418. err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len);
  419. @@ -4150,6 +4160,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
  420. int ret;
  421. struct brcmf_sdio *bus;
  422. struct workqueue_struct *wq;
  423. + struct brcmf_fw_request *fwreq;
  424. brcmf_dbg(TRACE, "Enter\n");
  425. @@ -4240,11 +4251,24 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
  426. if (ret)
  427. goto fail;
  428. - ret = brcmf_fw_get_firmwares(sdiodev->dev, BRCMF_FW_REQUEST_NVRAM,
  429. - sdiodev->fw_name, sdiodev->nvram_name,
  430. + fwreq = kzalloc(sizeof(fwreq) + 2 * sizeof(struct brcmf_fw_item),
  431. + GFP_KERNEL);
  432. + if (!fwreq) {
  433. + ret = -ENOMEM;
  434. + goto fail;
  435. + }
  436. +
  437. + fwreq->items[BRCMF_SDIO_FW_CODE].path = sdiodev->fw_name;
  438. + fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
  439. + fwreq->items[BRCMF_SDIO_FW_NVRAM].path = sdiodev->nvram_name;
  440. + fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
  441. + fwreq->n_items = 2;
  442. +
  443. + ret = brcmf_fw_get_firmwares(sdiodev->dev, fwreq,
  444. brcmf_sdio_firmware_callback);
  445. if (ret != 0) {
  446. brcmf_err("async firmware request failed: %d\n", ret);
  447. + kfree(fwreq);
  448. goto fail;
  449. }
  450. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
  451. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
  452. @@ -1155,18 +1155,23 @@ static const struct brcmf_bus_ops brcmf_
  453. .get_fwname = brcmf_usb_get_fwname,
  454. };
  455. +#define BRCMF_USB_FW_CODE 0
  456. +
  457. static void brcmf_usb_probe_phase2(struct device *dev, int ret,
  458. - const struct firmware *fw,
  459. - void *nvram, u32 nvlen)
  460. + struct brcmf_fw_request *fwreq)
  461. {
  462. struct brcmf_bus *bus = dev_get_drvdata(dev);
  463. struct brcmf_usbdev_info *devinfo = bus->bus_priv.usb->devinfo;
  464. + const struct firmware *fw;
  465. if (ret)
  466. goto error;
  467. brcmf_dbg(USB, "Start fw downloading\n");
  468. + fw = fwreq->items[BRCMF_USB_FW_CODE].binary;
  469. + kfree(fwreq);
  470. +
  471. ret = check_file(fw->data);
  472. if (ret < 0) {
  473. brcmf_err("invalid firmware\n");
  474. @@ -1200,6 +1205,7 @@ static int brcmf_usb_probe_cb(struct brc
  475. struct brcmf_bus *bus = NULL;
  476. struct brcmf_usbdev *bus_pub = NULL;
  477. struct device *dev = devinfo->dev;
  478. + struct brcmf_fw_request *fwreq;
  479. int ret;
  480. brcmf_dbg(USB, "Enter\n");
  481. @@ -1250,11 +1256,22 @@ static int brcmf_usb_probe_cb(struct brc
  482. if (ret)
  483. goto fail;
  484. + fwreq = kzalloc(sizeof(*fwreq) + sizeof(struct brcmf_fw_item),
  485. + GFP_KERNEL);
  486. + if (!fwreq) {
  487. + ret = -ENOMEM;
  488. + goto fail;
  489. + }
  490. +
  491. + fwreq->items[BRCMF_USB_FW_CODE].path = devinfo->fw_name;
  492. + fwreq->items[BRCMF_USB_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
  493. + fwreq->n_items = 1;
  494. +
  495. /* request firmware here */
  496. - ret = brcmf_fw_get_firmwares(dev, 0, devinfo->fw_name, NULL,
  497. - brcmf_usb_probe_phase2);
  498. + ret = brcmf_fw_get_firmwares(dev, fwreq, brcmf_usb_probe_phase2);
  499. if (ret) {
  500. brcmf_err("firmware request failed: %d\n", ret);
  501. + kfree(fwreq);
  502. goto fail;
  503. }
  504. @@ -1447,11 +1464,25 @@ static int brcmf_usb_reset_resume(struct
  505. {
  506. struct usb_device *usb = interface_to_usbdev(intf);
  507. struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
  508. + struct brcmf_fw_request *fwreq;
  509. + int ret;
  510. brcmf_dbg(USB, "Enter\n");
  511. - return brcmf_fw_get_firmwares(&usb->dev, 0, devinfo->fw_name, NULL,
  512. - brcmf_usb_probe_phase2);
  513. + fwreq = kzalloc(sizeof(*fwreq) + sizeof(struct brcmf_fw_item),
  514. + GFP_KERNEL);
  515. + if (!fwreq)
  516. + return -ENOMEM;
  517. +
  518. + fwreq->items[BRCMF_USB_FW_CODE].path = devinfo->fw_name;
  519. + fwreq->items[BRCMF_USB_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
  520. + fwreq->n_items = 1;
  521. +
  522. + ret = brcmf_fw_get_firmwares(&usb->dev, fwreq, brcmf_usb_probe_phase2);
  523. + if (ret < 0)
  524. + kfree(fwreq);
  525. +
  526. + return ret;
  527. }
  528. #define BRCMF_USB_DEVICE(dev_id) \