From: Hector Martin <hidden> Date: 2021-12-26 15:36:41
Hi everyone,
Merry Christmas! This year Santa brings us a 34-patch series to add
proper support for the Broadcom FullMAC chips used on Apple T2 and M1
platforms:
- BCM4355C1
- BCM4364B2/B3
- BCM4377B3
- BCM4378B1
- BCM4387C2
As usual for Apple, things are ever so slightly different on these
machines from every other Broadcom platform. In particular, besides
the normal device/firmware support changes, a large fraction of this
series deals with selecting and loading the correct firmware. These
platforms use multiple dimensions for firmware selection, and the values
for these dimensions are variously sourced from DT or OTP (see the
commit message for #9 for the gory details).
This is what is included:
# 01: DT bindings (M1 platforms)
On M1 platforms, we use the device tree to provide properties for PCIe
devices like these cards. This patch re-uses the existing SDIO binding
and adds the compatibles for these PCIe chips, plus the properties we
need to correctly instantiate them:
- apple,module-instance: A codename (seemingly always an island) that
identifies the specific platform/board. brcmfmac normally uses the
root node compatible for this on DT platforms, but Apple have their
own mapping/identifier here. This is prepended with `apple,` and
becomes the base board_name for firmware selection. An alternative
here might be to use something like brcm,board-name with the
`apple,`-prefixed value instead, which would be more general and allow
any DT platform to override the desired board name used when building
firmware filenames.
- apple,antenna-sku: Specifies the specific antenna configuration in a
produt. This would normally be filled in by the bootloader from
device-specific configuration data. On ACPI platforms, this is
provided via ACPI instead. This is used to build the funky Apple
firmware filenames. Note: it seems the antenna doesn't actually matter
for any of the above platforms (they are all aliases to the same files
and our firmware copier collapses down this dimension), but since
Apple do support having different firmware or NVRAM depending on
antenna SKU, we ough to support it in case it starts mattering on a
future platform.
- brcm,cal-blob: A calibration blob for the Wi-Fi module, specific to a
given unit. On most platforms, this is stored in SROM on the module,
and does not need to be provided externally, but Apple instead stores
this in platform configuration for M1 machines and the driver needs to
upload it to the device after initializing the firmware. This has a
generic brcm name, since a priori this mechanism shouldn't be
Apple-specific, although chances are only Apple do it like this so far.
# 02~09: Apple firmware selection (M1 platforms)
These patches add support for choosing firmwares (binaries, CLM blobs,
and NVRAM configs alike) using all the dimensions that Apple uses. The
firmware files are renamed to conform to the existing brcmfmac
convention. See the commit message for #9 for the gory details as to how
these filenames are constructed. The data to make the firmware selection
comes from the above DT properties and from an OTP ROM on the chips on
M1 platforms.
# 10~14: BCM4378 support (M1 T8103 platforms)
These patches make changes required to support the BCM4378 chip present
in Apple M1 (T8103) platforms. This includes adding support for passing
in the MAC address via the DT (this is standard on DT platforms) since
the chip does not have a burned-in MAC; adding support for PCIe core
revs >64 (which moved around some registers); tweaking ring buffer
sizes; and fixing a bug.
# 15~20: BCM4355/4364/4377 support (T2 platforms)
These patches add support for the chips found across T2 Mac platforms.
This includes ACPI support for fetching properties instead of using DT,
providing a buffer of entropy to the devices (required for some of the
firmwares), and adding the required IDs. This also fixes the BCM4364
firmware naming; it was added without consideration that there are two
incompatible chip revisions. To avoid this ambiguity in the future, all
the chips added by this series use firmware names ending in the revision
(apple/brcm style, that is letter+number), so that future revisions can
be added without creating confusion.
# 21~27: BCM4387 support (M1 Pro/Max T600x platforms)
These patches add support for the newer BCM4387 present in the recently
launched M1 Pro/Max platforms. This chip requires a few changes to D11
reset behavior and TCM size calculation to work properly, and it uses
newer firmware which needs support for newer firmware interfaces
in the cfg80211 support. Backwards compatibility is maintained via
feature flags discovered at runtime from information provided by the
firmware.
A note on #26: it seems this chip broke the old hack of passing the PMK
in hexdump form as a PSK, but it seems brcmfmac chips supported passing
it in binary all along. I'm not sure why it was done this way in the
Linux driver, but it seems OpenBSD always did it in binary and works
with older chips, so this should be reasonably well tested. Any further
insight as to why this was done this way would be appreciated.
# 28~31: Fixes
These are just random things I came across while developing this series.
#31 is required to avoid a compile warning in subsequent patches. None
of these are strictly required to support these chips/platforms.
# 32-34: TxCap and calibration blobs
These patches add support for uploading TxCap blobs, which are another
kind of firmware blob that Apple platforms use (T2 and M1), as well as
providing Wi-Fi calibration data from the device tree (M1).
I'm not sure what the TxCap blobs do. Given the stray function
prototype at [5], it would seem the Broadcom folks in charge of Linux
drivers also know all about Apple's fancy OTP for firmware selection
and the existence of TxCap blobs, so it would be great if you could
share any insight here ;-)
These patches are not required for the chips to function, but presumably
having proper per-device calibration data available matters, and I
assume the TxCap blobs aren't just for show either.
# On firmware
As you might expect, the firmware for these machines is not available
under a redistributable license; however, every owner of one of these
machines *is* implicitly licensed to posess the firmware, and the OS
packages containing it are available under well-known URLs on Apple's
CDN with no authentication.
Our plan to support this is to propose a platform firmware mechanism,
where platforms can provide a firmware package in the EFI system
partition along with a manifest, and distros will extract it to
/lib/firmware on boot or otherwise make it available to the kernel.
Then, on M1 platforms, our install script, which performs all the
bootloader installation steps required to run Linux on these machines in
the first place, will also take care of copying the firmware from the
base macOS image to the EFI partition. On T2 platforms, we'll provide an
analogous script that users can manually run prior to a normal EFI Linux
installation to just grab the firmware from /usr/share/firmware/wifi in
the running macOS.
There is an example firmware manifest at [1] which details the files
copied by our firmware rename script [2], as of macOS 12.0.1.
To test this series on a supported Mac today (T2 or M1), boot into macOS
and run:
$ git clone https://github.com/AsahiLinux/asahi-installer
$ cd asahi-installer/src
$ python -m firmware.wifi /usr/share/firmware/wifi firmware.tar
Then copy firmware.tar to Linux and extract it into /lib/firmware.
# Acknowledgements
This patch series was developed referencing the OpenBSD support for the
BCM4378 [3] and the bcmdhd-4359 GPL release [4], which contained some
interesting tidbits about newer chips, registers, OTP, etc.
[1] https://gist.github.com/marcan/5cfaad948e224279f09a4a79ccafd9b6
[2] https://github.com/AsahiLinux/asahi-installer/blob/main/src/firmware/wifi.py
[3] https://github.com/openbsd/src/blob/master/sys/dev/pci/if_bwfm_pci.c
[4] https://github.com/StreamUnlimited/broadcom-bcmdhd-4359/
[5] https://github.com/StreamUnlimited/broadcom-bcmdhd-4359/blob/master/dhd_pcie.h#L594
Hector Martin (34):
dt-bindings: net: bcm4329-fmac: Add Apple properties & chips
brcmfmac: pcie: Declare missing firmware files in pcie.c
brcmfmac: firmware: Support having multiple alt paths
brcmfmac: firmware: Handle per-board clm_blob files
brcmfmac: pcie/sdio/usb: Get CLM blob via standard firmware mechanism
brcmfmac: firmware: Support passing in multiple board_types
brcmfmac: pcie: Read Apple OTP information
brcmfmac: of: Fetch Apple properties
brcmfmac: pcie: Perform firmware selection for Apple platforms
brcmfmac: firmware: Allow platform to override macaddr
brcmfmac: msgbuf: Increase RX ring sizes to 1024
brcmfmac: pcie: Fix crashes due to early IRQs
brcmfmac: pcie: Support PCIe core revisions >= 64
brcmfmac: pcie: Add IDs/properties for BCM4378
ACPI / property: Support strings in Apple _DSM props
brcmfmac: acpi: Add support for fetching Apple ACPI properties
brcmfmac: pcie: Provide a buffer of random bytes to the device
brcmfmac: pcie: Add IDs/properties for BCM4355
brcmfmac: pcie: Add IDs/properties for BCM4377
brcmfmac: pcie: Perform correct BCM4364 firmware selection
brcmfmac: chip: Only disable D11 cores; handle an arbitrary number
brcmfmac: chip: Handle 1024-unit sizes for TCM blocks
brcmfmac: cfg80211: Add support for scan params v2
brcmfmac: feature: Add support for setting feats based on WLC version
brcmfmac: cfg80211: Add support for PMKID_V3 operations
brcmfmac: cfg80211: Pass the PMK in binary instead of hex
brcmfmac: pcie: Add IDs/properties for BCM4387
brcmfmac: pcie: Replace brcmf_pcie_copy_mem_todev with memcpy_toio
brcmfmac: pcie: Read the console on init and shutdown
brcmfmac: pcie: Release firmwares in the brcmf_pcie_setup error path
brcmfmac: fwil: Constify iovar name arguments
brcmfmac: common: Add support for downloading TxCap blobs
brcmfmac: pcie: Load and provide TxCap blobs
brcmfmac: common: Add support for external calibration blobs
.../net/wireless/brcm,bcm4329-fmac.yaml | 32 +-
drivers/acpi/x86/apple.c | 11 +-
.../broadcom/brcm80211/brcmfmac/Makefile | 2 +
.../broadcom/brcm80211/brcmfmac/acpi.c | 51 ++
.../broadcom/brcm80211/brcmfmac/bus.h | 20 +-
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 175 ++++-
.../broadcom/brcm80211/brcmfmac/chip.c | 36 +-
.../broadcom/brcm80211/brcmfmac/common.c | 130 +++-
.../broadcom/brcm80211/brcmfmac/common.h | 12 +
.../broadcom/brcm80211/brcmfmac/feature.c | 49 ++
.../broadcom/brcm80211/brcmfmac/feature.h | 6 +-
.../broadcom/brcm80211/brcmfmac/firmware.c | 140 +++-
.../broadcom/brcm80211/brcmfmac/firmware.h | 2 +-
.../broadcom/brcm80211/brcmfmac/fwil.c | 34 +-
.../broadcom/brcm80211/brcmfmac/fwil.h | 28 +-
.../broadcom/brcm80211/brcmfmac/fwil_types.h | 157 ++++-
.../broadcom/brcm80211/brcmfmac/msgbuf.h | 4 +-
.../wireless/broadcom/brcm80211/brcmfmac/of.c | 27 +-
.../broadcom/brcm80211/brcmfmac/pcie.c | 606 +++++++++++++++---
.../broadcom/brcm80211/brcmfmac/sdio.c | 41 +-
.../broadcom/brcm80211/brcmfmac/sdio.h | 2 +
.../broadcom/brcm80211/brcmfmac/usb.c | 23 +-
.../broadcom/brcm80211/include/brcm_hw_ids.h | 8 +
include/linux/bcma/bcma_driver_chipcommon.h | 1 +
24 files changed, 1327 insertions(+), 270 deletions(-)
create mode 100644 drivers/net/wireless/broadcom/brcm80211/brcmfmac/acpi.c
--
2.33.0
From: Hector Martin <hidden> Date: 2021-12-26 15:36:55
This binding is currently used for SDIO devices, but these chips are
also used as PCIe devices on DT platforms and may be represented in the
DT. Re-use the existing binding and add chip compatibles used by Apple
T2 and M1 platforms (the T2 ones are not known to be used in DT
platforms, but we might as well document them).
Then, add properties required for firmware selection and calibration on
M1 machines.
Signed-off-by: Hector Martin <redacted>
---
.../net/wireless/brcm,bcm4329-fmac.yaml | 32 +++++++++++++++++--
1 file changed, 29 insertions(+), 3 deletions(-)
@@ -4,7 +4,7 @@$id:http://devicetree.org/schemas/net/wireless/brcm,bcm4329-fmac.yaml#$schema:http://devicetree.org/meta-schemas/core.yaml#-title:Broadcom BCM4329 family fullmac wireless SDIO devices+title:Broadcom BCM4329 family fullmac wireless SDIO/PCIE devicesmaintainers:-Arend van Spriel <arend@broadcom.com>
@@ -36,16 +36,22 @@ properties:-brcm,bcm43455-fmac-brcm,bcm43456-fmac-brcm,bcm4354-fmac+-brcm,bcm4355c1-fmac-brcm,bcm4356-fmac-brcm,bcm4359-fmac+-brcm,bcm4364b2-fmac+-brcm,bcm4364b3-fmac+-brcm,bcm4377b3-fmac+-brcm,bcm4378b1-fmac+-brcm,bcm4387c2-fmac-cypress,cyw4373-fmac-cypress,cyw43012-fmac-const:brcm,bcm4329-fmac-const:brcm,bcm4329-fmacreg:-description:SDIO function number for the device, for most cases-this will be 1.+description:SDIO function number for the device (for most cases+this will be 1) or PCI device identifier.interrupts:maxItems:1
@@ -75,6 +81,26 @@ properties:items:pattern:'^[A-Z][A-Z]-[A-Z][0-9A-Z]-[0-9]+$'+brcm,cal-blob:+$ref:/schemas/types.yaml#/definitions/uint8-array+description:A per-device calibration blob for the Wi-Fi radio. This+should be filled in by the bootloader from platform configuration+data, if necessary, and will be uploaded to the device if present.++apple,module-instance:+$ref:/schemas/types.yaml#/definitions/string+description:Module codename used to identify a specific board on+Apple platforms. This is used to build the firmware filenames, to allow+different platforms to have different firmware and/or NVRAM config.++apple,antenna-sku:+$def:/schemas/types.yaml#/definitions/string+description:Antenna SKU used to identify a specific antenna configuration+on Apple platforms. This is use to build firmware filenames, to allow+platforms with different antenna configs to have different firmware and/or+NVRAM. This would normally be filled in by the bootloader from platform+configuration data.+required:-compatible-reg
From: Hector Martin <hidden> Date: 2021-12-26 15:37:02
Move one of the declarations from sdio.c to pcie.c, since it makes no
sense in the former (SDIO support is optional), and add missing ones.
Signed-off-by: Hector Martin <redacted>
Fixes: 75729e110e68 ("brcmfmac: expose firmware config files through modinfo")
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 7 +++++++
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 1 -
2 files changed, 7 insertions(+), 1 deletion(-)
From: Hector Martin <hidden> Date: 2021-12-26 15:37:07
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.
First, add support for having multiple alternate firmware paths.
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/firmware.c | 73 ++++++++++++++-----
1 file changed, 55 insertions(+), 18 deletions(-)
@@ -662,13 +687,26 @@ static void brcmf_fw_request_done_alt_path(const struct firmware *fw, void *ctx)structbrcmf_fw_item*first=&fwctx->req->items[0];intret=0;-/* Fall back to canonical path if board firmware not found */-if(!fw)+if(fw){+brcmf_fw_request_done(fw,ctx);+return;+}++fwctx->alt_index++;+if(fwctx->alt_paths[fwctx->alt_index]){+/* Try the next alt firmware */+ret=request_firmware_nowait(THIS_MODULE,true,+fwctx->alt_paths[fwctx->alt_index],+fwctx->dev,GFP_KERNEL,fwctx,+brcmf_fw_request_done_alt_path);+}else{+/* 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(fw||ret<0)+if(ret<0)brcmf_fw_request_done(fw,ctx);}
@@ -712,12 +749,12 @@ 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 */-alt_path=brcm_alt_fw_path(first->path,fwctx->req->board_type);-if(alt_path){-ret=request_firmware_nowait(THIS_MODULE,true,alt_path,+fwctx->alt_paths=brcm_alt_fw_paths(first->path,fwctx);+if(fwctx->alt_paths){+fwctx->alt_index=0;+ret=request_firmware_nowait(THIS_MODULE,true,fwctx->alt_paths[0],fwctx->dev,GFP_KERNEL,fwctx,brcmf_fw_request_done_alt_path);-kfree(alt_path);}else{ret=request_firmware_nowait(THIS_MODULE,true,first->path,fwctx->dev,GFP_KERNEL,fwctx,
From: Hector Martin <hidden> Date: 2021-12-26 15:37:18
Teach brcm_alt_fw_paths to correctly split off variable length
extensions, and enable alt firmware lookups for the CLM blob firmware
requests.
Apple platforms have per-board CLM blob files.
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/firmware.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
@@ -598,16 +598,16 @@ static const char **brcm_alt_fw_paths(const char *path, const char *board_type){charalt_path[BRCMF_FW_NAME_LEN];char**alt_paths;-charsuffix[5];+constchar*suffix;-strscpy(alt_path,path,BRCMF_FW_NAME_LEN);-/* At least one character + suffix */-if(strlen(alt_path)<5)+suffix=strrchr(path,'.');+if(!suffix||suffix==path)returnNULL;-/* strip .txt or .bin at the end */-strscpy(suffix,alt_path+strlen(alt_path)-4,5);-alt_path[strlen(alt_path)-4]=0;+/* strip extension at the end */+strscpy(alt_path,path,BRCMF_FW_NAME_LEN);+alt_path[suffix-path]=0;+strlcat(alt_path,".",BRCMF_FW_NAME_LEN);strlcat(alt_path,board_type,BRCMF_FW_NAME_LEN);strlcat(alt_path,suffix,BRCMF_FW_NAME_LEN);
@@ -638,7 +638,7 @@ static int brcmf_fw_request_firmware(const struct firmware **fw,intret,i;/* Files can be board-specific, first try a board-specific path */-if(cur->type==BRCMF_FW_TYPE_NVRAM&&fwctx->req->board_type){+if(fwctx->req->board_type){constchar**alt_paths=brcm_alt_fw_paths(cur->path,fwctx);if(!alt_paths)
From: Hector Martin <hidden> Date: 2021-12-26 15:37:29
Now that the firmware fetcher can handle per-board CLM files, load the
CLM blob alongside the other firmware files and change the bus API to
just return the existing blob, instead of fetching the filename.
This enables per-board CLM blobs, which are required on Apple platforms.
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/bus.h | 19 ++++++---
.../broadcom/brcm80211/brcmfmac/common.c | 12 +-----
.../broadcom/brcm80211/brcmfmac/pcie.c | 39 ++++++++++++-------
.../broadcom/brcm80211/brcmfmac/sdio.c | 36 ++++++++++-------
.../broadcom/brcm80211/brcmfmac/sdio.h | 2 +
.../broadcom/brcm80211/brcmfmac/usb.c | 23 +++--------
6 files changed, 69 insertions(+), 62 deletions(-)
@@ -7,6 +7,8 @@#define BRCMFMAC_BUS_H#include"debug.h"+#include<linux/kernel.h>+#include<linux/firmware.h>/* IDs of the 6 default common rings of msgbuf protocol */#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT 0
@@ -34,6 +36,11 @@ enum brcmf_bus_protocol_type {BRCMF_PROTO_MSGBUF};+/* Firmware blobs that may be available */+enumbrcmf_blob_type{+BRCMF_BLOB_CLM,+};+structbrcmf_mp_device;structbrcmf_bus_dcmd{
@@ -123,7 +123,6 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)structbrcmf_bus*bus=drvr->bus_if;structbrcmf_dload_data_le*chunk_buf;conststructfirmware*clm=NULL;-u8clm_name[BRCMF_FW_NAME_LEN];u32chunk_len;u32datalen;u32cumulative_len;
@@ -133,15 +132,8 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)brcmf_dbg(TRACE,"Enter\n");-memset(clm_name,0,sizeof(clm_name));-err=brcmf_bus_get_fwname(bus,".clm_blob",clm_name);-if(err){-bphy_err(drvr,"get CLM blob file name failed (%d)\n",err);-returnerr;-}--err=firmware_request_nowarn(&clm,clm_name,bus->dev);-if(err){+err=brcmf_bus_get_blob(bus,&clm,BRCMF_BLOB_CLM);+if(err||!clm){brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",err);return0;
@@ -4217,6 +4219,7 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,code=fwreq->items[BRCMF_SDIO_FW_CODE].binary;nvram=fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.data;nvram_len=fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.len;+sdiod->clm_fw=fwreq->items[BRCMF_SDIO_FW_CLM].binary;kfree(fwreq);/* try to download image and nvram to the dongle */
@@ -1154,24 +1154,11 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,returnNULL;}-static-intbrcmf_usb_get_fwname(structdevice*dev,constchar*ext,u8*fw_name)+staticintbrcmf_usb_get_blob(structdevice*dev,conststructfirmware**fw,+enumbrcmf_blob_typetype){-structbrcmf_bus*bus=dev_get_drvdata(dev);-structbrcmf_fw_request*fwreq;-structbrcmf_fw_namefwnames[]={-{ext,fw_name},-};--fwreq=brcmf_fw_alloc_request(bus->chip,bus->chiprev,-brcmf_usb_fwnames,-ARRAY_SIZE(brcmf_usb_fwnames),-fwnames,ARRAY_SIZE(fwnames));-if(!fwreq)-return-ENOMEM;--kfree(fwreq);-return0;+/* No blobs for USB devices... */+return-ENOENT;}staticconststructbrcmf_bus_opsbrcmf_usb_bus_ops={
From: Hector Martin <hidden> Date: 2021-12-26 15:37:30
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.
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/firmware.c | 35 +++++++++++++------
.../broadcom/brcm80211/brcmfmac/firmware.h | 2 +-
.../broadcom/brcm80211/brcmfmac/pcie.c | 7 +++-
.../broadcom/brcm80211/brcmfmac/sdio.c | 4 ++-
4 files changed, 35 insertions(+), 13 deletions(-)
@@ -594,26 +594,41 @@ static int brcmf_fw_complete_request(const struct firmware *fw,return(cur->flags&BRCMF_FW_REQF_OPTIONAL)?0:ret;}-staticconstchar**brcm_alt_fw_paths(constchar*path,constchar*board_type)+staticconstchar**brcm_alt_fw_paths(constchar*path,structbrcmf_fw*fwctx){+constchar**board_types=fwctx->req->board_types;+intboard_type_count=0;+inti;charalt_path[BRCMF_FW_NAME_LEN];char**alt_paths;constchar*suffix;+if(!board_types||!board_types[0])+returnNULL;++while(*board_types++)+board_type_count++;+suffix=strrchr(path,'.');if(!suffix||suffix==path)returnNULL;-/* strip extension at the end */-strscpy(alt_path,path,BRCMF_FW_NAME_LEN);-alt_path[suffix-path]=0;+alt_paths=kzalloc(sizeof(char*)*(board_type_count+1),+GFP_KERNEL);++board_types=fwctx->req->board_types;+for(i=0;i<board_type_count;i++){+/* strip extension at the end */+strscpy(alt_path,path,BRCMF_FW_NAME_LEN);+alt_path[suffix-path]=0;-strlcat(alt_path,".",BRCMF_FW_NAME_LEN);-strlcat(alt_path,board_type,BRCMF_FW_NAME_LEN);-strlcat(alt_path,suffix,BRCMF_FW_NAME_LEN);+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=kzalloc(sizeof(char*)*2,GFP_KERNEL);-alt_paths[0]=kstrdup(alt_path,GFP_KERNEL);+alt_paths[i]=kstrdup(alt_path,GFP_KERNEL);+brcmf_dbg(TRACE,"FW alt path: %s\n",alt_paths[i]);+}return(constchar**)alt_paths;}
@@ -638,7 +653,7 @@ static int brcmf_fw_request_firmware(const struct firmware **fw,intret,i;/* Files can be board-specific, first try a board-specific path */-if(fwctx->req->board_type){+if(fwctx->req->board_types){constchar**alt_paths=brcm_alt_fw_paths(cur->path,fwctx);if(!alt_paths)
From: Hector Martin <hidden> Date: 2021-12-26 15:37:45
On Apple platforms, the One Time Programmable ROM in the Broadcom chips
contains information about the specific board design (module, vendor,
version) that is required to select the correct NVRAM file. Parse this
OTP ROM and extract the required strings.
Note that the user OTP offset/size is per-chip. This patch does not add
any chips yet.
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/pcie.c | 219 ++++++++++++++++++
include/linux/bcma/bcma_driver_chipcommon.h | 1 +
2 files changed, 220 insertions(+)
@@ -1758,6 +1778,199 @@ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {.write32=brcmf_pcie_buscore_write32,};+#define BRCMF_OTP_SYS_VENDOR 0x15+#define BRCMF_OTP_BRCM_CIS 0x80++#define BRCMF_OTP_VENDOR_HDR 0x00000008++staticint+brcmf_pcie_parse_otp_sys_vendor(structbrcmf_pciedev_info*devinfo,+u8*data,size_tsize)+{+intidx=4;+constchar*chip_params;+constchar*module_params;+constchar*p;++/* 4-byte header and two empty strings */+if(size<6)+return-EINVAL;++if(get_unaligned_le32(data)!=BRCMF_OTP_VENDOR_HDR)+return-EINVAL;++chip_params=&data[idx];++/* Skip first string, including terminator */+idx+=strnlen(chip_params,size-idx)+1;+if(idx>=size)+return-EINVAL;++module_params=&data[idx];++/* Skip to terminator of second string */+idx+=strnlen(module_params,size-idx);+if(idx>=size)+return-EINVAL;++/* At this point both strings are guaranteed NUL-terminated */+brcmf_dbg(PCIE,"OTP: chip_params='%s' module_params='%s'\n",+chip_params,module_params);++p=module_params;+while(*p){+chartag=*p++;+constchar*end;+size_tlen;++if(tag==' ')/* Skip extra spaces */+continue;++if(*p++!='=')/* implicit NUL check */+return-EINVAL;++/* *p might be NUL here, if so end == p and len == 0 */+end=strchrnul(p,' ');+len=end-p;++/* leave 1 byte for NUL in destination string */+if(len>(BRCMF_OTP_MAX_PARAM_LEN-1))+return-EINVAL;++/* Copy len characters plus a NUL terminator */+switch(tag){+case'M':+strscpy(devinfo->otp.module,p,len+1);+break;+case'V':+strscpy(devinfo->otp.vendor,p,len+1);+break;+case'm':+strscpy(devinfo->otp.version,p,len+1);+break;+}++/* Skip to space separator or NUL */+p=end;+}++brcmf_dbg(PCIE,"OTP: module=%s vendor=%s version=%s\n",+devinfo->otp.module,devinfo->otp.vendor,+devinfo->otp.version);++if(!devinfo->otp.module||+!devinfo->otp.vendor||+!devinfo->otp.version)+return-EINVAL;++devinfo->otp.valid=true;+return0;+}++staticint+brcmf_pcie_parse_otp(structbrcmf_pciedev_info*devinfo,u8*otp,size_tsize)+{+intp=0;+intret=-1;++brcmf_dbg(PCIE,"parse_otp size=%ld\n",size);++while(p<(size-1)){+u8type=otp[p];+u8length=otp[p+1];++if(type==0)+break;++if((p+2+length)>size)+break;++switch(type){+caseBRCMF_OTP_SYS_VENDOR:+brcmf_dbg(PCIE,"OTP @ 0x%x (0x%x): SYS_VENDOR\n",+p,length);+ret=brcmf_pcie_parse_otp_sys_vendor(devinfo,+&otp[p+2],+length);+break;+caseBRCMF_OTP_BRCM_CIS:+brcmf_dbg(PCIE,"OTP @ 0x%x (0x%x): BRCM_CIS\n",+p,length);+break;+default:+brcmf_dbg(PCIE,"OTP @ 0x%x (0x%x): Unknown type 0x%x\n",+p,length,type);+break;+}++p+=2+length;+}++returnret;+}++staticintbrcmf_pcie_read_otp(structbrcmf_pciedev_info*devinfo)+{+conststructpci_dev*pdev=devinfo->pdev;+structbrcmf_bus*bus=dev_get_drvdata(&pdev->dev);+u32coreid,base,words,idx,sromctl;+u16*otp;+structbrcmf_core*core;+intret;++switch(devinfo->ci->chip){+default:+/* OTP not supported on this chip */+return0;+}++core=brcmf_chip_get_core(devinfo->ci,coreid);+if(!core){+brcmf_err(bus,"No OTP core\n");+return-ENODEV;+}++if(coreid==BCMA_CORE_CHIPCOMMON){+/* Chips with OTP accessed via ChipCommon need additional+*handlingtoaccesstheOTP+*/+brcmf_pcie_select_core(devinfo,coreid);+sromctl=READCC32(devinfo,sromcontrol);++if(!(sromctl&BCMA_CC_SROM_CONTROL_OTP_PRESENT)){+/* Chip lacks OTP, try without it... */+brcmf_err(bus,+"OTP unavailable, using default firmware\n");+return0;+}++/* Map OTP to shadow area */+WRITECC32(devinfo,sromcontrol,+sromctl|BCMA_CC_SROM_CONTROL_OTPSEL);+}++otp=kzalloc(sizeof(u16)*words,GFP_KERNEL);++/* Map bus window to SROM/OTP shadow area in core */+base=brcmf_pcie_buscore_prep_addr(devinfo->pdev,base+core->base);++brcmf_dbg(PCIE,"OTP data:\n");+for(idx=0;idx<words;idx++){+otp[idx]=brcmf_pcie_read_reg16(devinfo,base+2*idx);+brcmf_dbg(PCIE,"[%8x] 0x%04x\n",base+2*idx,otp[idx]);+}++if(coreid==BCMA_CORE_CHIPCOMMON){+brcmf_pcie_select_core(devinfo,coreid);+WRITECC32(devinfo,sromcontrol,sromctl);+}++ret=brcmf_pcie_parse_otp(devinfo,(u8*)otp,2*words);+kfree(otp);++returnret;+}+#define BRCMF_PCIE_FW_CODE 0#define BRCMF_PCIE_FW_NVRAM 1#define BRCMF_PCIE_FW_CLM 2
From: Hector Martin <hidden> Date: 2021-12-26 15:37:56
On Apple ARM64 platforms, firmware selection requires two properties
that come from system firmware: the module-instance (aka "island", a
codename representing a given hardware platform) and the antenna-sku.
The module-instance is hard-coded in per-board DTS files, while the
antenna-sku is forwarded by our bootloader from the Apple Device Tree
into the FDT. Grab them from the DT so firmware selection can use
them.
The module-instance is used to construct a board_type by prepending it
with "apple,".
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/common.h | 1 +
.../wireless/broadcom/brcm80211/brcmfmac/of.c | 19 ++++++++++++++++++-
2 files changed, 19 insertions(+), 1 deletion(-)
@@ -63,14 +63,31 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,{structbrcmfmac_sdio_pd*sdio=&settings->bus.sdio;structdevice_node*root,*np=dev->of_node;+constchar*prop;intirq;interr;u32irqf;u32val;+/* Apple ARM64 platforms have their own idea of board type, passed in+*viathedevicetree.TheyalsohaveanantennaSKUparameter+*/+if(!of_property_read_string(np,"apple,module-instance",&prop)){+constchar*prefix="apple,";+intlen=strlen(prefix)+strlen(prop)+1;+char*board_type=devm_kzalloc(dev,len,GFP_KERNEL);++strscpy(board_type,prefix,len);+strlcat(board_type,prop,len);+settings->board_type=board_type;+}++if(!of_property_read_string(np,"apple,antenna-sku",&prop))+settings->antenna_sku=devm_kstrdup(dev,prop,GFP_KERNEL);+/* Set board-type to the first string of the machine compatible prop */root=of_find_node_by_path("/");-if(root){+if(root&&!settings->board_type){inti,len;char*board_type;constchar*tmp;
From: Hector Martin <hidden> Date: 2021-12-26 15:38:06
On Apple platforms, firmware selection uses the following elements:
Property Example Source
============== ======= ========================
* Chip name 4378 Device ID
* Chip revision B1 OTP
* Platform shikoku DT (ARM64) or ACPI (x86)
* Module type RASP OTP
* Module vendor m OTP
* Module version 6.11 OTP
* Antenna SKU X3 DT (ARM64) or ??? (x86)
In macOS, these firmwares are stored using filenames in this format
under /usr/share/firmware/wifi:
C-4378__s-B1/P-shikoku-X3_M-RASP_V-m__m-6.11.txt
To prepare firmwares for Linux, we rename these to a scheme following
the existing brcmfmac convention:
brcmfmac<chip><lower(rev)>-pcie.apple,<platform>-<mod_type>-\
<mod_vendor>-<mod_version>-<antenna_sku>.txt
The NVRAM uses all the components, while the firmware and CLM blob only
use the chip/revision/platform/antenna_sku:
brcmfmac<chip><lower(rev)>-pcie.apple,<platform>-<antenna_sku>.bin
e.g.
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m-6.11-X3.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-X3.bin
In addition, since there are over 1000 files in total, many of which are
symlinks or outright duplicates, we deduplicate and prune the firmware
tree to reduce firmware filenames to fewer dimensions. For example, the
shikoku platform (MacBook Air M1 2020) simplifies to just 4 files:
brcm/brcmfmac4378b1-pcie.apple,shikoku.clm_blob
brcm/brcmfmac4378b1-pcie.apple,shikoku.bin
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-u.txt
This reduces the total file count to around 170, of which 75 are
symlinks and 95 are regular files: 7 firmware blobs, 27 CLM blobs, and
61 NVRAM config files. We also slightly process NVRAM files to correct
some formatting issues and add a missing default macaddr= property.
To handle this, the driver must try the following path formats when
looking for firmware files:
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m-6.11-X3.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m-6.11.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-X3.txt *
brcm/brcmfmac4378b1-pcie.apple,shikoku.txt
* Not relevant for NVRAM, only for firmware/CLM.
The chip revision nominally comes from OTP on Apple platforms, but it
can be mapped to the PCI revision number, so we ignore the OTP revision
and continue to use the existing PCI revision mechanism to identify chip
revisions, as the driver already does for other chips. Unfortunately,
the mapping is not consistent between different chip types, so this has
to be determined experimentally.
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/pcie.c | 68 +++++++++++++++++--
1 file changed, 63 insertions(+), 5 deletions(-)
From: Hector Martin <hidden> Date: 2021-12-26 15:38:10
On Device Tree platforms, it is customary to be able to set the MAC
address via the Device Tree, as it is often stored in system firmware.
This is particularly relevant for Apple ARM64 platforms, where this
information comes from system configuration and passed through by the
bootloader into the DT.
Implement support for this by fetching the platform MAC address and
adding or replacing the macaddr= property in nvram. This becomes the
dongle's default MAC address.
On platforms with an SROM MAC address, this overrides it. On platforms
without one, such as Apple ARM64 devices, this is required for the
firmware to boot (it will fail if it does not have a valid MAC at all).
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/firmware.c | 30 +++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
@@ -207,6 +214,9 @@ static int brcmf_init_nvram_parser(struct nvram_parser *nvp,size=BRCMF_FW_MAX_NVRAM_SIZE;elsesize=data_len;+/* Add space for properties we may add */+size+=strlen(BRCMF_FW_DEFAULT_BOARDREV)+1;+size+=BRCMF_FW_MACADDR_LEN+1;/* Alloc for extra 0 byte + roundup by 4 + length field */size+=1+3+sizeof(u32);nvp->nvram=kzalloc(size,GFP_KERNEL);
@@ -366,22 +376,34 @@ static void brcmf_fw_add_defaults(struct nvram_parser *nvp)nvp->nvram_len++;}+staticvoidbrcmf_fw_add_macaddr(structnvram_parser*nvp,u8*mac)+{+snprintf(&nvp->nvram[nvp->nvram_len],BRCMF_FW_MACADDR_LEN+1,+BRCMF_FW_MACADDR_FMT,mac);+nvp->nvram_len+=BRCMF_FW_MACADDR_LEN+1;+}+/* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a fil*andendinginaNUL.Removescarriagereturns,emptylines,commentlines,*andconvertsnewlinestoNULs.ShortensbufferasneededandpadswithNULs.*Endofbufferiscompletedwithtokenidentifyinglengthofbuffer.*/staticvoid*brcmf_fw_nvram_strip(constu8*data,size_tdata_len,-u32*new_length,u16domain_nr,u16bus_nr)+u32*new_length,u16domain_nr,u16bus_nr,+structdevice*dev){structnvram_parsernvp;u32pad;u32token;__le32token_le;+u8mac[ETH_ALEN];if(brcmf_init_nvram_parser(&nvp,data,data_len)<0)returnNULL;+if(eth_platform_get_mac_address(dev,mac)==0)+nvp.strip_mac=true;+while(nvp.pos<data_len){nvp.state=nv_parser_states[nvp.state](&nvp);if(nvp.state==END)
From: Hector Martin <hidden> Date: 2021-12-26 15:38:15
Newer chips used on Apple platforms have more than max_rxbufpost greater
than 512, which causes warnings when brcmf_msgbuf_rxbuf_data_fill tries
to put more in the ring than fit. Increase the ring sizes to 1024.
Signed-off-by: Hector Martin <redacted>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
From: Hector Martin <hidden> Date: 2021-12-26 15:38:25
The driver was enabling IRQs before the message processing was
initialized. This could cause IRQs to come in too early and crash the
driver. Instead, move the IRQ enable and hostready to a bus preinit
function, at which point everything is properly initialized.
Fixes: 9e37f045d5e7 ("brcmfmac: Adding PCIe bus layer support.")
Signed-off-by: Hector Martin <redacted>
---
.../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
From: Hector Martin <hidden> Date: 2021-12-26 15:38:46
These newer PCIe core revisions include new sets of registers that must
be used instead of the legacy ones. Introduce a brcmf_pcie_reginfo to
hold the specific register offsets and values to use for a given
platform, and change all the register accesses to indirect through it.
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/pcie.c | 125 +++++++++++++++---
1 file changed, 105 insertions(+), 20 deletions(-)
@@ -998,7 +1069,7 @@ static int brcmf_pcie_ring_mb_ring_bell(void *ctx)brcmf_dbg(PCIE,"RING !\n");/* Any arbitrary value will do, lets use 1 */-brcmf_pcie_write_reg32(devinfo,BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0,1);+brcmf_pcie_write_reg32(devinfo,devinfo->reginfo->h2d_mailbox_0,1);return0;}
@@ -1760,15 +1831,22 @@ static int brcmf_pcie_buscoreprep(void *ctx)staticintbrcmf_pcie_buscore_reset(void*ctx,structbrcmf_chip*chip){structbrcmf_pciedev_info*devinfo=(structbrcmf_pciedev_info*)ctx;-u32val;+structbrcmf_core*core;+u32val,reg;devinfo->ci=chip;brcmf_pcie_reset_device(devinfo);-val=brcmf_pcie_read_reg32(devinfo,BRCMF_PCIE_PCIE2REG_MAILBOXINT);+/* reginfo is not ready yet */+core=brcmf_chip_get_core(chip,BCMA_CORE_PCIE2);+if(core->rev>=64)+reg=BRCMF_PCIE_64_PCIE2REG_MAILBOXINT;+else+reg=BRCMF_PCIE_PCIE2REG_MAILBOXINT;++val=brcmf_pcie_read_reg32(devinfo,reg);if(val!=0xffffffff)-brcmf_pcie_write_reg32(devinfo,BRCMF_PCIE_PCIE2REG_MAILBOXINT,-val);+brcmf_pcie_write_reg32(devinfo,reg,val);return0;}
@@ -2365,7 +2450,7 @@ static int brcmf_pcie_pm_leave_D3(struct device *dev)brcmf_dbg(PCIE,"Enter, dev=%p, bus=%p\n",dev,bus);/* Check if device is still up and running, if so we are ready */-if(brcmf_pcie_read_reg32(devinfo,BRCMF_PCIE_PCIE2REG_INTMASK)!=0){+if(brcmf_pcie_read_reg32(devinfo,devinfo->reginfo->intmask)!=0){brcmf_dbg(PCIE,"Try to wakeup device....\n");if(brcmf_pcie_send_mb_data(devinfo,BRCMF_H2D_HOST_D0_INFORM))gotocleanup;
@@ -2010,6 +2012,11 @@ static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo)intret;switch(devinfo->ci->chip){+caseBRCM_CC_4378_CHIP_ID:+coreid=BCMA_CORE_GCI;+base=0x1120;+words=0x170;+break;default:/* OTP not supported on this chip */return0;
From: Hector Martin <hidden> Date: 2021-12-26 15:38:59
The Wi-Fi module in Apple machines has a "module-instance" device
property that specifies the platform type and is used for firmware
selection. Its value is a string, so add support for string values in
acpi_extract_apple_properties().
Signed-off-by: Hector Martin <redacted>
---
drivers/acpi/x86/apple.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
From: Hector Martin <hidden> Date: 2021-12-26 15:39:02
On DT platforms, the module-instance and antenna-sku-info properties
are passed in the DT. On ACPI platforms, module-instance is passed via
the analogous Apple device property mechanism, while the antenna SKU
info is instead obtained via an ACPI method that grabs it from
non-volatile storage.
Add support for this, to allow proper firmware selection on Apple
platforms.
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/Makefile | 2 +
.../broadcom/brcm80211/brcmfmac/acpi.c | 51 +++++++++++++++++++
.../broadcom/brcm80211/brcmfmac/common.c | 1 +
.../broadcom/brcm80211/brcmfmac/common.h | 9 ++++
4 files changed, 63 insertions(+)
create mode 100644 drivers/net/wireless/broadcom/brcm80211/brcmfmac/acpi.c
@@ -437,6 +437,7 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,/* No platform data for this device, try OF and DMI data */brcmf_dmi_probe(settings,chip,chiprev);brcmf_of_probe(dev,bus_type,settings);+brcmf_acpi_probe(dev,bus_type,settings);}returnsettings;}
From: Hector Martin <hidden> Date: 2021-12-26 15:39:06
Newer Apple firmwares on chipsets without a hardware RNG require the
host to provide a buffer of 256 random bytes to the device on
initialization. This buffer is present immediately before NVRAM,
suffixed by a footer containing a magic number and the buffer length.
This won't affect chips/firmwares that do not use this feature, so do it
unconditionally.
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/pcie.c | 30 +++++++++++++++++++
1 file changed, 30 insertions(+)
@@ -1693,11 +1701,33 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,brcmf_pcie_write_ram32(devinfo,devinfo->ci->ramsize-4,0);if(nvram){+size_trand_len=BRCMF_RANDOM_SEED_LENGTH;+structbrcmf_random_seed_footerfooter={+.length=cpu_to_le32(rand_len),+.magic=cpu_to_le32(BRCMF_RANDOM_SEED_MAGIC),+};+void*randbuf;+brcmf_dbg(PCIE,"Download NVRAM %s\n",devinfo->nvram_name);address=devinfo->ci->rambase+devinfo->ci->ramsize-nvram_len;brcmf_pcie_copy_mem_todev(devinfo,address,nvram,nvram_len);brcmf_fw_nvram_free(nvram);++/* Some Apple chips/firmwares expect a buffer of random data+*tobepresentbeforeNVRAM+*/+brcmf_dbg(PCIE,"Download random seed\n");++address-=sizeof(footer);+brcmf_pcie_copy_mem_todev(devinfo,address,&footer,+sizeof(footer));++address-=rand_len;+randbuf=kzalloc(rand_len,GFP_KERNEL);+get_random_bytes(randbuf,rand_len);+brcmf_pcie_copy_mem_todev(devinfo,address,randbuf,rand_len);+kfree(randbuf);}else{brcmf_dbg(PCIE,"No matching NVRAM file found %s\n",devinfo->nvram_name);
From: Hector Martin <hidden> Date: 2021-12-26 15:39:17
This chip is present on at least these Apple T2 Macs:
* hawaii: MacBook Air 13" (Late 2018)
* hawaii: MacBook Air 13" (True Tone, 2019)
Signed-off-by: Hector Martin <redacted>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 1 +
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 8 ++++++++
.../net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 2 ++
3 files changed, 11 insertions(+)
From: Hector Martin <hidden> Date: 2021-12-26 15:39:29
This chip is present on at least these Apple T2 Macs:
* tahiti: MacBook Pro 13" (2020, 2 TB3)
* formosa: MacBook Pro 13" (Touch/2019)
* fiji: MacBook Air 13" (Scissor, 2020)
Signed-off-by: Hector Martin <redacted>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 1 +
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 4 ++++
drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 2 ++
3 files changed, 7 insertions(+)
From: Hector Martin <hidden> Date: 2021-12-26 15:39:35
This chip exists in two revisions (B2=r3 and B3=r4) on different
platforms, and was added without regard to doing proper firmware
selection or differentiating between them. Fix this to have proper
per-revision firmwares and support Apple NVRAM selection.
Revision B2 is present on at least these Apple T2 Macs:
kauai: MacBook Pro 15" (Touch/2018-2019)
maui: MacBook Pro 13" (Touch/2018-2019)
lanai: Mac mini (Late 2018)
ekans: iMac Pro 27" (5K, Late 2017)
And these non-T2 Macs:
nihau: iMac 27" (5K, 2019)
Revision B3 is present on at least these Apple T2 Macs:
bali: MacBook Pro 16" (2019)
trinidad: MacBook Pro 13" (2020, 4 TB3)
borneo: MacBook Pro 16" (2019, 5600M)
kahana: Mac Pro (2019)
kahana: Mac Pro (2019, Rack)
hanauma: iMac 27" (5K, 2020)
kure: iMac 27" (5K, 2020, 5700/XT)
Fixes: 24f0bd136264 ("brcmfmac: add the BRCM 4364 found in MacBook Pro 15,2")
Signed-off-by: Hector Martin <redacted>
---
.../net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
From: Hector Martin <hidden> Date: 2021-12-26 15:39:51
BCM4387 has trailing odd-sized blocks as part of TCM which have
their size described as a multiple of 1024 instead of 8192. Handle this
so we can compute the TCM size properly.
Signed-off-by: Hector Martin <redacted>
---
.../wireless/broadcom/brcm80211/brcmfmac/chip.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
@@ -752,7 +759,7 @@ int brcmf_chip_get_raminfo(struct brcmf_chip *pub)mem=brcmf_chip_get_core(&ci->pub,BCMA_CORE_ARM_CR4);if(mem){mem_core=container_of(mem,structbrcmf_core_priv,pub);-ci->pub.ramsize=brcmf_chip_tcm_ramsize(mem_core);+ci->pub.ramsize=brcmf_chip_tcm_ramsize(ci,mem_core);ci->pub.rambase=brcmf_chip_tcm_rambase(ci);if(ci->pub.rambase==INVALID_RAMBASE){brcmf_err("RAM base not provided with ARM CR4 core\n");
From: Hector Martin <hidden> Date: 2021-12-26 15:39:56
This new API version is required for at least the BCM4387 firmware. Add
support for it, with a fallback to the v1 API.
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 113 ++++++++++++++----
.../broadcom/brcm80211/brcmfmac/feature.c | 1 +
.../broadcom/brcm80211/brcmfmac/feature.h | 4 +-
.../broadcom/brcm80211/brcmfmac/fwil_types.h | 49 +++++++-
4 files changed, 145 insertions(+), 22 deletions(-)
@@ -769,12 +769,50 @@ void brcmf_set_mpc(struct brcmf_if *ifp, int mpc)}}+staticvoidbrcmf_escan_prep(structbrcmf_cfg80211_info*cfg,+structbrcmf_scan_params_v2_le*params_le,+structcfg80211_scan_request*request);++staticvoidbrcmf_scan_params_v2_to_v1(structbrcmf_scan_params_v2_le*params_v2_le,+structbrcmf_scan_params_le*params_le)+{+size_tparams_size;+u32ch;+intn_channels,n_ssids;++memcpy(¶ms_le->ssid_le,¶ms_v2_le->ssid_le,+sizeof(params_le->ssid_le));+memcpy(¶ms_le->bssid,¶ms_v2_le->bssid,+sizeof(params_le->bssid));++params_le->bss_type=params_v2_le->bss_type;+params_le->scan_type=params_v2_le->scan_type;+params_le->nprobes=params_v2_le->nprobes;+params_le->active_time=params_v2_le->active_time;+params_le->passive_time=params_v2_le->passive_time;+params_le->home_time=params_v2_le->home_time;+params_le->channel_num=params_v2_le->channel_num;++ch=le32_to_cpu(params_v2_le->channel_num);+n_channels=ch&BRCMF_SCAN_PARAMS_COUNT_MASK;+n_ssids=ch>>BRCMF_SCAN_PARAMS_NSSID_SHIFT;++params_size=sizeof(u16)*n_channels;+if(n_ssids>0){+params_size=roundup(params_size,sizeof(u32));+params_size+=sizeof(structbrcmf_ssid_le)*n_ssids;+}++memcpy(¶ms_le->channel_list[0],+¶ms_v2_le->channel_list[0],params_size);+}+s32brcmf_notify_escan_complete(structbrcmf_cfg80211_info*cfg,structbrcmf_if*ifp,boolaborted,boolfw_abort){structbrcmf_pub*drvr=cfg->pub;-structbrcmf_scan_params_leparams_le;+structbrcmf_scan_params_v2_leparams_v2_le;structcfg80211_scan_request*scan_request;u64reqid;u32bucket;
@@ -793,20 +831,23 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,if(fw_abort){/* Do a scan abort to stop the driver's scan engine */brcmf_dbg(SCAN,"ABORT scan in firmware\n");-memset(¶ms_le,0,sizeof(params_le));-eth_broadcast_addr(params_le.bssid);-params_le.bss_type=DOT11_BSSTYPE_ANY;-params_le.scan_type=0;-params_le.channel_num=cpu_to_le32(1);-params_le.nprobes=cpu_to_le32(1);-params_le.active_time=cpu_to_le32(-1);-params_le.passive_time=cpu_to_le32(-1);-params_le.home_time=cpu_to_le32(-1);-/* Scan is aborted by setting channel_list[0] to -1 */-params_le.channel_list[0]=cpu_to_le16(-1);++brcmf_escan_prep(cfg,¶ms_v2_le,NULL);+/* E-Scan (or anyother type) can be aborted by SCAN */-err=brcmf_fil_cmd_data_set(ifp,BRCMF_C_SCAN,-¶ms_le,sizeof(params_le));+if(brcmf_feat_is_enabled(ifp,BRCMF_FEAT_SCAN_V2)){+err=brcmf_fil_cmd_data_set(ifp,BRCMF_C_SCAN,+¶ms_v2_le,+sizeof(params_v2_le));+}else{+structbrcmf_scan_params_leparams_le;++brcmf_scan_params_v2_to_v1(¶ms_v2_le,¶ms_le);+err=brcmf_fil_cmd_data_set(ifp,BRCMF_C_SCAN,+¶ms_le,+sizeof(params_le));+}+if(err)bphy_err(drvr,"Scan abort failed\n");}
@@ -1054,6 +1109,7 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,brcmf_dbg(SCAN,"### List of channelspecs to scan ### %d\n",n_channels);if(n_channels>0){+length+=roundup(sizeof(u16)*n_channels,sizeof(u32));for(i=0;i<n_channels;i++){chanspec=channel_to_chanspec(&cfg->d11inf,request->channels[i]);
@@ -1064,12 +1120,14 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,}else{brcmf_dbg(SCAN,"Scanning all channels\n");}+/* Copy ssid array if applicable */brcmf_dbg(SCAN,"### List of SSIDs to scan ### %d\n",n_ssids);if(n_ssids>0){-offset=offsetof(structbrcmf_scan_params_le,channel_list)++offset=offsetof(structbrcmf_scan_params_v2_le,channel_list)+n_channels*sizeof(u16);offset=roundup(offset,sizeof(u32));+length+=sizeof(ssid_le)*n_ssids,ptr=(char*)params_le+offset;for(i=0;i<n_ssids;i++){memset(&ssid_le,0,sizeof(ssid_le));
@@ -48,6 +48,10 @@/* size of brcmf_scan_params not including variable length array */#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64+#define BRCMF_SCAN_PARAMS_V2_FIXED_SIZE 72++/* version of brcmf_scan_params structure */+#define BRCMF_SCAN_PARAMS_VERSION_V2 2/* masks for channel and ssid count */#define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff
@@ -67,6 +71,7 @@#define BRCMF_PRIMARY_KEY (1 << 1)#define DOT11_BSSTYPE_ANY 2#define BRCMF_ESCAN_REQ_VERSION 1+#define BRCMF_ESCAN_REQ_VERSION_V2 2#define BRCMF_MAXRATES_IN_SET 16 /* max # of rates in rateset */
@@ -386,6 +391,45 @@ struct brcmf_scan_params_le {__le16channel_list[1];/* list of chanspecs */};+structbrcmf_scan_params_v2_le{+__le16version;/* structure version */+__le16length;/* structure length */+structbrcmf_ssid_lessid_le;/* default: {0, ""} */+u8bssid[ETH_ALEN];/* default: bcast */+s8bss_type;/* default: any,+*DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT+*/+u8pad;+__le32scan_type;/* flags, 0 use default */+__le32nprobes;/* -1 use default, number of probes per channel */+__le32active_time;/* -1 use default, dwell time per channel for+*activescanning+*/+__le32passive_time;/* -1 use default, dwell time per channel+*forpassivescanning+*/+__le32home_time;/* -1 use default, dwell time for the+*homechannelbetweenchannelscans+*/+__le32channel_num;/* count of channels and ssids that follow+*+*lowhalfiscountofchannelsin+*channel_list,0meansdefault(useall+*availablechannels)+*+*highhalfisentriesinstructbrcmf_ssid+*arraythatfollowschannel_list,alignedfor+*s32(4bytes)meaninganoddchannelcount+*impliesa2-bytepadbetweenendof+*channel_listandfirstssid+*+*ifssidcountiszero,singlessidinthe+*fixedparameterportionisassumed,otherwise+*ssidinthefixedportionisignored+*/+__le16channel_list[1];/* list of chanspecs */+};+structbrcmf_scan_results{u32buflen;u32version;
From: Hector Martin <hidden> Date: 2021-12-26 15:40:08
Add support for the new PMKID_V3 API, which allows performing PMKID
mutations individually, instead of requiring the driver to keep track of
the full list. This new API is required by at least BCM4387.
Note that PMKID_V2 is not implemented yet.
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 49 ++++++++++-
.../broadcom/brcm80211/brcmfmac/fwil_types.h | 83 +++++++++++++++++++
2 files changed, 129 insertions(+), 3 deletions(-)
@@ -174,6 +174,10 @@#define BRCMF_HE_CAP_MCS_MAP_NSS_MAX 8+#define BRCMF_PMKSA_VER_2 2+#define BRCMF_PMKSA_VER_3 3+#define BRCMF_PMKSA_NO_EXPIRY 0xffffffff+/* MAX_CHUNK_LEN is the maximum length for data passing to firmware in each*ioctl.Itisrelativelysmallbecausefirmwarehassmallmaximumsizeinput*playloadrestrictionforioctls.
@@ -355,6 +359,12 @@ struct brcmf_ssid_le {unsignedcharSSID[IEEE80211_MAX_SSID_LEN];};+/* Alternate SSID structure used in some places... */+structbrcmf_ssid8_le{+u8SSID_len;+unsignedcharSSID[IEEE80211_MAX_SSID_LEN];+};+structbrcmf_scan_params_le{structbrcmf_ssid_lessid_le;/* default: {0, ""} */u8bssid[ETH_ALEN];/* default: bcast */
From: Hector Martin <hidden> Date: 2021-12-26 15:40:16
The "wlc_ver" iovar returns information on the WLC and EPI versions.
This can be used to determine whether the PMKID_V2 and _V3 features are
supported.
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/feature.c | 48 +++++++++++++++++++
.../broadcom/brcm80211/brcmfmac/feature.h | 4 +-
.../broadcom/brcm80211/brcmfmac/fwil_types.h | 25 ++++++++++
3 files changed, 76 insertions(+), 1 deletion(-)
From: Hector Martin <hidden> Date: 2021-12-26 15:40:25
Apparently the hex passphrase mechanism does not work on newer
chips/firmware (e.g. BCM4387). It seems there was a simple way of
passing it in binary all along, so use that and avoid the hexification.
OpenBSD has been doing it like this from the beginning, so this should
work on all chips.
Also clear the structure before setting the PMK. This was leaking
uninitialized stack contents to the device.
Signed-off-by: Hector Martin <redacted>
---
.../wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
@@ -2064,6 +2066,11 @@ static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo)base=0x1120;words=0x170;break;+caseBRCM_CC_4387_CHIP_ID:+coreid=BCMA_CORE_GCI;+base=0x113c;+words=0x170;+break;default:/* OTP not supported on this chip */return0;
From: Hector Martin <hidden> Date: 2021-12-26 15:40:40
The alignment check was wrong (e.g. & 4 instead of & 3), and the logic
was also inefficient if the length was not a multiple of 4, since it
would needlessly fall back to copying the entire buffer bytewise.
We already have a perfectly good memcpy_toio function, so just call that
instead of rolling our own copy logic here. brcmf_pcie_init_ringbuffers
was already using it anyway.
Fixes: 9e37f045d5e7 ("brcmfmac: Adding PCIe bus layer support.")
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/pcie.c | 53 +++----------------
1 file changed, 6 insertions(+), 47 deletions(-)
@@ -1719,7 +1679,7 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,brcmf_dbg(PCIE,"Download NVRAM %s\n",devinfo->nvram_name);address=devinfo->ci->rambase+devinfo->ci->ramsize-nvram_len;-brcmf_pcie_copy_mem_todev(devinfo,address,nvram,nvram_len);+memcpy_toio(devinfo->tcm+address,nvram,nvram_len);brcmf_fw_nvram_free(nvram);/* Some Apple chips/firmwares expect a buffer of random data
@@ -1728,13 +1688,12 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,brcmf_dbg(PCIE,"Download random seed\n");address-=sizeof(footer);-brcmf_pcie_copy_mem_todev(devinfo,address,&footer,-sizeof(footer));+memcpy_toio(devinfo->tcm+address,&footer,sizeof(footer));address-=rand_len;randbuf=kzalloc(rand_len,GFP_KERNEL);get_random_bytes(randbuf,rand_len);-brcmf_pcie_copy_mem_todev(devinfo,address,randbuf,rand_len);+memcpy_toio(devinfo->tcm+address,randbuf,rand_len);kfree(randbuf);}else{brcmf_dbg(PCIE,"No matching NVRAM file found %s\n",
From: Hector Martin <hidden> Date: 2021-12-26 15:40:44
At least on BCM4387, the D11 cores are held in reset on cold startup and
firmware expects to release reset itself. Just assert reset here and let
firmware deassert it. Premature deassertion results in the firmware
failing to initialize properly some of the time, with strange AXI bus
errors.
Also, BCM4387 has 3 cores, up from 2. The logic for handling that is in
brcmf_chip_ai_resetcore(), but since we aren't using that any more, just
handle it here.
Signed-off-by: Hector Martin <redacted>
---
.../net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
@@ -1289,15 +1289,18 @@ static bool brcmf_chip_cm3_set_active(struct brcmf_chip_priv *chip)staticinlinevoidbrcmf_chip_cr4_set_passive(structbrcmf_chip_priv*chip){+inti;structbrcmf_core*core;brcmf_chip_disable_arm(chip,BCMA_CORE_ARM_CR4);-core=brcmf_chip_get_core(&chip->pub,BCMA_CORE_80211);-brcmf_chip_resetcore(core,D11_BCMA_IOCTL_PHYRESET|-D11_BCMA_IOCTL_PHYCLOCKEN,-D11_BCMA_IOCTL_PHYCLOCKEN,-D11_BCMA_IOCTL_PHYCLOCKEN);+/* Disable the cores only and let the firmware enable them.+*ReleasingresetourselvesbreaksBCM4387inweirdways.+*/+for(i=0;(core=brcmf_chip_get_d11core(&chip->pub,i));i++)+brcmf_chip_coredisable(core,D11_BCMA_IOCTL_PHYRESET|+D11_BCMA_IOCTL_PHYCLOCKEN,+D11_BCMA_IOCTL_PHYCLOCKEN);}staticboolbrcmf_chip_cr4_set_active(structbrcmf_chip_priv*chip,u32rstvec)
From: Hector Martin <hidden> Date: 2021-12-26 15:40:54
This avoids leaking memory if brcmf_chip_get_raminfo fails. Note that
the CLM blob is released in the device remove path.
Fixes: 82f93cf46d60 ("brcmfmac: get chip's default RAM info during PCIe setup")
Signed-off-by: Hector Martin <redacted>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 2 ++
1 file changed, 2 insertions(+)
@@ -2118,6 +2118,8 @@ static void brcmf_pcie_setup(struct device *dev, int ret,ret=brcmf_chip_get_raminfo(devinfo->ci);if(ret){brcmf_err(bus,"Failed to get RAM info\n");+release_firmware(fw);+brcmf_fw_nvram_free(nvram);gotofail;}
From: Hector Martin <hidden> Date: 2021-12-26 15:40:57
This allows us to get console messages if the firmware crashed during
early init, or if an operation failed and we're about to shut down.
Signed-off-by: Hector Martin <redacted>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 4 ++++
1 file changed, 4 insertions(+)
From: Hector Martin <hidden> Date: 2021-12-26 15:41:14
Make all the iovar name arguments const char * instead of just char *.
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/fwil.c | 34 +++++++++----------
.../broadcom/brcm80211/brcmfmac/fwil.h | 28 +++++++--------
2 files changed, 31 insertions(+), 31 deletions(-)
From: Hector Martin <hidden> Date: 2021-12-26 15:41:25
The TxCap blobs are additional data blobs used on Apple devices, and
are uploaded analogously to CLM blobs. Add core support for doing this.
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/bus.h | 1 +
.../broadcom/brcm80211/brcmfmac/common.c | 97 +++++++++++++------
2 files changed, 71 insertions(+), 27 deletions(-)
@@ -39,6 +39,7 @@ enum brcmf_bus_protocol_type {/* Firmware blobs that may be available */enumbrcmf_blob_type{BRCMF_BLOB_CLM,+BRCMF_BLOB_TXCAP,};structbrcmf_mp_device;
@@ -132,20 +132,11 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)brcmf_dbg(TRACE,"Enter\n");-err=brcmf_bus_get_blob(bus,&clm,BRCMF_BLOB_CLM);-if(err||!clm){-brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",-err);-return0;-}-chunk_buf=kzalloc(sizeof(*chunk_buf)+MAX_CHUNK_LEN-1,GFP_KERNEL);-if(!chunk_buf){-err=-ENOMEM;-gotodone;-}+if(!chunk_buf)+return-ENOMEM;-datalen=clm->size;+datalen=size;cumulative_len=0;do{if(datalen>MAX_CHUNK_LEN){
@@ -154,9 +145,10 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)chunk_len=datalen;dl_flag|=DL_END;}-memcpy(chunk_buf->data,clm->data+cumulative_len,chunk_len);+memcpy(chunk_buf->data,data+cumulative_len,chunk_len);-err=brcmf_c_download(ifp,dl_flag,chunk_buf,chunk_len);+err=brcmf_c_download(ifp,dl_flag,chunk_buf,chunk_len,+loadvar);dl_flag&=~DL_BEGIN;
@@ -165,20 +157,64 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)}while((datalen>0)&&(err==0));if(err){-bphy_err(drvr,"clmload (%zu byte file) failed (%d)\n",-clm->size,err);-/* Retrieve clmload_status and print */-err=brcmf_fil_iovar_int_get(ifp,"clmload_status",&status);+bphy_err(drvr,"%s (%zu byte file) failed (%d)\n",+loadvar,size,err);+/* Retrieve status and print */+err=brcmf_fil_iovar_int_get(ifp,statvar,&status);if(err)-bphy_err(drvr,"get clmload_status failed (%d)\n",err);+bphy_err(drvr,"get %s failed (%d)\n",statvar,err);else-brcmf_dbg(INFO,"clmload_status=%d\n",status);+brcmf_dbg(INFO,"%s=%d\n",statvar,status);err=-EIO;}kfree(chunk_buf);-done:-release_firmware(clm);+returnerr;+}++staticintbrcmf_c_process_clm_blob(structbrcmf_if*ifp)+{+structbrcmf_pub*drvr=ifp->drvr;+structbrcmf_bus*bus=drvr->bus_if;+conststructfirmware*fw=NULL;+s32err;++brcmf_dbg(TRACE,"Enter\n");++err=brcmf_bus_get_blob(bus,&fw,BRCMF_BLOB_CLM);+if(err||!fw){+brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",+err);+return0;+}++err=brcmf_c_download_blob(ifp,fw->data,fw->size,+"clmload","clmload_status");++release_firmware(fw);+returnerr;+}++staticintbrcmf_c_process_txcap_blob(structbrcmf_if*ifp)+{+structbrcmf_pub*drvr=ifp->drvr;+structbrcmf_bus*bus=drvr->bus_if;+conststructfirmware*fw=NULL;+s32err;++brcmf_dbg(TRACE,"Enter\n");++err=brcmf_bus_get_blob(bus,&fw,BRCMF_BLOB_TXCAP);+if(err||!fw){+brcmf_info("no txcap_blob available (err=%d)\n",err);+return0;+}++brcmf_info("TxCap blob found, loading\n");+err=brcmf_c_download_blob(ifp,fw->data,fw->size,+"txcapload","txcapload_status");++release_firmware(fw);returnerr;}
@@ -248,6 +284,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)gotodone;}+/* Do TxCap downloading, if needed */+err=brcmf_c_process_txcap_blob(ifp);+if(err<0){+bphy_err(drvr,"download TxCap blob file failed, %d\n",err);+gotodone;+}+/* query for 'ver' to get version info from firmware */memset(buf,0,sizeof(buf));err=brcmf_fil_iovar_data_get(ifp,"ver",buf,sizeof(buf));
From: Hector Martin <hidden> Date: 2021-12-26 15:41:31
These blobs are named .txcap_blob, and exist alongside the existing
.clm_blob files. Use the existing firmware machinery to provide them to
the core.
Signed-off-by: Hector Martin <redacted>
---
.../net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
From: Hector Martin <hidden> Date: 2021-12-26 15:41:35
The calibration blob for a chip is normally stored in SROM and loaded
internally by the firmware. However, Apple ARM64 platforms instead store
it as part of platform configuration data, and provide it via the Apple
Device Tree. We forward this into the Linux DT in the bootloader.
Add support for taking this blob from the DT and loading it into the
dongle. The loading mechanism is the same as used for the CLM and TxCap
blobs.
Signed-off-by: Hector Martin <redacted>
---
.../broadcom/brcm80211/brcmfmac/common.c | 24 +++++++++++++++++++
.../broadcom/brcm80211/brcmfmac/common.h | 2 ++
.../wireless/broadcom/brcm80211/brcmfmac/of.c | 8 +++++++
3 files changed, 34 insertions(+)
@@ -218,6 +218,23 @@ static int brcmf_c_process_txcap_blob(struct brcmf_if *ifp)returnerr;}+staticintbrcmf_c_process_cal_blob(structbrcmf_if*ifp)+{+structbrcmf_pub*drvr=ifp->drvr;+structbrcmf_mp_device*settings=drvr->settings;+s32err;++brcmf_dbg(TRACE,"Enter\n");++if(!settings->cal_blob||!settings->cal_size)+return0;++brcmf_info("Calibration blob provided by platform, loading\n");+err=brcmf_c_download_blob(ifp,settings->cal_blob,settings->cal_size,+"calload","calload_status");+returnerr;+}+intbrcmf_c_preinit_dcmds(structbrcmf_if*ifp){structbrcmf_pub*drvr=ifp->drvr;
@@ -291,6 +308,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)gotodone;}+/* Download external calibration blob, if available */+err=brcmf_c_process_cal_blob(ifp);+if(err<0){+bphy_err(drvr,"download calibration blob file failed, %d\n",err);+gotodone;+}+/* query for 'ver' to get version info from firmware */memset(buf,0,sizeof(buf));err=brcmf_fil_iovar_data_get(ifp,"ver",buf,sizeof(buf));
@@ -85,6 +85,14 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,if(!of_property_read_string(np,"apple,antenna-sku",&prop))settings->antenna_sku=devm_kstrdup(dev,prop,GFP_KERNEL);+/* The WLAN calibration blob is normally stored in SROM, but Apple+*ARM64platformspassitviatheDTinstead.+*/+prop=of_get_property(np,"brcm,cal-blob",&settings->cal_size);+if(prop&&settings->cal_size)+settings->cal_blob=devm_kmemdup(dev,prop,settings->cal_size,+GFP_KERNEL);+/* Set board-type to the first string of the machine compatible prop */root=of_find_node_by_path("/");if(root&&!settings->board_type){
On Mon, Dec 27, 2021 at 12:36:05AM +0900, Hector Martin wrote:
The Wi-Fi module in Apple machines has a "module-instance" device
property that specifies the platform type and is used for firmware
selection. Its value is a string, so add support for string values in
acpi_extract_apple_properties().
Signed-off-by: Hector Martin <redacted>
On Mon, Dec 27, 2021 at 12:35:50AM +0900, Hector Martin wrote:
# On firmware
As you might expect, the firmware for these machines is not available
under a redistributable license; however, every owner of one of these
machines *is* implicitly licensed to posess the firmware, and the OS
packages containing it are available under well-known URLs on Apple's
CDN with no authentication.
Apple's EFI firmware contains a full-fledged network stack for
downloading macOS images from osrecovery.apple.com. I suspect
that it also contains wifi firmware.
You may want to check if it's passed to the OS as an EFI property.
Using that would sidestep license issues. There's EDID data,
Thunderbolt DROM data and whatnot in those properties, so I
wouldn't be surprised if it contained wifi stuff as well.
Enable CONFIG_APPLE_PROPERTIES and pass "dump_apple_properties"
on the command line to see all EFI properties in dmesg.
Alternatively, check "ioreg -l" on macOS. Generally, what's
available in the I/O registry should also be available on Linux
either as an ACPI or EFI property.
Thanks,
Lukas
On Sun, Dec 26, 2021 at 4:36 PM Hector Martin [off-list ref] wrote:
This binding is currently used for SDIO devices, but these chips are
also used as PCIe devices on DT platforms and may be represented in the
DT. Re-use the existing binding and add chip compatibles used by Apple
T2 and M1 platforms (the T2 ones are not known to be used in DT
platforms, but we might as well document them).
Then, add properties required for firmware selection and calibration on
M1 machines.
Signed-off-by: Hector Martin <redacted>
Makes sense to me!
Reviewed-by: Linus Walleij <redacted>
quoted hunk
+ brcm,cal-blob:+ $ref: /schemas/types.yaml#/definitions/uint8-array+ description: A per-device calibration blob for the Wi-Fi radio. This+ should be filled in by the bootloader from platform configuration+ data, if necessary, and will be uploaded to the device if present.
This is especially nice. This way on other systems U-Boot can read the
calibration file (usually stored in a special partition) and modify the
device tree to include this, then we don't need the driver to learn
about any specific file locations for calibrations or worry about
inserting it from userspace.
Yours,
Linus Walleij
On Sun, Dec 26, 2021 at 4:36 PM Hector Martin [off-list ref] wrote:
Move one of the declarations from sdio.c to pcie.c, since it makes no
sense in the former (SDIO support is optional), and add missing ones.
Signed-off-by: Hector Martin <redacted>
Fixes: 75729e110e68 ("brcmfmac: expose firmware config files through modinfo")
From: Hans de Goede <hidden> Date: 2021-12-26 21:43:01
Hi,
On 12/26/21 20:17, Lukas Wunner wrote:
On Mon, Dec 27, 2021 at 12:35:50AM +0900, Hector Martin wrote:
quoted
# On firmware
As you might expect, the firmware for these machines is not available
under a redistributable license; however, every owner of one of these
machines *is* implicitly licensed to posess the firmware, and the OS
packages containing it are available under well-known URLs on Apple's
CDN with no authentication.
Apple's EFI firmware contains a full-fledged network stack for
downloading macOS images from osrecovery.apple.com. I suspect
that it also contains wifi firmware.
You may want to check if it's passed to the OS as an EFI property.
Using that would sidestep license issues. There's EDID data,
Thunderbolt DROM data and whatnot in those properties, so I
wouldn't be surprised if it contained wifi stuff as well.
Enable CONFIG_APPLE_PROPERTIES and pass "dump_apple_properties"
on the command line to see all EFI properties in dmesg.
Alternatively, check "ioreg -l" on macOS. Generally, what's
available in the I/O registry should also be available on Linux
either as an ACPI or EFI property.
Interesting, note that even if the files are not available as
a property we also have CONFIG_EFI_EMBEDDED_FIRMWARE, see:
drivers/firmware/efi/embedded-firmware.c
Documentation/driver-api/firmware/fallback-mechanisms.rst
I wrote this to pry/dig out some touchscreen firmwares (where
we have been unable to get permission to redistribute) out of
EFI boot_services_code mem regions on tablets where
the touchsceen is supported under the EFI environment.
This may need some tweaks, but if there is an embedded copy
of the firmware files in the EFI mem regions somewhere it
should be possible to adjust this code to grab it and present
it to the firmware-loader mechanism as a fallback option.
Refards,
Hans
From: Rob Herring <robh@kernel.org> Date: 2021-12-26 23:34:18
On Mon, 27 Dec 2021 00:35:51 +0900, Hector Martin wrote:
This binding is currently used for SDIO devices, but these chips are
also used as PCIe devices on DT platforms and may be represented in the
DT. Re-use the existing binding and add chip compatibles used by Apple
T2 and M1 platforms (the T2 ones are not known to be used in DT
platforms, but we might as well document them).
Then, add properties required for firmware selection and calibration on
M1 machines.
Signed-off-by: Hector Martin <redacted>
---
.../net/wireless/brcm,bcm4329-fmac.yaml | 32 +++++++++++++++++--
1 file changed, 29 insertions(+), 3 deletions(-)
My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):
yamllint warnings/errors:
dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml: properties:apple,antenna-sku: '$def' is not one of ['$ref', 'additionalItems', 'additionalProperties', 'allOf', 'anyOf', 'const', 'contains', 'default', 'dependencies', 'dependentRequired', 'dependentSchemas', 'deprecated', 'description', 'else', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'items', 'if', 'minItems', 'minimum', 'maxItems', 'maximum', 'multipleOf', 'not', 'oneOf', 'pattern', 'patternProperties', 'properties', 'required', 'then', 'type', 'typeSize', 'unevaluatedProperties', 'uniqueItems']
from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml: properties:apple,antenna-sku: 'oneOf' conditional failed, one must be fixed:
'type' is a required property
hint: A vendor boolean property can use "type: boolean"
Additional properties are not allowed ('$def' was unexpected)
hint: A vendor boolean property can use "type: boolean"
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml: properties:apple,antenna-sku: 'oneOf' conditional failed, one must be fixed:
'enum' is a required property
'const' is a required property
hint: A vendor string property with exact values has an implicit type
from schema $id: http://devicetree.org/meta-schemas/vendor-props.yaml#
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml: properties:apple,antenna-sku: 'oneOf' conditional failed, one must be fixed:
'$ref' is a required property
'allOf' is a required property
hint: A vendor property needs a $ref to types.yaml
from schema $id: http://devicetree.org/meta-schemas/vendor-props.yaml#
hint: Vendor specific properties must have a type and description unless they have a defined, common suffix.
from schema $id: http://devicetree.org/meta-schemas/vendor-props.yaml#
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml: ignoring, error in schema: properties: apple,antenna-sku
Documentation/devicetree/bindings/mmc/mmc-controller.example.dt.yaml:0:0: /example-0/mmc@1c12000/wifi@1: failed to match any schema with compatible: ['brcm,bcm4329-fmac']
Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.example.dt.yaml:0:0: /example-0/mmc@80118000/wifi@1: failed to match any schema with compatible: ['brcm,bcm4334-fmac', 'brcm,bcm4329-fmac']
Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.example.dt.yaml:0:0: /example-0/mmc@80118000/wifi@1: failed to match any schema with compatible: ['brcm,bcm4334-fmac', 'brcm,bcm4329-fmac']
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/patch/1573232
This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit.
From: Hector Martin <hidden> Date: 2021-12-27 11:53:34
On 2021/12/27 6:42, Hans de Goede wrote:
Hi,
On 12/26/21 20:17, Lukas Wunner wrote:
quoted
On Mon, Dec 27, 2021 at 12:35:50AM +0900, Hector Martin wrote:
quoted
# On firmware
As you might expect, the firmware for these machines is not available
under a redistributable license; however, every owner of one of these
machines *is* implicitly licensed to posess the firmware, and the OS
packages containing it are available under well-known URLs on Apple's
CDN with no authentication.
Apple's EFI firmware contains a full-fledged network stack for
downloading macOS images from osrecovery.apple.com. I suspect
that it also contains wifi firmware.
You may want to check if it's passed to the OS as an EFI property.
Using that would sidestep license issues. There's EDID data,
Thunderbolt DROM data and whatnot in those properties, so I
wouldn't be surprised if it contained wifi stuff as well.
Enable CONFIG_APPLE_PROPERTIES and pass "dump_apple_properties"
on the command line to see all EFI properties in dmesg.
Alternatively, check "ioreg -l" on macOS. Generally, what's
available in the I/O registry should also be available on Linux
either as an ACPI or EFI property.
Interesting, note that even if the files are not available as
a property we also have CONFIG_EFI_EMBEDDED_FIRMWARE, see:
drivers/firmware/efi/embedded-firmware.c
Documentation/driver-api/firmware/fallback-mechanisms.rst
I wrote this to pry/dig out some touchscreen firmwares (where
we have been unable to get permission to redistribute) out of
EFI boot_services_code mem regions on tablets where
the touchsceen is supported under the EFI environment.
This may need some tweaks, but if there is an embedded copy
of the firmware files in the EFI mem regions somewhere it
should be possible to adjust this code to grab it and present
it to the firmware-loader mechanism as a fallback option.
Note that this wouldn't work on M1 Macs anyway, since those don't have
EFI (we provide EFI via U-Boot as a chained bootloader on those), and
their bootloader doesn't support any networking (it doesn't even do USB
or any kind of UI).
Quick recap for those not familiar with the M1 boot process: the
bootloader is iBoot, which is extremely simple (at least compared to
EFI). All it can do is boot kernels from APFS volumes on internal NVMe.
The boot selection menu and recovery options are implemented as macOS
apps running from a recovery image (~1GB), and "USB boot" is implemented
by copying the macOS equivalent of /boot to NVMe. There is a global
recovery image as well as per-OS recovery image. The WiFi firmware is
present in this image as well as on normal macOS root volumes.
Our Linux install script is actually mostly a macOS install script that
sets up all the boot components that macOS would normally have,
including the recovery image, minus the main root filesystem. This is
all required to work properly within Apple's security and multi-boot
framework. So, since we're installing the recovery image, we're already
in an easy position to pull the firmware out and stick it in the EFI
partition for Linux to easily use. The alternative would be for Linux
userspace to read it from APFS directly, but that seems unlikely to be
practical until linux-apfs is upstreamed.
For T2 Macs I'm sure the firmware will be in EFI somewhere, but even if
we can get it from there (I wouldn't be surprised if it's e.g. still
compressed in the normal boot path that doesn't start network services),
I'm not sure it's worth implementing yet another mechanism for those
machines. Once we have the vendor-firmware mechanism implemented for M1,
it's easy to just run the same script on T2s and get the proper firmware
from macOS (which might even be different from the EFI firmware...).
macOS definitely doesn't read the firmware from EFI on those machines,
so a hack to do it by scanning the code would probably not be something
we can rely on to continue working across firmware updates (and they do
update WiFi firmware; it's a rather well known source of security
issues... so then we'd have to play the update-the-sha256 cat and mouse
game). I'm pretty sure there's no property containing the big firmware
blob passed explicitly to the OS; it has its own copy.
--
Hector Martin (marcan@marcan.st)
Public Key: https://mrcn.st/pub
From: Rob Herring <robh@kernel.org> Date: 2021-12-27 16:36:40
On Mon, Dec 27, 2021 at 12:35:51AM +0900, Hector Martin wrote:
quoted hunk
This binding is currently used for SDIO devices, but these chips are
also used as PCIe devices on DT platforms and may be represented in the
DT. Re-use the existing binding and add chip compatibles used by Apple
T2 and M1 platforms (the T2 ones are not known to be used in DT
platforms, but we might as well document them).
Then, add properties required for firmware selection and calibration on
M1 machines.
Signed-off-by: Hector Martin <redacted>
---
.../net/wireless/brcm,bcm4329-fmac.yaml | 32 +++++++++++++++++--
1 file changed, 29 insertions(+), 3 deletions(-)
@@ -4,7 +4,7 @@$id:http://devicetree.org/schemas/net/wireless/brcm,bcm4329-fmac.yaml#$schema:http://devicetree.org/meta-schemas/core.yaml#-title:Broadcom BCM4329 family fullmac wireless SDIO devices+title:Broadcom BCM4329 family fullmac wireless SDIO/PCIE devicesmaintainers:-Arend van Spriel <arend@broadcom.com>
@@ -36,16 +36,22 @@ properties:-brcm,bcm43455-fmac-brcm,bcm43456-fmac-brcm,bcm4354-fmac+-brcm,bcm4355c1-fmac-brcm,bcm4356-fmac-brcm,bcm4359-fmac+-brcm,bcm4364b2-fmac+-brcm,bcm4364b3-fmac+-brcm,bcm4377b3-fmac+-brcm,bcm4378b1-fmac+-brcm,bcm4387c2-fmac-cypress,cyw4373-fmac-cypress,cyw43012-fmac-const:brcm,bcm4329-fmac-const:brcm,bcm4329-fmacreg:-description:SDIO function number for the device, for most cases-this will be 1.+description:SDIO function number for the device (for most cases+this will be 1) or PCI device identifier.interrupts:maxItems:1
@@ -75,6 +81,26 @@ properties:items:pattern:'^[A-Z][A-Z]-[A-Z][0-9A-Z]-[0-9]+$'+brcm,cal-blob:+$ref:/schemas/types.yaml#/definitions/uint8-array+description:A per-device calibration blob for the Wi-Fi radio. This+should be filled in by the bootloader from platform configuration+data, if necessary, and will be uploaded to the device if present.++apple,module-instance:+$ref:/schemas/types.yaml#/definitions/string+description:Module codename used to identify a specific board on+Apple platforms. This is used to build the firmware filenames, to allow+different platforms to have different firmware and/or NVRAM config.++apple,antenna-sku:+$def:/schemas/types.yaml#/definitions/string+description:Antenna SKU used to identify a specific antenna configuration+on Apple platforms. This is use to build firmware filenames, to allow+platforms with different antenna configs to have different firmware and/or+NVRAM. This would normally be filled in by the bootloader from platform+configuration data.
Is there a known set of strings that can be defined?
There's also the somewhat standard 'firmware-name' property that serves
similar purpose, but if there's multiple files, then I guess this
approach is fine.
Rob
From: Hector Martin <hidden> Date: 2021-12-27 17:23:18
On 28/12/2021 01.36, Rob Herring wrote:
On Mon, Dec 27, 2021 at 12:35:51AM +0900, Hector Martin wrote:
quoted
+ brcm,cal-blob:+ $ref: /schemas/types.yaml#/definitions/uint8-array+ description: A per-device calibration blob for the Wi-Fi radio. This+ should be filled in by the bootloader from platform configuration+ data, if necessary, and will be uploaded to the device if present.++ apple,module-instance:+ $ref: /schemas/types.yaml#/definitions/string+ description: Module codename used to identify a specific board on+ Apple platforms. This is used to build the firmware filenames, to allow+ different platforms to have different firmware and/or NVRAM config.++ apple,antenna-sku:+ $def: /schemas/types.yaml#/definitions/string+ description: Antenna SKU used to identify a specific antenna configuration+ on Apple platforms. This is use to build firmware filenames, to allow+ platforms with different antenna configs to have different firmware and/or+ NVRAM. This would normally be filled in by the bootloader from platform+ configuration data.
Is there a known set of strings that can be defined?
For apple,module-instance there is, though it will grow with every new
machine. If you're happy with me pushing updates to this through
asahi-soc I can keep it maintained as we add DTs and compatibles there.
I'm curious whether you prefer this approach or something like
brcm,board-name instead. Right now we do:
apple,module-instance = "honshu"
That gets converted to board_name="apple,honshu" in the code, which is
what the firmwares are named after (plus extra info later appended, if
the rest of the Apple data is available).
But we could also do:
brcm,board-name = "apple,honshu"
The latter would be more generically useful for other platforms, since
it would allow e.g. having DTs for different boards that use the same
WiFi module/subsystem and thus a compatible NVRAM fw file alias to the
same file name (right now this is done with symlinks in /lib/firmware,
one for each equivalent board). For non-Apple platforms (i.e. if
antenna-sku and/or the OTP aren't available to do the funky Apple
firmware selection), this just ends up replacing what would normally be
the OF root node compatible in the firmware filename.
E.g. right now we have:
brcmfmac43430-sdio.AP6212.txt
brcmfmac43430-sdio.raspberrypi,3-model-b.txt
brcmfmac43430-sdio.raspberrypi,model-zero-w.txt -> brcmfmac43430-sdio.raspberrypi,3-model-b.txt
brcmfmac43430-sdio.sinovoip,bpi-m2-plus.txt -> brcmfmac43430-sdio.AP6212.txt
brcmfmac43430-sdio.sinovoip,bpi-m2-ultra.txt -> brcmfmac43430-sdio.AP6212.txt
brcmfmac43430-sdio.sinovoip,bpi-m2-zero.txt -> brcmfmac43430-sdio.AP6212.txt
brcmfmac43430-sdio.sinovoip,bpi-m3.txt -> brcmfmac43430-sdio.AP6212.txt
And this could allow the sinovoip.* DTs to say:
brcm,board-name = "AP6212";
And the rPi zero one:
brcm,board-name = "raspberrypi,3-model-b";
And avoid the symlinks.
The antenna-sku thing is specific to the Apple firmware selection
process and doesn't make sense as a more generic property.
antenna-sku right now always seems to be one of "ID", "X0", "X2", "X3",
though that could presumably change in the future. I can add this to the
binding if you want, though since this will be filled in by the
bootloader from platform data we wouldn't be validating it anyway. Not
sure if it's worth it.
There's also the somewhat standard 'firmware-name' property that
serves similar purpose, but if there's multiple files, then I guess
this approach is fine.
Yeah, and the firmware name is constructed using non-DT information too
(and we have several attempted filenames times several firmware types),
so it wouldn't be complete.
--
Hector Martin (marcan@marcan.st)
Public Key: https://mrcn.st/pub
On Sun, Dec 26, 2021 at 4:37 PM Hector Martin [off-list ref] wrote:
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.
First, add support for having multiple alternate firmware paths.
Signed-off-by: Hector Martin <redacted>
This looks OK to me so FWIW:
Acked-by: Linus Walleij <redacted>
Make sure Dmitry Osipenko gets to review this though, he has many
valuable insights about how the FW is loaded and helped me out a
lot when I patched this.
Yours,
Linus Walleij
On Sun, Dec 26, 2021 at 4:37 PM Hector Martin [off-list ref] wrote:
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.
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:37 PM Hector Martin [off-list ref] wrote:
On Apple platforms, the One Time Programmable ROM in the Broadcom chips
contains information about the specific board design (module, vendor,
version) that is required to select the correct NVRAM file. Parse this
OTP ROM and extract the required strings.
Note that the user OTP offset/size is per-chip. This patch does not add
any chips yet.
Signed-off-by: Hector Martin <redacted>
This variable name "module_params" is a bit confusing since loadable
kernel modules have params...
Can we think of another name and just put a comment that this
refers to the WiFi module building block?
Sometimes people talk about SoM:s (system-on-modules), so
maybe som_params or brcm_som_params?
Yours,
Linus Walleij
On Sun, Dec 26, 2021 at 4:37 PM Hector Martin [off-list ref] wrote:
On Apple ARM64 platforms, firmware selection requires two properties
that come from system firmware: the module-instance (aka "island", a
codename representing a given hardware platform) and the antenna-sku.
The module-instance is hard-coded in per-board DTS files, while the
antenna-sku is forwarded by our bootloader from the Apple Device Tree
into the FDT. Grab them from the DT so firmware selection can use
them.
The module-instance is used to construct a board_type by prepending it
with "apple,".
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:37 PM Hector Martin [off-list ref] wrote:
On Apple platforms, firmware selection uses the following elements:
Property Example Source
============== ======= ========================
* Chip name 4378 Device ID
* Chip revision B1 OTP
* Platform shikoku DT (ARM64) or ACPI (x86)
* Module type RASP OTP
* Module vendor m OTP
* Module version 6.11 OTP
* Antenna SKU X3 DT (ARM64) or ??? (x86)
In macOS, these firmwares are stored using filenames in this format
under /usr/share/firmware/wifi:
C-4378__s-B1/P-shikoku-X3_M-RASP_V-m__m-6.11.txt
To prepare firmwares for Linux, we rename these to a scheme following
the existing brcmfmac convention:
brcmfmac<chip><lower(rev)>-pcie.apple,<platform>-<mod_type>-\
<mod_vendor>-<mod_version>-<antenna_sku>.txt
The NVRAM uses all the components, while the firmware and CLM blob only
use the chip/revision/platform/antenna_sku:
brcmfmac<chip><lower(rev)>-pcie.apple,<platform>-<antenna_sku>.bin
e.g.
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m-6.11-X3.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-X3.bin
In addition, since there are over 1000 files in total, many of which are
symlinks or outright duplicates, we deduplicate and prune the firmware
tree to reduce firmware filenames to fewer dimensions. For example, the
shikoku platform (MacBook Air M1 2020) simplifies to just 4 files:
brcm/brcmfmac4378b1-pcie.apple,shikoku.clm_blob
brcm/brcmfmac4378b1-pcie.apple,shikoku.bin
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-u.txt
This reduces the total file count to around 170, of which 75 are
symlinks and 95 are regular files: 7 firmware blobs, 27 CLM blobs, and
61 NVRAM config files. We also slightly process NVRAM files to correct
some formatting issues and add a missing default macaddr= property.
To handle this, the driver must try the following path formats when
looking for firmware files:
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m-6.11-X3.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m-6.11.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP-m.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-RASP.txt
brcm/brcmfmac4378b1-pcie.apple,shikoku-X3.txt *
brcm/brcmfmac4378b1-pcie.apple,shikoku.txt
* Not relevant for NVRAM, only for firmware/CLM.
The chip revision nominally comes from OTP on Apple platforms, but it
can be mapped to the PCI revision number, so we ignore the OTP revision
and continue to use the existing PCI revision mechanism to identify chip
revisions, as the driver already does for other chips. Unfortunately,
the mapping is not consistent between different chip types, so this has
to be determined experimentally.
Signed-off-by: Hector Martin <redacted>
It's a neat hack, and I don't see anyone doing anything smarter so:
Reviewed-by: Linus Walleij <redacted>
Yours,
Linus Walleij
On Sun, Dec 26, 2021 at 4:37 PM Hector Martin [off-list ref] wrote:
On Device Tree platforms, it is customary to be able to set the MAC
address via the Device Tree, as it is often stored in system firmware.
This is particularly relevant for Apple ARM64 platforms, where this
information comes from system configuration and passed through by the
bootloader into the DT.
Implement support for this by fetching the platform MAC address and
adding or replacing the macaddr= property in nvram. This becomes the
dongle's default MAC address.
On platforms with an SROM MAC address, this overrides it. On platforms
without one, such as Apple ARM64 devices, this is required for the
firmware to boot (it will fail if it does not have a valid MAC at all).
Signed-off-by: Hector Martin <redacted>
This looks very helpful.
quoted hunk
+ /* Add space for properties we may add */+ size += strlen(BRCMF_FW_DEFAULT_BOARDREV) + 1;+ size += BRCMF_FW_MACADDR_LEN + 1;
Add some note to the commit log why you also make space for
boardrev? (Looks useful.) Is the boardrev spacing in the right
patch?
With that addressed:
Reviewed-by: Linus Walleij <redacted>
Yours,
Linus Walleij
On Sun, Dec 26, 2021 at 4:38 PM Hector Martin [off-list ref] wrote:
Newer chips used on Apple platforms have more than max_rxbufpost greater
than 512, which causes warnings when brcmf_msgbuf_rxbuf_data_fill tries
to put more in the ring than fit. Increase the ring sizes to 1024.
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:38 PM Hector Martin [off-list ref] wrote:
The driver was enabling IRQs before the message processing was
initialized. This could cause IRQs to come in too early and crash the
driver. Instead, move the IRQ enable and hostready to a bus preinit
function, at which point everything is properly initialized.
Fixes: 9e37f045d5e7 ("brcmfmac: Adding PCIe bus layer support.")
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:38 PM Hector Martin [off-list ref] wrote:
These newer PCIe core revisions include new sets of registers that must
be used instead of the legacy ones. Introduce a brcmf_pcie_reginfo to
hold the specific register offsets and values to use for a given
platform, and change all the register accesses to indirect through it.
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:38 PM Hector Martin [off-list ref] wrote:
On DT platforms, the module-instance and antenna-sku-info properties
are passed in the DT. On ACPI platforms, module-instance is passed via
the analogous Apple device property mechanism, while the antenna SKU
info is instead obtained via an ACPI method that grabs it from
non-volatile storage.
Add support for this, to allow proper firmware selection on Apple
platforms.
Signed-off-by: Hector Martin <redacted>
If the strings treated here are exactly the same as for the device tree,
you should be able to just use "devprops" (firmware node) to handle it
abstractly, and then the respective DT and ACPI backend will provide
the properties.
I don't know if this patch I made recently is enough of an examples:
https://lore.kernel.org/linux-hwmon/20211206020423.62402-2-linus.walleij@linaro.org/
If the ACPI and DT differs a lot in format and strings etc it may not
be worth it.
Yours,
Linus Walleij
On Sun, Dec 26, 2021 at 4:38 PM Hector Martin [off-list ref] wrote:
Newer Apple firmwares on chipsets without a hardware RNG require the
host to provide a buffer of 256 random bytes to the device on
initialization. This buffer is present immediately before NVRAM,
suffixed by a footer containing a magic number and the buffer length.
This won't affect chips/firmwares that do not use this feature, so do it
unconditionally.
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:39 PM Hector Martin [off-list ref] wrote:
This chip is present on at least these Apple T2 Macs:
* hawaii: MacBook Air 13" (Late 2018)
* hawaii: MacBook Air 13" (True Tone, 2019)
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:39 PM Hector Martin [off-list ref] wrote:
This chip is present on at least these Apple T2 Macs:
* tahiti: MacBook Pro 13" (2020, 2 TB3)
* formosa: MacBook Pro 13" (Touch/2019)
* fiji: MacBook Air 13" (Scissor, 2020)
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:39 PM Hector Martin [off-list ref] wrote:
This chip exists in two revisions (B2=r3 and B3=r4) on different
platforms, and was added without regard to doing proper firmware
selection or differentiating between them. Fix this to have proper
per-revision firmwares and support Apple NVRAM selection.
Revision B2 is present on at least these Apple T2 Macs:
kauai: MacBook Pro 15" (Touch/2018-2019)
maui: MacBook Pro 13" (Touch/2018-2019)
lanai: Mac mini (Late 2018)
ekans: iMac Pro 27" (5K, Late 2017)
And these non-T2 Macs:
nihau: iMac 27" (5K, 2019)
Revision B3 is present on at least these Apple T2 Macs:
bali: MacBook Pro 16" (2019)
trinidad: MacBook Pro 13" (2020, 4 TB3)
borneo: MacBook Pro 16" (2019, 5600M)
kahana: Mac Pro (2019)
kahana: Mac Pro (2019, Rack)
hanauma: iMac 27" (5K, 2020)
kure: iMac 27" (5K, 2020, 5700/XT)
Fixes: 24f0bd136264 ("brcmfmac: add the BRCM 4364 found in MacBook Pro 15,2")
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:39 PM Hector Martin [off-list ref] wrote:
At least on BCM4387, the D11 cores are held in reset on cold startup and
firmware expects to release reset itself. Just assert reset here and let
firmware deassert it. Premature deassertion results in the firmware
failing to initialize properly some of the time, with strange AXI bus
errors.
Also, BCM4387 has 3 cores, up from 2. The logic for handling that is in
brcmf_chip_ai_resetcore(), but since we aren't using that any more, just
handle it here.
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:39 PM Hector Martin [off-list ref] wrote:
BCM4387 has trailing odd-sized blocks as part of TCM which have
their size described as a multiple of 1024 instead of 8192. Handle this
so we can compute the TCM size properly.
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:39 PM Hector Martin [off-list ref] wrote:
The "wlc_ver" iovar returns information on the WLC and EPI versions.
This can be used to determine whether the PMKID_V2 and _V3 features are
supported.
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:39 PM Hector Martin [off-list ref] wrote:
Add support for the new PMKID_V3 API, which allows performing PMKID
mutations individually, instead of requiring the driver to keep track of
the full list. This new API is required by at least BCM4387.
Note that PMKID_V2 is not implemented yet.
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:40 PM Hector Martin [off-list ref] wrote:
Apparently the hex passphrase mechanism does not work on newer
chips/firmware (e.g. BCM4387). It seems there was a simple way of
passing it in binary all along, so use that and avoid the hexification.
OpenBSD has been doing it like this from the beginning, so this should
work on all chips.
Also clear the structure before setting the PMK. This was leaking
uninitialized stack contents to the device.
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:40 PM Hector Martin [off-list ref] wrote:
The alignment check was wrong (e.g. & 4 instead of & 3), and the logic
was also inefficient if the length was not a multiple of 4, since it
would needlessly fall back to copying the entire buffer bytewise.
We already have a perfectly good memcpy_toio function, so just call that
instead of rolling our own copy logic here. brcmf_pcie_init_ringbuffers
was already using it anyway.
Fixes: 9e37f045d5e7 ("brcmfmac: Adding PCIe bus layer support.")
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:40 PM Hector Martin [off-list ref] wrote:
This allows us to get console messages if the firmware crashed during
early init, or if an operation failed and we're about to shut down.
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:40 PM Hector Martin [off-list ref] wrote:
This avoids leaking memory if brcmf_chip_get_raminfo fails. Note that
the CLM blob is released in the device remove path.
Fixes: 82f93cf46d60 ("brcmfmac: get chip's default RAM info during PCIe setup")
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:40 PM Hector Martin [off-list ref] wrote:
The TxCap blobs are additional data blobs used on Apple devices, and
are uploaded analogously to CLM blobs. Add core support for doing this.
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:41 PM Hector Martin [off-list ref] wrote:
These blobs are named .txcap_blob, and exist alongside the existing
.clm_blob files. Use the existing firmware machinery to provide them to
the core.
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:41 PM Hector Martin [off-list ref] wrote:
The calibration blob for a chip is normally stored in SROM and loaded
internally by the firmware. However, Apple ARM64 platforms instead store
it as part of platform configuration data, and provide it via the Apple
Device Tree. We forward this into the Linux DT in the bootloader.
Add support for taking this blob from the DT and loading it into the
dongle. The loading mechanism is the same as used for the CLM and TxCap
blobs.
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:38 PM Hector Martin [off-list ref] wrote:
The Wi-Fi module in Apple machines has a "module-instance" device
property that specifies the platform type and is used for firmware
selection. Its value is a string, so add support for string values in
acpi_extract_apple_properties().
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:37 PM Hector Martin [off-list ref] wrote:
Now that the firmware fetcher can handle per-board CLM files, load the
CLM blob alongside the other firmware files and change the bus API to
just return the existing blob, instead of fetching the filename.
This enables per-board CLM blobs, which are required on Apple platforms.
Signed-off-by: Hector Martin <redacted>
On Sun, Dec 26, 2021 at 4:39 PM Hector Martin [off-list ref] wrote:
This new API version is required for at least the BCM4387 firmware. Add
support for it, with a fallback to the v1 API.
Signed-off-by: Hector Martin <redacted>