1
0
Fork 0

Force-rebind bound-but-broken USB WiFi drivers in reprobe

This commit is contained in:
Brendan Szymanski 2026-07-13 13:15:06 -04:00
parent c82551723e
commit 1668ff73d8

View file

@ -8,26 +8,56 @@
# leaving the hardware driverless or degraded. Run from init at post-fs
# (i.e. after /vendor is mounted) via init.tart.wifi.rc, this script:
#
# 1. Re-probes every driverless USB interface, so a USB WiFi adapter that
# was plugged in at power-on (and whose driver probe failed on the
# missing firmware) gets a second probe that can now load firmware.
# 1. Force-rebinds known WiFi USB drivers, so a USB WiFi adapter that was
# plugged in at power-on (and whose firmware request failed on the
# missing /vendor mount) gets a second, working probe. Confirmed on
# hardware (2026-07-13) that mt76-family drivers do NOT fail probe() on
# a missing-firmware error -- they bind "successfully" and then loop
# forever retrying an MCU handshake that can never succeed, so a plain
# driverless-only reprobe (the previous version of this script) never
# touches them. Unbind+rebind is required regardless of bound state.
# 2. Rebinds the Broadcom Bluetooth serdev device, so hci_bcm reloads its
# .hcd patch firmware (e.g. brcm/SYN43711A0.hcd). Without the patch the
# .hcd patch firmware (e.g. brcm/BCM.hcd). Without the patch the
# controller runs with unpatched defaults, which cripples TX power/range.
# Confirmed on hardware: firmware build version goes 0000 -> 1000 after
# this rebind.
#
# Both operations are idempotent and safe: already-bound USB interfaces are
# skipped, and the BT rebind simply re-registers hci0 before the Bluetooth
# stack starts.
# Both operations are idempotent and safe to run more than once.
# 1. USB: ask the kernel to re-run driver matching for unbound interfaces
# (directories like 1-1:1.0 without a "driver" symlink). Two passes with a
# delay: a probe that was already in flight (started just before /vendor
# finished mounting) can still fail after the first pass runs; the second
# pass catches the interface it leaves behind.
# List of built-in USB WiFi driver names from tart_defconfig (see
# CONFIG_WLAN_VENDOR_MEDIATEK/_REALTEK/_ATH/_RALINK/_ZYDAS/CONFIG_MWIFIEX).
WIFI_USB_DRIVERS="mt7601u mt76x0u mt76x2u mt7921u mt7925u \
rt2500usb rt73usb rt2800usb \
rtl8187 rtl8xxxu rtw_8822bu rtw_8822cu rtw_8723du rtw_8821cu \
ath9k_htc carl9170 ar5523 \
zd1211rw mwifiex_usb"
is_wifi_driver() {
for d in $WIFI_USB_DRIVERS; do
[ "$d" = "$1" ] && return 0
done
return 1
}
# USB: for interfaces already bound to a known WiFi driver, force an
# unbind+rebind (their probe "succeeded" despite the firmware failure, so a
# driverless-only reprobe never reaches them). For genuinely unbound
# interfaces, just ask the kernel to re-run driver matching. Two passes with
# a delay: a probe already in flight when /vendor finished mounting can still
# fail after the first pass runs; the second pass catches what it leaves
# behind.
reprobe_usb() {
for intf in /sys/bus/usb/devices/*:*; do
[ -e "$intf/driver" ] && continue
echo "${intf##*/}" > /sys/bus/usb/drivers_probe 2>/dev/null
name="${intf##*/}"
if [ -e "$intf/driver" ]; then
drv="$(basename "$(readlink -f "$intf/driver")")"
if is_wifi_driver "$drv"; then
echo "$name" > "$intf/driver/unbind" 2>/dev/null
echo "$name" > /sys/bus/usb/drivers_probe 2>/dev/null
fi
else
echo "$name" > /sys/bus/usb/drivers_probe 2>/dev/null
fi
done
}
reprobe_usb