[openwrt/openwrt] mac80211: read alternative brcm fw names from DT

LEDE Commits lede-commits at lists.infradead.org
Fri Jul 1 03:28:34 PDT 2022


stintel pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/a5526efde0c4a5c0a94fc2e7f6bcecd844148408

commit a5526efde0c4a5c0a94fc2e7f6bcecd844148408
Author: Stijn Tintel <stijn at linux-ipv6.be>
AuthorDate: Wed May 18 21:40:51 2022 +0300

    mac80211: read alternative brcm fw names from DT
    
    This patch is required for the Raspberry Pi Zero 2 W.
    
    Signed-off-by: Stijn Tintel <stijn at linux-ipv6.be>
---
 ...c-Read-alternative-firmware-names-from-DT.patch | 205 +++++++++++++++++++++
 1 file changed, 205 insertions(+)

diff --git a/package/kernel/mac80211/patches/brcm/865-brcmfmac-Read-alternative-firmware-names-from-DT.patch b/package/kernel/mac80211/patches/brcm/865-brcmfmac-Read-alternative-firmware-names-from-DT.patch
new file mode 100644
index 0000000000..6d9cfe7b14
--- /dev/null
+++ b/package/kernel/mac80211/patches/brcm/865-brcmfmac-Read-alternative-firmware-names-from-DT.patch
@@ -0,0 +1,205 @@
+From 4e32024cbb14230af3048e249e84f8c2b25ce45a Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil at raspberrypi.com>
+Date: Thu, 28 Oct 2021 15:03:16 +0100
+Subject: [PATCH] brcmfmac: Read alternative firmware names from DT
+
+Add the ability to load the names of alternative firmwares from the
+Device Tree node. This permits separate firmwares for 43436s and 43438
+and allows downstream firmwares to coexist with upstream.
+
+Signed-off-by: Phil Elwell <phil at raspberrypi.com>
+---
+ .../wireless/broadcom/brcm80211/brcmfmac/of.c | 36 ++++++++++++++
+ .../wireless/broadcom/brcm80211/brcmfmac/of.h |  7 +++
+ .../broadcom/brcm80211/brcmfmac/sdio.c        | 47 +++++++++++++++++--
+ 3 files changed, 87 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
+index 2f7bc3a70c65..c2d6b8a22858 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
+@@ -10,6 +10,7 @@
+ #include "debug.h"
+ #include "core.h"
+ #include "common.h"
++#include "firmware.h"
+ #include "of.h"
+ 
+ static int brcmf_of_get_country_codes(struct device *dev,
+@@ -118,3 +119,38 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
+ 	sdio->oob_irq_nr = irq;
+ 	sdio->oob_irq_flags = irqf;
+ }
++
++struct brcmf_firmware_mapping *
++brcmf_of_fwnames(struct device *dev, u32 *fwname_count)
++{
++	struct device_node *np = dev->of_node;
++	struct brcmf_firmware_mapping *fwnames;
++	struct device_node *map_np, *fw_np;
++	int of_count;
++	int count = 0;
++
++	map_np = of_get_child_by_name(np, "firmwares");
++	of_count = of_get_child_count(map_np);
++	if (!of_count)
++		return NULL;
++
++	fwnames = devm_kcalloc(dev, of_count,
++			       sizeof(struct brcmf_firmware_mapping),
++			       GFP_KERNEL);
++
++	for_each_child_of_node(map_np, fw_np)
++	{
++		struct brcmf_firmware_mapping *cur = &fwnames[count];
++
++		if (of_property_read_u32(fw_np, "chipid", &cur->chipid) ||
++		    of_property_read_u32(fw_np, "revmask", &cur->revmask))
++			continue;
++		cur->fw_base = of_get_property(fw_np, "fw_base", NULL);
++		if (cur->fw_base)
++			count++;
++	}
++
++	*fwname_count = count;
++
++	return count ? fwnames : NULL;
++}
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
+index 10bf52253337..5b39a39812d0 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
+@@ -5,9 +5,16 @@
+ #ifdef CONFIG_OF
+ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
+ 		    struct brcmf_mp_device *settings);
++struct brcmf_firmware_mapping *
++brcmf_of_fwnames(struct device *dev, u32 *map_count);
+ #else
+ static void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
+ 			   struct brcmf_mp_device *settings)
+ {
+ }
++static struct brcmf_firmware_mapping *
++brcmf_of_fwnames(struct device *dev, u32 *map_count)
++{
++	return NULL;
++}
+ #endif /* CONFIG_OF */
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+index 89de65d32ed5..88c08fee58f6 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -35,6 +35,7 @@
+ #include "core.h"
+ #include "common.h"
+ #include "bcdc.h"
++#include "of.h"
+ 
+ #define DCMD_RESP_TIMEOUT	msecs_to_jiffies(2500)
+ #define CTL_DONE_TIMEOUT	msecs_to_jiffies(2500)
+@@ -634,7 +635,7 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-sdio.*.txt");
+ /* per-board firmware binaries */
+ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-sdio.*.bin");
+ 
+-static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
++static const struct brcmf_firmware_mapping sdio_fwnames[] = {
+ 	BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
+ 	BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0),
+ 	BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x00000020, 43241B4),
+@@ -660,6 +661,9 @@ static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
+ 	BRCMF_FW_ENTRY(CY_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752)
+ };
+ 
++static const struct brcmf_firmware_mapping *brcmf_sdio_fwnames = sdio_fwnames;
++static u32 brcmf_sdio_fwnames_count = ARRAY_SIZE(sdio_fwnames);
++
+ #define TXCTL_CREDITS	2
+ 
+ static void pkt_align(struct sk_buff *p, int len, int align)
+@@ -4151,7 +4155,7 @@ int brcmf_sdio_get_fwname(struct device *dev, const char *ext, u8 *fw_name,
+ 	}
+ 	fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev,
+ 				       brcmf_sdio_fwnames,
+-				       ARRAY_SIZE(brcmf_sdio_fwnames),
++				       brcmf_sdio_fwnames_count,
+ 				       fwnames, ARRAY_SIZE(fwnames));
+ 	if (!fwreq)
+ 		return -ENOMEM;
+@@ -4207,6 +4211,9 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
+ #define BRCMF_SDIO_FW_CODE	0
+ #define BRCMF_SDIO_FW_NVRAM	1
+ 
++static struct brcmf_fw_request *
++brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus);
++
+ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
+ 					 struct brcmf_fw_request *fwreq)
+ {
+@@ -4222,6 +4229,22 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
+ 
+ 	brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
+ 
++	if (err && brcmf_sdio_fwnames != sdio_fwnames) {
++		/* Try again with the standard firmware names */
++		brcmf_sdio_fwnames = sdio_fwnames;
++		brcmf_sdio_fwnames_count = ARRAY_SIZE(sdio_fwnames);
++		kfree(fwreq);
++		fwreq = brcmf_sdio_prepare_fw_request(bus);
++		if (!fwreq) {
++			err = -ENOMEM;
++			goto fail;
++		}
++		err = brcmf_fw_get_firmwares(dev, fwreq,
++					     brcmf_sdio_firmware_callback);
++		if (!err)
++			return;
++	}
++
+ 	if (err)
+ 		goto fail;
+ 
+@@ -4430,7 +4453,7 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
+ 
+ 	fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev,
+ 				       brcmf_sdio_fwnames,
+-				       ARRAY_SIZE(brcmf_sdio_fwnames),
++				       brcmf_sdio_fwnames_count,
+ 				       fwnames, ARRAY_SIZE(fwnames));
+ 	if (!fwreq)
+ 		return NULL;
+@@ -4448,6 +4471,9 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
+ 	struct brcmf_sdio *bus;
+ 	struct workqueue_struct *wq;
+ 	struct brcmf_fw_request *fwreq;
++	struct brcmf_firmware_mapping *of_fwnames, *fwnames = NULL;
++	const int fwname_size = sizeof(struct brcmf_firmware_mapping);
++	u32 of_fw_count;
+ 
+ 	brcmf_dbg(TRACE, "Enter\n");
+ 
+@@ -4530,6 +4556,21 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
+ 
+ 	brcmf_dbg(INFO, "completed!!\n");
+ 
++	of_fwnames = brcmf_of_fwnames(sdiodev->dev, &of_fw_count);
++	if (of_fwnames)
++		fwnames = devm_kcalloc(sdiodev->dev,
++				       of_fw_count + brcmf_sdio_fwnames_count,
++				       fwname_size, GFP_KERNEL);
++
++	if (fwnames) {
++		/* The array is scanned in order, so overrides come first */
++		memcpy(fwnames, of_fwnames, of_fw_count * fwname_size);
++		memcpy(fwnames + of_fw_count, sdio_fwnames,
++		       brcmf_sdio_fwnames_count * fwname_size);
++		brcmf_sdio_fwnames = fwnames;
++		brcmf_sdio_fwnames_count += of_fw_count;
++	}
++
+ 	fwreq = brcmf_sdio_prepare_fw_request(bus);
+ 	if (!fwreq) {
+ 		ret = -ENOMEM;
+-- 
+2.30.2
+




More information about the lede-commits mailing list