Skip to content

Commit d09ae51

Browse files
Arend Van SprielKalle Valo
authored andcommitted
brcmfmac: pass struct in brcmf_fw_get_firmwares()
Make the function brcmf_fw_get_firmwares() a bit more easy to extend using a structure to pass the request parameters. Reviewed-by: Hante Meuleman <[email protected]> Reviewed-by: Pieter-Paul Giesberts <[email protected]> Reviewed-by: Franky Lin <[email protected]> Signed-off-by: Arend van Spriel <[email protected]> Signed-off-by: Kalle Valo <[email protected]>
1 parent 41f573d commit d09ae51

File tree

5 files changed

+245
-86
lines changed

5 files changed

+245
-86
lines changed

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

Lines changed: 120 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -438,129 +438,194 @@ void brcmf_fw_nvram_free(void *nvram)
438438

439439
struct brcmf_fw {
440440
struct device *dev;
441-
u16 flags;
442-
const struct firmware *code;
443-
const char *nvram_name;
444-
u16 domain_nr;
445-
u16 bus_nr;
446-
void (*done)(struct device *dev, int err, const struct firmware *fw,
447-
void *nvram_image, u32 nvram_len);
441+
struct brcmf_fw_request *req;
442+
u32 curpos;
443+
void (*done)(struct device *dev, int err, struct brcmf_fw_request *req);
448444
};
449445

446+
static void brcmf_fw_request_done(const struct firmware *fw, void *ctx);
447+
448+
static void brcmf_fw_free_request(struct brcmf_fw_request *req)
449+
{
450+
struct brcmf_fw_item *item;
451+
int i;
452+
453+
for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) {
454+
if (item->type == BRCMF_FW_TYPE_BINARY)
455+
release_firmware(item->binary);
456+
else if (item->type == BRCMF_FW_TYPE_NVRAM)
457+
brcmf_fw_nvram_free(item->nv_data.data);
458+
}
459+
kfree(req);
460+
}
461+
450462
static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
451463
{
452464
struct brcmf_fw *fwctx = ctx;
465+
struct brcmf_fw_item *cur;
453466
u32 nvram_length = 0;
454467
void *nvram = NULL;
455468
u8 *data = NULL;
456469
size_t data_len;
457470
bool raw_nvram;
458471

459472
brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
473+
474+
cur = &fwctx->req->items[fwctx->curpos];
475+
460476
if (fw && fw->data) {
461477
data = (u8 *)fw->data;
462478
data_len = fw->size;
463479
raw_nvram = false;
464480
} else {
465481
data = bcm47xx_nvram_get_contents(&data_len);
466-
if (!data && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
482+
if (!data && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
467483
goto fail;
468484
raw_nvram = true;
469485
}
470486

471487
if (data)
472488
nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length,
473-
fwctx->domain_nr, fwctx->bus_nr);
489+
fwctx->req->domain_nr,
490+
fwctx->req->bus_nr);
474491

475492
if (raw_nvram)
476493
bcm47xx_nvram_release_contents(data);
477494
release_firmware(fw);
478-
if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
495+
if (!nvram && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
479496
goto fail;
480497

481-
fwctx->done(fwctx->dev, 0, fwctx->code, nvram, nvram_length);
482-
kfree(fwctx);
498+
brcmf_dbg(TRACE, "nvram %p len %d\n", nvram, nvram_length);
499+
cur->nv_data.data = nvram;
500+
cur->nv_data.len = nvram_length;
483501
return;
484502

485503
fail:
486504
brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
487-
release_firmware(fwctx->code);
488-
fwctx->done(fwctx->dev, -ENOENT, NULL, NULL, 0);
505+
fwctx->done(fwctx->dev, -ENOENT, NULL);
506+
brcmf_fw_free_request(fwctx->req);
489507
kfree(fwctx);
490508
}
491509

492-
static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)
510+
static int brcmf_fw_request_next_item(struct brcmf_fw *fwctx, bool async)
511+
{
512+
struct brcmf_fw_item *cur;
513+
const struct firmware *fw = NULL;
514+
int ret;
515+
516+
cur = &fwctx->req->items[fwctx->curpos];
517+
518+
brcmf_dbg(TRACE, "%srequest for %s\n", async ? "async " : "",
519+
cur->path);
520+
521+
if (async)
522+
ret = request_firmware_nowait(THIS_MODULE, true, cur->path,
523+
fwctx->dev, GFP_KERNEL, fwctx,
524+
brcmf_fw_request_done);
525+
else
526+
ret = request_firmware(&fw, cur->path, fwctx->dev);
527+
528+
if (ret < 0) {
529+
brcmf_fw_request_done(NULL, fwctx);
530+
} else if (!async && fw) {
531+
brcmf_dbg(TRACE, "firmware %s %sfound\n", cur->path,
532+
fw ? "" : "not ");
533+
if (cur->type == BRCMF_FW_TYPE_BINARY)
534+
cur->binary = fw;
535+
else if (cur->type == BRCMF_FW_TYPE_NVRAM)
536+
brcmf_fw_request_nvram_done(fw, fwctx);
537+
else
538+
release_firmware(fw);
539+
540+
return -EAGAIN;
541+
}
542+
return 0;
543+
}
544+
545+
static void brcmf_fw_request_done(const struct firmware *fw, void *ctx)
493546
{
494547
struct brcmf_fw *fwctx = ctx;
548+
struct brcmf_fw_item *cur;
495549
int ret = 0;
496550

497-
brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
498-
if (!fw) {
551+
cur = &fwctx->req->items[fwctx->curpos];
552+
553+
brcmf_dbg(TRACE, "enter: firmware %s %sfound\n", cur->path,
554+
fw ? "" : "not ");
555+
556+
if (fw) {
557+
if (cur->type == BRCMF_FW_TYPE_BINARY)
558+
cur->binary = fw;
559+
else if (cur->type == BRCMF_FW_TYPE_NVRAM)
560+
brcmf_fw_request_nvram_done(fw, fwctx);
561+
else
562+
release_firmware(fw);
563+
} else if (cur->type == BRCMF_FW_TYPE_NVRAM) {
564+
brcmf_fw_request_nvram_done(NULL, fwctx);
565+
} else if (!(cur->flags & BRCMF_FW_REQF_OPTIONAL)) {
499566
ret = -ENOENT;
500567
goto fail;
501568
}
502-
/* only requested code so done here */
503-
if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM))
504-
goto done;
505569

