Files
bwn-a1370/README.md
T
bwn-a1370 a8418431bb bwn BCM43224 (MacBook Air A1370) driver fixes for FreeBSD 15.1
Patches + build scripts + firmware sources to make the Broadcom BCM43224
(PCI 0x14e4:0x4353, subvendor 0x106b:0x00d1) work on FreeBSD 15.1.

Fixes:
- Fix 1: compile GPL N-PHY code (BWN_GPL_PHY build wiring)
- Fix 2: NULL-guard bwn_dma_ringfree on partial attach
- Fix 3: wire bwn_update_mcast to ic->ic_update_mcast
- Fix 5: load bwn_v4_n firmware at loader stage (loader.conf)
- Fix 6: reclaim pending TX frames at bwn_dma_stop (detach double-free)
- Fix 7: driver-owned node ref + remove dr_usedslot early-return +
        bhndb_pci BHNDB_PCI_QUIRK_NO_MSI for BCM43224 (legacy INTx)
- Fix 8: restrict reclaim to TX rings only (RX reclaim caused heap
        corruption / TCP panic)

README.md  = rebuild guide (apply.sh + build.sh, manual steps)
RESEARCH.md = root-cause investigation log (Fixes 5-8)
2026-08-16 16:08:44 +03:00

5.1 KiB

bwn driver fixes for Broadcom BCM43224 (Apple MacBook Air A1370)

A complete, self-contained set of fixes that make the FreeBSD bwn(4) driver work on the Apple MacBook Air A1370's BCM43224 (PCI 0x14e4:0x4353, subvendor 0x106b:0x00d1) 802.11a/b/g/n chip.

The driver has been tested through multiple kldunload/kldload cycles and reboots on the target hardware with no panic.

Build & install (clean FreeBSD 15.1)

You need the FreeBSD 15.1 source tree at /usr/src (or pass an alternate SRC_ROOT to the scripts). Then, as root:

cd bwn-a1370
sudo ./apply.sh            # patch /usr/src  (or: sudo ./apply.sh /path/to/src)
sudo ./build.sh            # build + install if_bwn.ko, bhndb_pci.ko, bwn_v4_n.ko
reboot

After reboot, bring up the interface:

ifconfig wlan create wlandev bwn0 [wap]
# or, to join a WPA network, create the wlan and run wpa_supplicant as usual

build.sh installs everything for the next boot; it does not touch the running kernel, so an active session (e.g. SSH over a fallback rtwn0/wlan0 interface) is never disrupted.

What the scripts do

  • apply.sh — idempotently applies the 4 source patches to /usr/src (patches/patch-*.c and patches/patch-Makefile). Safe to re-run.
  • build.sh — builds if_bwn.ko (sys/modules/bwn), bhndb_pci.ko (sys/modules/bhnd/bhndb_pci), and bwn_v4_n.ko (from src/firmware/); installs them to /boot/modules and /boot/kernel; and appends bwn_v4_n_load="YES" to /boot/loader.conf if missing (Fix 5).

Manual build (equivalent to build.sh)

SRC=/usr/src

# 1. driver
make -C $SRC/sys/modules/bwn SRCTOP=$SRC SYSDIR=$SRC/sys
install -m 444 $SRC/sys/modules/bwn/if_bwn.ko /boot/modules/

# 2. PCIe bridge (NO_MSI quirk)
make -C $SRC/sys/modules/bhnd/bhndb_pci SRCTOP=$SRC SYSDIR=$SRC/sys
install -m 444 $SRC/sys/modules/bhnd/bhndb_pci/bhndb_pci.ko /boot/kernel/

# 3. firmware
make -C src/firmware SRCTOP=$SRC SYSDIR=$SRC/sys
install -m 444 src/firmware/bwn_v4_n.ko /boot/modules/

# 4. loader.conf (Fix 5)
echo 'bwn_v4_n_load="YES"' >> /boot/loader.conf

Directory layout

bwn-a1370/
  README.md           This file (rebuild guide)
  RESEARCH.md         Root-cause investigation log (Fixes 5-8)
  apply.sh            Apply the 4 source patches to /usr/src (idempotent)
  build.sh            Build + install all 3 modules and add the loader.conf entry
  loader.conf.bwn     Snippet for /boot/loader.conf (Fix 5: load firmware at boot)
  patches/
    patch-if_bwn.c        Driver fixes (Fixes 1-4, 6-8)
    patch-Makefile        GPL PHY build wiring (Fix 1)
    patch-bhndb_pci.c     NO_MSI quirk for BCM43224 (Fix 7)
    patch-bhndb_pcivar.h  NO_MSI quirk definition (Fix 7)
    combined.patch        All of the above in one file (alternative to apply.sh)
  src/firmware/       Broadcom v4 firmware module (bwn_v4_n.ko) sources + Makefile
  rc.conf.backups/    Backups of loader.conf/rc.conf made by the scripts

What was broken (summary)

On a stock FreeBSD 15.1 system this chip (an N-PHY rev-23 core behind a BCMA/bhnd bus, attached via the bhndb_pci PCIe-G1 bridge) failed in several ways:

  1. The GPL N-PHY code is not compiled in (build wiring).
  2. A NULL ring pointer can be dereferenced on a partial attach.
  3. Multicast updates are not wired to ic->ic_update_mcast.
  4. Firmware is not found at attach (loader vs kld_list ordering).
  5. MSI interrupts are never delivered on this host (NVIDIA MCP89 bridge), so TX completions never run -> "device timeout" and the NIC never passes traffic.
  6. Detaching while a TX frame is pending double-frees an ieee80211_node (kernel panic).
  7. Reclaiming the RX ring at device-stop DMAs received frames into freed kernel memory -> heap corruption / TCP panic.
# Area Problem Fix
1 build GPL N-PHY code not compiled in BWN_GPL_PHY via opt_bwn.h; add 7 GPL PHY files to SRCS in modules/bwn/Makefile
2 bwn_dma_ringfree NULL ring deref on partial attach NULL-guard if (dr == NULL || *dr == NULL) return;
3 bwn_update_mcast mcast not updated wire to ic->ic_update_mcast
4 build.sh reload clobbered live iface unload/rebuild/reinstall/reload if_bwn only
5 /boot/loader.conf firmware not found at attach bwn_v4_n_load="YES" loads firmware at loader stage
6 bwn_dma_stop detach double-frees node (vmcore.4) reclaim pending TX frames (drop node refs) at device-stop
7 if_bwn + bhndb_pci node ref ownership + MSI never delivered (vmcore.5 / "device timeout") driver takes its own ieee80211_ref_node(); remove dr_usedslot early-return; BHNDB_PCI_QUIRK_NO_MSI for BCM43224 forces legacy INTx
8 bwn_dma_stop RX-ring reclaim -> heap corruption (vmcore.6) restrict reclaim to TX rings only (new bwn_dma_reclaim_tx())

Files modified in /usr/src

  • sys/dev/bwn/if_bwn.c
  • sys/modules/bwn/Makefile
  • sys/dev/bhnd/bhndb/bhndb_pci.c
  • sys/dev/bhnd/bhndb/bhndb_pcivar.h

(Plus the prebuilt bwn_v4_n.ko firmware, reproducible from src/firmware/.)

See RESEARCH.md for the full root-cause analysis behind each fix.