If you’re running OpenWrt on a Raspberry Pi 5 with a USB-to-Ethernet adapter based on the Realtek RTL8153B chipset, you may have noticed that the adapter stops working after a power outage. It works fine after a manual unplug/replug, but never comes up on its own after a cold boot. Here’s why, and how to fix it permanently.
The Problem
Many RTL8153B-based USB Ethernet adapters (including models from TP-Link, Ugreen, and others) use a dual-mode design. When first plugged in, they present themselves as a USB CD-ROM drive (product ID 0bda:8151) containing a Windows driver installer. A special kernel driver called r8152-cfgselector is supposed to intercept this, switch the device to Ethernet mode (product ID 0bda:8153), and hand it off to the r8152 network driver.
The problem is a boot-time race condition. On the Raspberry Pi 5 running OpenWrt, the USB device enumerates at around t=4s during boot, but r8152-cfgselector doesn’t load until t=8-25s (it varies between boots). In that gap, the usb-storage driver claims the device as a CD-ROM, and the Ethernet driver never gets a chance.
You can confirm this by checking dmesg after a cold boot:
When you manually unplug and replug the adapter, r8152-cfgselector is already loaded and intercepts the device before usb-storage can grab it. That’s why a replug always fixes it.
What Doesn’t Work
Before finding the real fix, I tried several approaches that all failed:
1. OpenWrt Hotplug Script (/etc/hotplug.d/usb/)
I wrote a script to detect 0bda:8151 and trigger a USB reset. It never fired. OpenWrt’s hotplug.json (procd) short-circuits USB device events – when a USB device has MAJOR/MINOR set (which all USB devices do), it takes the makedev code path and returns before reaching the generic hotplug-call dispatcher. Scripts in /etc/hotplug.d/usb/ are simply never executed for USB device add events on OpenWrt.
2. Init.d Script with USB Deauthorize/Reauthorize
I created an init.d service that waited for the device, detected 8151 mode, unbound it from usb-storage, then deauthorized/reauthorized the USB port to trigger re-enumeration. The script ran correctly (confirmed by syslog), but the deauthorize/reauthorize cycle doesn’t actually power-cycle the USB hardware on the Raspberry Pi 5. The device kept its internal state and re-enumerated in CD-ROM mode again, with usb-storage immediately reclaiming it.
3. Kernel Quirk Alone (usb-storage.quirks=0bda:8151:i)
Adding usb-storage.quirks=0bda:8151:i to /boot/cmdline.txt successfully prevents usb-storage from claiming the device (dmesg shows “device ignored”). However, this alone is not enough. When r8152-cfgselector loads later, it does not probe already-present unclaimed devices – it only acts on new USB attach events. So the device just sits there unclaimed in CD-ROM mode, and nothing ever switches it to Ethernet.
The Fix (Two Parts)
The complete solution requires two things working together:
Part 1: Kernel Boot Parameter
Edit /boot/cmdline.txt and append:
| |
The i flag means ignore – the kernel will prevent usb-storage from ever binding to 0bda:8151. The full line should look something like:
| |
Important: Everything must stay on a single line.
This prevents usb-storage from grabbing the device, but we still need to force a re-enumeration after r8152-cfgselector loads.
Part 2: Init.d Script with USB Port Disable/Enable
The key insight: the RPi5’s xHCI controller exposes a disable sysfs entry for each USB hub port. Writing 1 to it physically disconnects the device from the bus. Writing 0 back re-enables the port and triggers a fresh enumeration – equivalent to a physical unplug/replug.
Create /etc/init.d/fix-rtl8153:
| |
Then make it executable and enable it:
The script runs at START=19 (before network at 20), backgrounds itself so it doesn’t block boot, and:
- Waits for the USB device to appear on bus 3 or bus 4
- Checks if it’s stuck in CD-ROM mode (
idProduct = 8151) - Waits for
r8152-cfgselectorto load - Disables both USB 2.0 and USB 3.0 sides of the port (the RPi5’s xHCI controller uses paired buses for the same physical port)
- Waits 2 seconds for the device firmware to reset
- Re-enables both port sides, triggering fresh enumeration
- Verifies
eth1comes up with carrier within 15 seconds - If it doesn’t, retries the full cycle once more
Why This Works
The RTL8153B’s dual-mode behavior is identical to how old 3G USB modems worked – they’d present a virtual CD-ROM with Windows drivers, and usb_modeswitch would switch them to modem mode.
The kernel quirk prevents usb-storage from claiming the device, so it sits unclaimed. The init.d script then does the equivalent of a physical unplug/replug by disabling and re-enabling the USB port through sysfs. When the device re-enumerates, r8152-cfgselector is already loaded and intercepts it, switches the USB configuration, and the r8152 Ethernet driver takes over.
The reason we need both parts: the kernel quirk alone leaves the device unclaimed (cfgselector doesn’t probe existing devices), and the port cycle alone doesn’t help if usb-storage reclaims the device on re-enumeration.
Debugging
After a power cycle, check if the fix ran:
| |
You should see something like:
Environment
- Raspberry Pi 5
- OpenWrt 24.10.4 (
bcm27xx/bcm2712) - Kernel 6.6.110
- USB Ethernet adapter: Realtek RTL8153B (
0bda:8151/0bda:8153) - Connected via the RPi5’s USB 3.0 xHCI controller (
xhci-hcd.1, bus 3/4)
TL;DR
- Add
usb-storage.quirks=0bda:8151:ito/boot/cmdline.txt - Create the init.d script above that does a USB port disable/enable cycle after
r8152-cfgselectorloads - Reboot. Your RTL8153B USB Ethernet adapter will survive power outages without needing a manual replug.