506-
fwctx->code = fw;
507-
ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
508-
fwctx->dev, GFP_KERNEL, fwctx,
509-
brcmf_fw_request_nvram_done);
570+
do {
571+
if (++fwctx->curpos == fwctx->req->n_items) {
572+
ret = 0;
573+
goto done;
574+
}
575+
576+
ret = brcmf_fw_request_next_item(fwctx, false);
577+
} while (ret == -EAGAIN);
510578

511-
/* pass NULL to nvram callback for bcm47xx fallback */
512-
if (ret)
513-
brcmf_fw_request_nvram_done(NULL, fwctx);
514579
return;
515580

516581
fail:
517-
brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
582+
brcmf_dbg(TRACE, "failed err=%d: dev=%s, fw=%s\n", ret,
583+
dev_name(fwctx->dev), cur->path);
584+
brcmf_fw_free_request(fwctx->req);
585+
fwctx->req = NULL;
518586
done:
519-
fwctx->done(fwctx->dev, ret, fw, NULL, 0);
587+
fwctx->done(fwctx->dev, ret, fwctx->req);
520588
kfree(fwctx);
521589
}
522590

523-
int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
524-
const char *code, const char *nvram,
525-
void (*fw_cb)(struct device *dev, int err,
526-
const struct firmware *fw,
527-
void *nvram_image, u32 nvram_len),
528-
u16 domain_nr, u16 bus_nr)
591+
static bool brcmf_fw_request_is_valid(struct brcmf_fw_request *req)
592+
{
593+
struct brcmf_fw_item *item;
594+
int i;
595+
596+
if (!req->n_items)
597+
return false;
598+
599+
for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) {
600+
if (!item->path)
601+
return false;
602+
}
603+
return true;
604+
}
605+
606+
int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
607+
void (*fw_cb)(struct device *dev, int err,
608+
struct brcmf_fw_request *req))
529609
{
530610
struct brcmf_fw *fwctx;
531611

532612
brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
533-
if (!fw_cb || !code)
613+
if (!fw_cb)
534614
return -EINVAL;
535615

536-
if ((flags & BRCMF_FW_REQUEST_NVRAM) && !nvram)
616+
if (!brcmf_fw_request_is_valid(req))
537617
return -EINVAL;
538618

539619
fwctx = kzalloc(sizeof(*fwctx), GFP_KERNEL);
540620
if (!fwctx)
541621
return -ENOMEM;
542622

543623
fwctx->dev = dev;
544-
fwctx->flags = flags;
624+
fwctx->req = req;
545625
fwctx->done = fw_cb;
546-
if (flags & BRCMF_FW_REQUEST_NVRAM)
547-
fwctx->nvram_name = nvram;
548-
fwctx->domain_nr = domain_nr;
549-
fwctx->bus_nr = bus_nr;
550-
551-
return request_firmware_nowait(THIS_MODULE, true, code, dev,
552-
GFP_KERNEL, fwctx,
553-
brcmf_fw_request_code_done);
554-
}
555626

