Debugging bwfm at pci

About me:

bwfm(4)

Broadcom FullMAC Wireless driver

  • 802.11 stack in firmware
  • PCI/SDIO/USB
linux OpenBSD NetBSD
brcmfmac -> bwfm -> bwfm
Broadcom bluerise@openbsd jmcneill
I ported bwfm at PCI

Common in laptops (this one)

Early problems:
bwfm at pci ...
panic
ddb> bt
gdb /path/to/netbsd.gdb
gdb> info line *(bwfm_attach+0x37)
if_bwfm_pci.c:1234
Easy! (easier)
Late problems:
HTTP OK
FTP OK
SSH NOT OK
HTTPS NOT OK
Ideas:
  • ssh -vvv
  • tcpdump
  • reading code
  • big packets broken?
Reduced test case
ping -s 100
ping -s 200
ping -s 300
...
for i in `jot 1000`; do ping -s $i ... ; done
Results: one packet test case!
ping -s 400OK
ping -s 600NOT OK
Printf debugging:
bwfm_pci_pktid_new(...)
{
+ printf("%s:%d\n", __func__, __LINE__);
..
}
bwfm_fill_rx_rings(...)
{
+ printf("%s:%d\n", __func__, __LINE__);
...
}
dmesg > dmesg.before
ping -s 400
dmesg > dmesg.after
diff dmesg.before dmesg.after
OK NOT OK
+[   45.811580] bwfm_pci_flowring_lookup:1669
+[   45.811580] bwfm_pci_ring_write_reserve:1258
+[   45.811580] bwfm_pci_ring_update_rptr:1159
+[   45.811580] bwfm_pci_pktid_new:936
+[   45.811580] length of mbuf chain before: 0
+[   45.811580] mp->m_pkthdr.len:392
+[   45.811580] mp->m_len:392
+[   45.811580] ds_len:392
+[   45.811580] bwfm_pci_ring_write_commit:1350
+[   45.871653] bwfm_pci_flowring_lookup:1669
+[   45.871653] bwfm_pci_ring_write_reserve:1258
+[   45.871653] bwfm_pci_ring_update_rptr:1159
+[   45.871653] bwfm_pci_pktid_new:936
+[   45.871653] length of mbuf chain before: 1
+[   45.871653] MCLGETI:334
+[   45.871653] mp->m_pkthdr.len:0
+[   45.871653] mp->m_len:0
+[   45.871653] ds_len:14
+[   45.871653] bwfm_pci_ring_write_commit:1350
NetBSD m_defrag ≠ OpenBSD m_defrag
Log Message:
bwfm has only one tx descriptor; limit mbuf chains to one segment.

PR kern/53287

Can't use m_defrag because it always yields two segments.

Discussion on tech-net:
https://mail-index.NetBSD.org/tech-net/2018/09/01/msg007031.html

Diagnosed and tested by maya.


To generate a diff of this commit:
cvs rdiff -u -r1.12 -r1.13 src/sys/dev/ic/bwfm.c
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/ic/bwfmvar.h
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/pci/if_bwfm_pci.c
cvs rdiff -u -r1.7 -r1.8 src/sys/dev/usb/if_bwfm_usb.c

Acknowledgments:

  • mlelstv, for ping -s suggestion
  • riastradh, finding problem too quickly, and working diff