mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-16 04:13:31 +00:00
182 lines
6.6 KiB
Diff
182 lines
6.6 KiB
Diff
From 95500b48e476af858b0a3ae6c96d9fe8ab92cb61 Mon Sep 17 00:00:00 2001
|
|
From: Hector Martin <marcan@marcan.st>
|
|
Date: Fri, 7 Jan 2022 11:14:44 +0900
|
|
Subject: [PATCH 088/171] brcmfmac: firmware: Support passing in multiple
|
|
board_types
|
|
|
|
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>
|
|
---
|
|
.../broadcom/brcm80211/brcmfmac/firmware.c | 53 +++++++++++++++----
|
|
.../broadcom/brcm80211/brcmfmac/firmware.h | 4 +-
|
|
.../broadcom/brcm80211/brcmfmac/pcie.c | 4 +-
|
|
.../broadcom/brcm80211/brcmfmac/sdio.c | 2 +-
|
|
4 files changed, 49 insertions(+), 14 deletions(-)
|
|
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
|
index deacd39b3f7b..d04a59cf4a1e 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
|
@@ -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);
|
|
};
|
|
|
|
@@ -625,17 +626,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;
|
|
@@ -669,15 +674,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);
|
|
}
|
|
|
|
@@ -721,10 +751,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);
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
|
|
index e290dec9c53d..1266cbaee072 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
|
|
@@ -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
|
|
@@ -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[];
|
|
};
|
|
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
|
index ec73d2620ec9..2a74c9d8d46a 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
|
@@ -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;
|
|
}
|
|
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
|
index 27dc8ed29ac8..2b71991f7d9b 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
|
@@ -4433,7 +4433,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.34.1
|
|
|