556-
int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
557-
const char *code, const char *nvram,
558-
void (*fw_cb)(struct device *dev, int err,
559-
const struct firmware *fw,
560-
void *nvram_image, u32 nvram_len))
561-
{
562-
return brcmf_fw_get_firmwares_pcie(dev, flags, code, nvram, fw_cb, 0,
563-
0);
627+
brcmf_fw_request_next_item(fwctx, true);
628+
return 0;
564629
}
565630

566631
static void brcmf_fw_get_full_name(char fw_name[BRCMF_FW_NAME_LEN],

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

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@
1616
#ifndef BRCMFMAC_FIRMWARE_H
1717
#define BRCMFMAC_FIRMWARE_H
1818

19-
#define BRCMF_FW_REQUEST 0x000F
20-
#define BRCMF_FW_REQUEST_NVRAM 0x0001
21-
#define BRCMF_FW_REQ_FLAGS 0x00F0
22-
#define BRCMF_FW_REQ_NV_OPTIONAL 0x0010
19+
#define BRCMF_FW_REQF_OPTIONAL 0x0001
2320

2421
#define BRCMF_FW_NAME_LEN 320
2522

@@ -54,21 +51,39 @@ int brcmf_fw_map_chip_to_name(u32 chip, u32 chiprev,
5451
u32 table_size, char fw_name[BRCMF_FW_NAME_LEN],
5552
char nvram_name[BRCMF_FW_NAME_LEN]);
5653
void brcmf_fw_nvram_free(void *nvram);
54+
55+
enum brcmf_fw_type {
56+
BRCMF_FW_TYPE_BINARY,
57+
BRCMF_FW_TYPE_NVRAM
58+
};
59+
60+
struct brcmf_fw_item {
61+
const char *path;
62+
enum brcmf_fw_type type;
63+
u16 flags;
64+
union {
65+
const struct firmware *binary;
66+
struct {
67+
void *data;
68+
u32 len;
69+
} nv_data;
70+
};
71+
};
72+
73+
struct brcmf_fw_request {
74+
u16 domain_nr;
75+
u16 bus_nr;
76+
u32 n_items;
77+
struct brcmf_fw_item items[0];
78+
};
79+
5780
/*
5881
* Request firmware(s) asynchronously. When the asynchronous request
5982
* fails it will not use the callback, but call device_release_driver()
6083
* instead which will call the driver .remove() callback.
6184
*/
62-
int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
63-
const char *code, const char *nvram,
64-
void (*fw_cb)(struct device *dev, int err,
65-
const struct firmware *fw,
66-
void *nvram_image, u32 nvram_len),
67-
u16 domain_nr, u16 bus_nr);
68-
int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
69-
const char *code, const char *nvram,
85+
int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
7086
void (*fw_cb)(struct device *dev, int err,
71-
const struct firmware *fw,
72-
void *nvram_image, u32 nvram_len));
87+
struct brcmf_fw_request *req));
7388

