#7622·linux

Pi 5: NCM gadget (usb_f_ncm on dwc2) hard-locks the system during link-up with a macOS host

Author: JAKONLCreated Sep 13, 2026Updated Sep 13, 2026

Describe the bug

Binding a configfs gadget with a single ncm function on a Raspberry Pi 5 hard-locks the whole system as soon as a macOS host starts enumerating it. The last kernel messages are always the same three dwc2 lines (bound driver, high-speed, new address 1), then nothing: no oops, no soft-lockup report, and oops=panic panic=10 never fires, so the board needs a power cycle. Reproduced three times, identically, including once with RAM capped to 3 GB (mem=3G) to rule out DMA addressing above the controller's 32-bit reach. g_ether (ECM) on the same setup enumerates and passes traffic in both directions, so this is specific to the NCM function on dwc2/BCM2712.

Steps to reproduce the behaviour

  1. dtoverlay=dwc2,dr_mode=peripheral under [all] in config.txt; PSU_MAX_CURRENT=3000 in the EEPROM config so the Mac can see the gadget at all (see #6569).
  2. Boot with the Pi connected to an Apple Silicon Mac (macOS 26.6.2) by USB-C to USB-C, Pi powered by the Mac. g_ether enumerates fine at this point.
  3. Switch to NCM:
modprobe libcomposite usb_f_ncm
modprobe -r g_ether
cd /sys/kernel/config/usb_gadget && mkdir g1 && cd g1
echo 0x2e8a > idVendor; echo 0x0013 > idProduct; echo 0x0200 > bcdUSB
mkdir -p strings/0x409 configs/c.1/strings/0x409 functions/ncm.usb0
echo "Raspberry Pi Ltd." > strings/0x409/manufacturer; echo "Raspberry Pi USB Gadget" > strings/0x409/product
echo NCM > configs/c.1/strings/0x409/configuration; echo 250 > configs/c.1/MaxPower
echo 02:6c:cc:fa:69:4e > functions/ncm.usb0/host_addr; echo 02:6c:cc:fa:69:4f > functions/ncm.usb0/dev_addr
ln -s functions/ncm.usb0 configs/c.1/
echo 1000480000.usb > UDC
  1. The Mac resets the bus, assigns an address, reads descriptors, and shows the "Allow accessory to connect?" prompt (all fine). The Pi locks up hard a moment later, as the NCM function goes live and starts sending link notifications (see Logs). Full system lockup; only a power cycle recovers it.

Device (s)

Raspberry Pi 5

System

Raspberry Pi OS trixie (Debian 13), 8GB board
Linux blackbox 6.18.39+rpt-rpi-2712 #1 SMP PREEMPT Debian 1:6.18.39-1+rpt1 (2026-07-29) aarch64
(also reproduced on 6.18.34+rpt-rpi-2712)
Bootloader: 2026/05/26 16:01:25
Host: MacBook (Apple M2), macOS 26.6.2

Logs

With tp_printk on the kernel command line and events/gadget/enable=1, the gadget endpoint activity is printed to the kernel log and streamed over netconsole (eth0). This shows the hang is not during enumeration — descriptors are read, the address is set, the config is applied, and the function goes live. The system dies during the NCM link-up notification.

Tail of the capture, right before it goes silent:

usb_gadget_giveback_request: ep0: req ... length 8/8 ... status 0 --> 0
usb_ep_queue:                ep0: req ... length 0/0 ... status -115 --> 0
usb_gadget_giveback_request: ep0: req ... length 0/0 ... status 0 --> 0
usb_gadget_giveback_request: ep2in: req ... length 16/16 ... status 0 --> 0   # NCM notification sent
usb_ep_queue:                ep2in: req ... length 0/16 ... status -115 --> 0
usb_gadget_giveback_request: ep2in: req ... length 16/16 ... status 0 --> 0   # second notification sent
usb_ep_queue:                ep2in: req ... length 0/8  ... status -115 --> 0  # third notification queued
<complete silence, no oops, no further output>

Immediately before this, ep1out (bulk OUT) had ~16 requests queued at 16384 bytes each and ep2in (the interrupt/notification endpoint) was cycling 16-byte then 8-byte transfers — i.e. the CDC-NCM NETWORK_CONNECTION / SPEED_CHANGE notification sequence. The lockup happens as the function transitions to carrying data, not while the host is reading descriptors. g_ether (ECM) on the identical setup gets past this point and passes traffic.

ssh over both Wi-Fi and Ethernet drops at the same instant, so it is a full system lockup. A systemd-fed hardware watchdog (RuntimeWatchdogSec=15, BCM2835 WDT) did not reset the board — the lockup is hard enough that the reset path never runs — so recovery required a manual power cycle. No oops, no soft/hard-lockup report (neither detector is enabled in this kernel config).

Additional context

Motivation: g_ether/ECM is unusable with current macOS because AppleUserECM stops transmitting after ~150 frames per enumeration (Apple FB24614121, see raspberrypi/rpi-usb-gadget#27), and NCM is the only other Ethernet class macOS drives natively. I have not yet been able to test NCM against a Linux host on this board, so I cannot say whether the lockup is host-specific. Happy to test patches or capture more state; netconsole over the dongle is set up.

Full captures (netconsole output from the tracepoint run, and from the earlier mem=3G run): https://gist.github.com/JAKONL/59430a4cc738b689f71e3d225962e904