Skip to content

Commit

Permalink
wifi: brcmfmac: firmware: Support passing in multiple board_types
Browse files Browse the repository at this point in the history
Apple platforms have firmware and config files identified with multiple
dimensions. We want to be able to find the most specific firmware
available for any given platform, progressively trying more general
firmwares.

To do this, first add support for passing in multiple board_types,
which will be tried in sequence.

Since this will cause more log spam due to missing firmwares, also
switch the secondary firmware fecthes to use the _nowarn variant, which
will not log if the firmware is not found.

Signed-off-by: Hector Martin <marcan@marcan.st>
Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/E1oZDnd-0077aG-Dk@rmk-PC.armlinux.org.uk
  • Loading branch information
Hector Martin authored and Kalle Valo committed Sep 19, 2022
1 parent a1b5a90 commit 7cb46e7
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 14 deletions.
53 changes: 42 additions & 11 deletions drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ struct brcmf_fw {
struct device *dev;
struct brcmf_fw_request *req;
u32 curpos;
unsigned int board_index;
void (*done)(struct device *dev, int err, struct brcmf_fw_request *req);
};

Expand Down Expand Up @@ -616,17 +617,21 @@ static int brcmf_fw_request_firmware(const struct firmware **fw,
struct brcmf_fw *fwctx)
{
struct brcmf_fw_item *cur = &fwctx->req->items[fwctx->curpos];
unsigned int i;
int ret;

/* Files can be board-specific, first try a board-specific path */
if (fwctx->req->board_type) {
/* Files can be board-specific, first try board-specific paths */
for (i = 0; i < ARRAY_SIZE(fwctx->req->board_types); i++) {
char *alt_path;

alt_path = brcm_alt_fw_path(cur->path, fwctx->req->board_type);
if (!fwctx->req->board_types[i])
goto fallback;
alt_path = brcm_alt_fw_path(cur->path,
fwctx->req->board_types[i]);
if (!alt_path)
goto fallback;

ret = request_firmware(fw, alt_path, fwctx->dev);
ret = firmware_request_nowarn(fw, alt_path, fwctx->dev);
kfree(alt_path);
if (ret == 0)
return ret;
Expand Down Expand Up @@ -660,15 +665,40 @@ static void brcmf_fw_request_done_alt_path(const struct firmware *fw, void *ctx)
{
struct brcmf_fw *fwctx = ctx;
struct brcmf_fw_item *first = &fwctx->req->items[0];
const char *board_type, *alt_path;
int ret = 0;

/* Fall back to canonical path if board firmware not found */
if (!fw)
ret = request_firmware_nowait(THIS_MODULE, true, first->path,
if (fw) {
brcmf_fw_request_done(fw, ctx);
return;
}

/* Try next board firmware */
if (fwctx->board_index < ARRAY_SIZE(fwctx->req->board_types)) {
board_type = fwctx->req->board_types[fwctx->board_index++];
if (!board_type)
goto fallback;
alt_path = brcm_alt_fw_path(first->path, board_type);
if (!alt_path)
goto fallback;

ret = request_firmware_nowait(THIS_MODULE, true, alt_path,
fwctx->dev, GFP_KERNEL, fwctx,
brcmf_fw_request_done);
brcmf_fw_request_done_alt_path);
kfree(alt_path);

if (fw || ret < 0)
if (ret < 0)
brcmf_fw_request_done(fw, ctx);
return;
}

fallback:
/* Fall back to canonical path if board firmware not found */
ret = request_firmware_nowait(THIS_MODULE, true, first->path,
fwctx->dev, GFP_KERNEL, fwctx,
brcmf_fw_request_done);

if (ret < 0)
brcmf_fw_request_done(fw, ctx);
}

Expand Down Expand Up @@ -712,10 +742,11 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
fwctx->done = fw_cb;

/* First try alternative board-specific path if any */
if (fwctx->req->board_type)
if (fwctx->req->board_types[0])
alt_path = brcm_alt_fw_path(first->path,
fwctx->req->board_type);
fwctx->req->board_types[0]);
if (alt_path) {
fwctx->board_index++;
ret = request_firmware_nowait(THIS_MODULE, true, alt_path,
fwctx->dev, GFP_KERNEL, fwctx,
brcmf_fw_request_done_alt_path);
Expand Down
4 changes: 3 additions & 1 deletion drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

#define BRCMF_FW_DEFAULT_PATH "brcm/"

#define BRCMF_FW_MAX_BOARD_TYPES 8

/**
* struct brcmf_firmware_mapping - Used to map chipid/revmask to firmware
* filename and nvram filename. Each bus type implementation should create
Expand Down Expand Up @@ -66,7 +68,7 @@ struct brcmf_fw_request {
u16 domain_nr;
u16 bus_nr;
u32 n_items;
const char *board_type;
const char *board_types[BRCMF_FW_MAX_BOARD_TYPES];
struct brcmf_fw_item items[];
};

Expand Down
4 changes: 3 additions & 1 deletion drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
Original file line number Diff line number Diff line change
Expand Up @@ -1852,11 +1852,13 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
fwreq->items[BRCMF_PCIE_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
fwreq->items[BRCMF_PCIE_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL;
fwreq->board_type = devinfo->settings->board_type;
/* NVRAM reserves PCI domain 0 for Broadcom's SDK faked bus */
fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1;
fwreq->bus_nr = devinfo->pdev->bus->number;

brcmf_dbg(PCIE, "Board: %s\n", devinfo->settings->board_type);
fwreq->board_types[0] = devinfo->settings->board_type;

return fwreq;
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -4426,7 +4426,7 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
fwreq->items[BRCMF_SDIO_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
fwreq->items[BRCMF_SDIO_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL;
fwreq->board_type = bus->sdiodev->settings->board_type;
fwreq->board_types[0] = bus->sdiodev->settings->board_type;

return fwreq;
}
Expand Down

0 comments on commit 7cb46e7

Please sign in to comment.