7489
#endif /* BRCMFMAC_FIRMWARE_H */

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

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,15 +1651,19 @@ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
16511651
.write32 = brcmf_pcie_buscore_write32,
16521652
};
16531653

1654+
#define BRCMF_PCIE_FW_CODE 0
1655+
#define BRCMF_PCIE_FW_NVRAM 1
1656+
16541657
static void brcmf_pcie_setup(struct device *dev, int ret,
1655-
const struct firmware *fw,
1656-
void *nvram, u32 nvram_len)
1658+
struct brcmf_fw_request *fwreq)
16571659
{
1660+
const struct firmware *fw;
1661+
void *nvram;
16581662
struct brcmf_bus *bus;
16591663
struct brcmf_pciedev *pcie_bus_dev;
16601664
struct brcmf_pciedev_info *devinfo;
16611665
struct brcmf_commonring **flowrings;
1662-
u32 i;
1666+
u32 i, nvram_len;
16631667

16641668
/* check firmware loading result */
16651669
if (ret)
@@ -1670,6 +1674,11 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
16701674
devinfo = pcie_bus_dev->devinfo;
16711675
brcmf_pcie_attach(devinfo);
16721676

1677+
fw = fwreq->items[BRCMF_PCIE_FW_CODE].binary;
1678+
nvram = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.data;
1679+
nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len;
1680+
kfree(fwreq);
1681+
16731682
/* Some of the firmwares have the size of the memory of the device
16741683
* defined inside the firmware. This is because part of the memory in
16751684
* the device is shared and the devision is determined by FW. Parse
@@ -1730,6 +1739,7 @@ static int
17301739
brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
17311740
{
17321741
int ret;
1742+
struct brcmf_fw_request *fwreq;
17331743
struct brcmf_pciedev_info *devinfo;
17341744
struct brcmf_pciedev *pcie_bus_dev;
17351745
struct brcmf_bus *bus;
@@ -1800,12 +1810,26 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
18001810
if (ret)
18011811
goto fail_bus;
18021812

1803-
ret = brcmf_fw_get_firmwares_pcie(bus->dev, BRCMF_FW_REQUEST_NVRAM |
1804-
BRCMF_FW_REQ_NV_OPTIONAL,
1805-
devinfo->fw_name, devinfo->nvram_name,
1806-
brcmf_pcie_setup, domain_nr, bus_nr);
1813+
fwreq = kzalloc(sizeof(*fwreq) + 2 * sizeof(struct brcmf_fw_item),
1814+
GFP_KERNEL);
1815+
if (!fwreq) {
1816+
ret = -ENOMEM;
1817+
goto fail_bus;
1818+
}
1819+
1820+
fwreq->items[BRCMF_PCIE_FW_CODE].path = devinfo->fw_name;
1821+
fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
1822+
fwreq->items[BRCMF_PCIE_FW_NVRAM].path = devinfo->nvram_name;
1823+
fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
1824+
fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
1825+
fwreq->n_items = 2;
1826+
fwreq->domain_nr = domain_nr;
1827+
fwreq->bus_nr = bus_nr;
1828+
ret = brcmf_fw_get_firmwares(bus->dev, fwreq, brcmf_pcie_setup);
18071829
if (ret == 0)
18081830
return 0;
1831+
1832+
kfree(fwreq);
18091833
fail_bus:
18101834
kfree(bus->msgbuf);
18111835
kfree(bus);

0 commit comments

Comments
 (0)