In order to make use of the multiple alt_path functionality, change board_type to an array. Bus drivers can pass in a NULL-terminated list of board type strings to try for the firmware fetch. Acked-by: Linus Walleij <linus.walleij@xxxxxxxxxx> Signed-off-by: Hector Martin <marcan@xxxxxxxxx> --- .../broadcom/brcm80211/brcmfmac/firmware.c | 35 ++++++++++++------- .../broadcom/brcm80211/brcmfmac/firmware.h | 2 +- .../broadcom/brcm80211/brcmfmac/pcie.c | 4 ++- .../broadcom/brcm80211/brcmfmac/sdio.c | 2 +- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c index 7570dbf22cdd..054ea3ed133e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -594,28 +594,39 @@ static int brcmf_fw_complete_request(const struct firmware *fw, return (cur->flags & BRCMF_FW_REQF_OPTIONAL) ? 0 : ret; } -static int brcm_alt_fw_paths(const char *path, const char *board_type, +static int brcm_alt_fw_paths(const char *path, struct brcmf_fw *fwctx, const char *alt_paths[BRCMF_FW_MAX_ALT_PATHS]) { + const char **board_types = fwctx->req->board_types; + unsigned int i; char alt_path[BRCMF_FW_NAME_LEN]; const char *suffix; memset(alt_paths, 0, array_size(sizeof(*alt_paths), BRCMF_FW_MAX_ALT_PATHS)); + if (!board_types[0]) + return -ENOENT; + suffix = strrchr(path, '.'); if (!suffix || suffix == path) return -EINVAL; - /* strip extension at the end */ - strscpy(alt_path, path, BRCMF_FW_NAME_LEN); - alt_path[suffix - path] = 0; + for (i = 0; i < BRCMF_FW_MAX_ALT_PATHS; i++) { + if (!board_types[i]) + break; - strlcat(alt_path, ".", BRCMF_FW_NAME_LEN); - strlcat(alt_path, board_type, BRCMF_FW_NAME_LEN); - strlcat(alt_path, suffix, BRCMF_FW_NAME_LEN); + /* strip extension at the end */ + strscpy(alt_path, path, BRCMF_FW_NAME_LEN); + alt_path[suffix - path] = 0; - alt_paths[0] = kstrdup(alt_path, GFP_KERNEL); + strlcat(alt_path, ".", BRCMF_FW_NAME_LEN); + strlcat(alt_path, board_types[i], BRCMF_FW_NAME_LEN); + strlcat(alt_path, suffix, BRCMF_FW_NAME_LEN); + + alt_paths[i] = kstrdup(alt_path, GFP_KERNEL); + brcmf_dbg(TRACE, "FW alt path: %s\n", alt_paths[i]); + } return 0; } @@ -637,11 +648,10 @@ static int brcmf_fw_request_firmware(const struct firmware **fw, unsigned int i; /* Files can be board-specific, first try a board-specific path */ - if (fwctx->req->board_type) { + if (fwctx->req->board_types[0]) { const char *alt_paths[BRCMF_FW_MAX_ALT_PATHS]; - if (brcm_alt_fw_paths(cur->path, fwctx->req->board_type, - alt_paths) != 0) + if (brcm_alt_fw_paths(cur->path, fwctx, alt_paths) != 0) goto fallback; for (i = 0; i < BRCMF_FW_MAX_ALT_PATHS && alt_paths[i]; i++) { @@ -750,8 +760,7 @@ 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 (brcm_alt_fw_paths(first->path, req->board_type, - fwctx->alt_paths) == 0) { + if (brcm_alt_fw_paths(first->path, fwctx, fwctx->alt_paths) == 0) { fwctx->alt_index = 0; ret = request_firmware_nowait(THIS_MODULE, true, fwctx->alt_paths[0], diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h index 7f4e6e359c82..3b60a0e290b0 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h @@ -68,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_ALT_PATHS]; struct brcmf_fw_item items[]; }; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 591f870d1e47..a52a6f8081eb 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -1877,11 +1877,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; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 7466e6fd6eca..ed944764f6ea 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -4432,7 +4432,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; } -- 2.33.0