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)
This commit is contained in:
bwn-a1370
2026-08-16 16:08:44 +03:00
commit a8418431bb
26 changed files with 1168 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
KMOD= bwn_v4_n
FIRMWS= ucode16_mimo.fw:bwn_v4_ucode16_mimo \
n0initvals11.fw:bwn_v4_n0initvals11 \
n0bsinitvals11.fw:bwn_v4_n0bsinitvals11 \
n0initvals16.fw:bwn_v4_n0initvals16 \
n0bsinitvals16.fw:bwn_v4_n0bsinitvals16 \
n0initvals24.fw:bwn_v4_n0initvals24 \
n0bsinitvals24.fw:bwn_v4_n0bsinitvals24
.include <bsd.kmod.mk>
+3
View File
@@ -0,0 +1,3 @@
KMOD= bwn_v4_n
FIRMWS= ucode16_mimo.fw:bwn_v4_n_ucode16_mimo n0initvals11.fw:bwn_v4_n_n0initvals11 n0bsinitvals11.fw:bwn_v4_n_n0bsinitvals11 n0initvals16.fw:bwn_v4_n_n0initvals16 n0initvals24.fw:bwn_v4_n_n0initvals24 n0bsinitvals16.fw:bwn_v4_n_n0bsinitvals16 n0bsinitvals24.fw:bwn_v4_n_n0bsinitvals24
.include <bsd.kmod.mk>
+80
View File
@@ -0,0 +1,80 @@
/* * Automatically @generated */
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/linker.h>
#include <sys/firmware.h>
#include <sys/systm.h>
extern char _binary_ucode16_mimo_fw_start[], _binary_ucode16_mimo_fw_end[];
extern char _binary_n0initvals11_fw_start[], _binary_n0initvals11_fw_end[];
extern char _binary_n0bsinitvals11_fw_start[], _binary_n0bsinitvals11_fw_end[];
extern char _binary_n0initvals16_fw_start[], _binary_n0initvals16_fw_end[];
extern char _binary_n0bsinitvals16_fw_start[], _binary_n0bsinitvals16_fw_end[];
extern char _binary_n0initvals24_fw_start[], _binary_n0initvals24_fw_end[];
extern char _binary_n0bsinitvals24_fw_start[], _binary_n0bsinitvals24_fw_end[];
static int
bwn_v4_n_fw_modevent(module_t mod, int type, void *unused){ const struct firmware *fp;
const struct firmware *parent;
int error; switch (type) { case MOD_LOAD:
fp = firmware_register("bwn_v4_ucode16_mimo", _binary_ucode16_mimo_fw_start , (size_t)(_binary_ucode16_mimo_fw_end - _binary_ucode16_mimo_fw_start), 0, NULL);
if (fp == NULL)
goto fail_0;
parent = fp;
fp = firmware_register("bwn_v4_n0initvals11", _binary_n0initvals11_fw_start , (size_t)(_binary_n0initvals11_fw_end - _binary_n0initvals11_fw_start), 0, parent);
if (fp == NULL)
goto fail_1;
fp = firmware_register("bwn_v4_n0bsinitvals11", _binary_n0bsinitvals11_fw_start , (size_t)(_binary_n0bsinitvals11_fw_end - _binary_n0bsinitvals11_fw_start), 0, parent);
if (fp == NULL)
goto fail_2;
fp = firmware_register("bwn_v4_n0initvals16", _binary_n0initvals16_fw_start , (size_t)(_binary_n0initvals16_fw_end - _binary_n0initvals16_fw_start), 0, parent);
if (fp == NULL)
goto fail_3;
fp = firmware_register("bwn_v4_n0bsinitvals16", _binary_n0bsinitvals16_fw_start , (size_t)(_binary_n0bsinitvals16_fw_end - _binary_n0bsinitvals16_fw_start), 0, parent);
if (fp == NULL)
goto fail_4;
fp = firmware_register("bwn_v4_n0initvals24", _binary_n0initvals24_fw_start , (size_t)(_binary_n0initvals24_fw_end - _binary_n0initvals24_fw_start), 0, parent);
if (fp == NULL)
goto fail_5;
fp = firmware_register("bwn_v4_n0bsinitvals24", _binary_n0bsinitvals24_fw_start , (size_t)(_binary_n0bsinitvals24_fw_end - _binary_n0bsinitvals24_fw_start), 0, parent);
if (fp == NULL)
goto fail_6;
return (0);
fail_6:
(void)firmware_unregister("bwn_v4_n0initvals24");
fail_5:
(void)firmware_unregister("bwn_v4_n0bsinitvals16");
fail_4:
(void)firmware_unregister("bwn_v4_n0initvals16");
fail_3:
(void)firmware_unregister("bwn_v4_n0bsinitvals11");
fail_2:
(void)firmware_unregister("bwn_v4_n0initvals11");
fail_1:
(void)firmware_unregister("bwn_v4_ucode16_mimo");
fail_0:
return (ENXIO);
case MOD_UNLOAD:
error = firmware_unregister("bwn_v4_n0initvals11");
if (error)
return (error);
error = firmware_unregister("bwn_v4_n0bsinitvals11");
if (error)
return (error);
error = firmware_unregister("bwn_v4_n0initvals16");
if (error)
return (error);
error = firmware_unregister("bwn_v4_n0bsinitvals16");
if (error)
return (error);
error = firmware_unregister("bwn_v4_n0initvals24");
if (error)
return (error);
error = firmware_unregister("bwn_v4_n0bsinitvals24");
if (error)
return (error);
error = firmware_unregister("bwn_v4_ucode16_mimo");
return (error); } return (EINVAL);}static moduledata_t bwn_v4_n_fw_mod = { "bwn_v4_n_fw", bwn_v4_n_fw_modevent, 0};DECLARE_MODULE(bwn_v4_n_fw, bwn_v4_n_fw_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);MODULE_VERSION(bwn_v4_n_fw, 1);MODULE_DEPEND(bwn_v4_n_fw, firmware, 1, 1, 1);
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.