Linux kernel module r8152 new alias entry

How do I add more kernel aliases for a driver of hardware version that is newer?

My system details:

NAME="OpenWrt"
VERSION="21.02.0"
PRETTY_NAME="OpenWrt 21.02.0"
VERSION_ID="21.02.0"
BUILD_ID="r16279-5cc0535800"
OPENWRT_BOARD="bcm27xx/bcm2709"
OPENWRT_ARCH="arm_cortex-a7_neon-vfpv4"
OPENWRT_DEVICE_PRODUCT="Generic"
OPENWRT_DEVICE_REVISION="v0"
OPENWRT_RELEASE="OpenWrt 21.02.0 r16279-5cc0535800"

from /sys/kernel/debug/usb/devices

new hardware, not working, no driver associated, requires r8152

T:  Bus=01 Lev=02 Prnt=02 Port=02 Cnt=03 Dev#=  5 Spd=480  MxCh= 0
D:  Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  3
P:  Vendor=0bda ProdID=8153 Rev=f3.f0
S:  Manufacturer=Realtek
S:  Product=USB 10/100/1000 LAN
S:  SerialNumber=0F3F000001
C:  #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=200mA
I:  If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=00 **Driver=**
E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=83(I) Atr=03(Int.) MxPS=   2 Ivl=128ms
C:* #Ifs= 2 Cfg#= 2 Atr=a0 MxPwr=200mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=0d Prot=00 Driver=(none)
E:  Ad=83(I) Atr=03(Int.) MxPS=  16 Ivl=128ms
I:* If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=01 Driver=(none)
I:  If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=01 Driver=(none)
E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
C:  #Ifs= 2 Cfg#= 3 Atr=a0 MxPwr=200mA
I:  If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=06 Prot=00 Driver=
E:  Ad=83(I) Atr=03(Int.) MxPS=  16 Ivl=128ms
I:  If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=00 Driver=
I:  If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=
E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms

old hardware and working with r8152

T:  Bus=01 Lev=02 Prnt=02 Port=03 Cnt=04 Dev#=  6 Spd=480  MxCh= 0
D:  Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  2
P:  Vendor=0bda ProdID=8153 Rev=31.00
S:  Manufacturer=Realtek
S:  Product=USB 10/100/1000 LAN
S:  SerialNumber=001000001
C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=350mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=00 **Driver=r8152**
E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=83(I) Atr=03(Int.) MxPS=   2 Ivl=16ms
C:  #Ifs= 2 Cfg#= 2 Atr=a0 MxPwr=350mA
I:  If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=06 Prot=00 Driver=
E:  Ad=83(I) Atr=03(Int.) MxPS=  16 Ivl=16ms
I:  If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=00 Driver=
I:  If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=
E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms

new:

cat /sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3/1-1.3:2.1/modalias
usb:v0BDAp8153dF3F0dc00dsc00dp00ic0Aisc00ip01in01

old:

cat /sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.5/1-1.5:1.0/modalias
usb:v0BDAp5411d0104dc09dsc00dp02ic09isc00ip02in00

As I understand it, if I want to load the kernel module with a parameter I must use insmod. However when I try to run:

insmod r8152 alias=usb:v0BDAp8153dF3F0dc00dsc00dp00ic0Aisc00ip01in01

kern.warn kernel: [ 3412.755392] r8152: unknown parameter 'alias' ignored
kern.info kernel: [ 3412.853630] usb 1-1.4: reset high-speed USB device number 6 using dwc_otg
kern.info kernel: [ 3413.046156] r8152 1-1.4:1.0 eth1: v1.10.11
kern.info kernel: [ 3413.052535] usbcore: registered new interface driver r8152

What option do I have left to fix this at run time?

Will a more generic alias also be better for future hardware?

usb:v0BDAp8053d*dc*dsc*dp*icFFisc*ip*in*

I can confirm that this hardware works with kernel 5.18.15 on my i686 Arch Linux, after adding the additional udev rule.

What would be the equivalent in OpenWRT or am I onto the right path here with the kernel module needing to add a newer alias?

Ideally, the new USB IDs are just added to the source in form of a patch (mainline first, backported to OpenWrt - if necessary).

Where should I submit my request?

https://www.kernel.org/doc/html/latest/process/submitting-patches.html

okay I see, submit a patch to the kernel, not openwrt's version to include the alias into the driver?

I think this is giving me an idea. perhaps I can build the system with the version magic and simply add my alias in there, but this driver was installed as a package called kmod-usb-net-rtl8152.

if I try to build openwrt, how would I build the package? is there a guide that could perhaps help me with that? greatly appreciate the feedback.

It's easiest to test this on x86_64 and a general purpose distribution, to write the patch, you'll need to work with the current linux(-next) kernel git anyways, once merged you can request it for -stable backporting (after testing it in v5.10/ v5.15; and it'll appear in OpenWrt almost by magic).

I'm not sure whether this could help you to bind a specific driver to a device:
https://lwn.net/Articles/143397/

1 Like

The root cause of this problem is an unfortunate choice made in the Linux kernel a very long time ago. In contrast to most other systems, Linux will not always use the first available configuration if a device supports multiple alternatives. Linux prefers configurations with class functions over configurations with vendor specific functions (only the first function of each configuration is considered in case of a multi-function device). The background is probably the complete lack of support for vendor defined functions when this code was written. The problem today is that we cannot change it without breaking expected behaviour for all the devices and users having adapted to this.

The different configurations have a "C" prefix in the "devices" dump. Functions (or actually interfaces) are prefixed with "I". The active choices are marked with *

The failing device supports three configurations with one function each::

  1. vendor class, supported by the r8152 driver
  2. CDC NCM ("Network Control Model") class
  3. CDC ECM ("Ethernet Control Model") class

Your working device supports two configurations with one function each:

  1. vendor class, supported by the r8152 driver
  2. CDC ECM ("Ethernet Control Model") class

Give what I wrote above, we expect Linux to choose configuration #2 in both cases, ending up with an NCM device in the first case and an ECM device in the second. And this is what happens when Linux probes these devices.

Why is the second device then using configuration #1 supported by the r8152 driver? Because something has changed it back to that configuration after the initial probing. This "something" is the r8152 driver. The problem with that is that the r8152 driver doesn't support this device unless it's in configuration #1.

And now we finally get to the explanation why it works in one case and not in the other: To work around that problem, the r8152 driver pretends to support CDC ECM class devices too, provided they have a matching device ID. But tthe driver dioesn't pretend to support CDC NCM devices, which makes the hack fail to work with the first device.

Pretending to support a function just to get a chance to modify the USB device is a horrible hack and has always been so.. To make it fly, they also had to blacklist these devices in the CDC ECM class driver - causing that driver to carry a loing list of blacklisted device IDs. And even worse: Forcing that driver fail with these devices.

I'm really hoping we can avoid extending this hack to the CDC NCM driver. Or maybe that's too late? I don't follow the USB discussions closely anymore. Probably should...

Anyway, long story. Short solution: You should be able to make your device work with the r8152 driver by simply switching it to configuration #1. You can do that from the command line by something like

echo 1 >/sys/bus/usb/devices/1-1.3/bConfigurationValue

provided it is plugged into the same USB port you showed us above. Otherwise you'll have to adapt the 1-1.3 to the bus and port where the device is.

In theory, the device should also work as an NCM device if you install kmod-usb-net-cdc-ncm. But I assume there is a reason these devices want to be handled as vendor specific, and that you will lose some functionality with the class drivers.

Note that neither of these devices will work as ECM devices due to the mentioned blacklisting.

I believe it's time to figure out some generic and better workaround for this problem....

2 Likes

usb-modeswitch seems to operate at least partly in this space - could it be adapted to deal with this (even if not as a permanent solution)?

I would think so, yes. Some USB modems have similar requirements for switching to a non-default configuration, and I believe usbmode implements it. So you should be able to create a configuration supporting this,

As for a more generic solution: I see that there has been some improvements in the kernel wrt device specific USB device drivers (not the same as USB interface drivers - which is what almost every USB driver implements). I believe it's now possible to create a very tiny driver for each such device, replacing the generic driver doing all that messy configuration selection.

One could also imagine this as a quirk modifying the generic driver behaviour. But I don't think that's appropriate as long as the kernel already implements full userspace control. The reason that's not being used here is that the r8152 maintainer wanted an in-kernel solution. And look where that got us...

Some background https://lkml.org/lkml/2014/1/7/184

Thank you, this makes sense as to how I got it working in my x86/i686 system with systemd-udev

Fixing performance issues with Realtek RTL8156B 2.5GbE USB dongle in Ubuntu - CNX Software (cnx-software.com)

It is my first time seeing bConfigurationValue used in a udev rule. I have yet to understand how it all ties together.

This is the udev-rule referenced from the article I mentioned r8152/50-usb-realtek-net.rules at master · bb-qq/r8152 (github.com)

What you describe is exactly what I experienced. After I installed the kernel package kmod-usb-net-cdc-ncm, associated, and the device was not functional. No vlan worked. and the same thing happened on my i686 with udev. Until I managed to find the article mentioned earlier, that I need to change the driver to r8152, same as what the older version hardware already works with. From what I can tell, the udev rule changes bConfigurationValue to 1

# This is used to change the default configuration of Realtek USB ethernet adapters
ACTION!="add", GOTO="usb_realtek_net_end"
SUBSYSTEM!="usb", GOTO="usb_realtek_net_end"
ENV{DEVTYPE}!="usb_device", GOTO="usb_realtek_net_end"

# Modify this to change the default value
ENV{REALTEK_MODE1}="1"
ENV{REALTEK_MODE2}="3"

# Realtek
ATTR{idVendor}=="0bda", ATTR{idProduct}=="815[2,3,5,6]", ATTR{bConfigurationValue}!="$env{REALTEK_MODE1}", ATTR{bConfigurationValue}="$env{REALTEK_MODE1}"
ATTR{idVendor}=="0bda", ATTR{idProduct}=="8053", ATTR{bcdDevice}=="e???", ATTR{bConfigurationValue}!="$env{REALTEK_MODE2}", ATTR{bConfigurationValue}="$env{REALTEK_MODE2}"
.
.
.
LABEL="usb_realtek_net_end"

I disabled the udev rule on my Arch system, this time plugging it in, found the path of the device, sent 1 > bConfigurationValue and I could see the 2 before changing to 1.

and this would happen in /sys/bus/usb/devices/7-2.2

# lsusb -t
/:  Bus 07.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 5000M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 5000M
    |__ Port 2: Dev 3, If 0, Class=Hub, Driver=hub/4p, 5000M
        |__ Port 2: Dev 8, If 0, Class=Vendor Specific Class, Driver=cdc_ncm, 5000M

inside the path /sys/bus/usb/devices/7-2.2

7-2.2:2.0
7-2.2:2.1

would disappear and be replaced with

7-2.2:1.0

then

# lsusb -t
/:  Bus 07.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 5000M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 5000M
    |__ Port 2: Dev 3, If 0, Class=Hub, Driver=hub/4p, 5000M
        |__ Port 2: Dev 8, If 0, Class=Vendor Specific Class, Driver=r8152, 5000M

So it works exactly as explained!

This is on my Arch system:

5.18.15-arch1-1.0

However when I do the exact same thing on my OpenWRT raspberry pi 2B+

1-1.3:2.0
1-1.3:2.1

changes to

1-1.3:1.0

but no driver associated

# lsusb -t
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=dwc_otg/1p, 480M
    |__ Port 1: Dev 2, If 0, Class=, Driver=hub/5p, 480M
        |__ Port 3: Dev 17, If 0, Class=, Driver=, 480M
        |__ Port 4: Dev 16, If 0, Class=, Driver=r8152, 480M

As suggested in this thread earlier, I try to bind the driver.

# rmmod r8152
# modprobe r8152

# echo -n '1-1.3:1.0' > /sys/bus/usb/drivers/r8152/bind
ash: write error: No such device

# logread -f
kern.info kernel: [106226.361046] usb 1-1.4: reset high-speed USB device number 16 using dwc_otg
kern.info kernel: [106226.553486] r8152 1-1.4:1.0 eth1: v1.10.11
kern.info kernel: [106226.559746] r8152 1-1.3:1.0: Unknown version 0x7420
kern.info kernel: [106226.566359] usbcore: registered new interface driver r8152

As we can see the newer device has an unknown version error of 0x7420

Does this mean I need a newer driver because my OpenWRT is using 5.4.143?

Is there something else I can try? Or do I need a newer driver package?

Yes, looks like that unfortunately.

0x7420 was added as part of the large commit 195aae321c82 ("r8152: support new chips") which was in kernel release v5.13. This patch does a whole lot more than just adding a few new IDs, so I guess it won't be backported to any earlier stable kernel.

There's no reason OpenWrt cannot backport it though. But you'll probably need more patches as dependencies.. Might be easier to just grab the driver from a newer kernel and use that. Still needs some testing and most likely changes to adapt to older kernel APIs.

Thank you for assisting. I'm out of depth when it comes to adding drivers to OpenWRT. I guess a simpleton like me would have to wait for OpenWRT to update the kernel at some point. Any idea how long this might take?

Well, the move to v5.15 kernels has been going on for a while and is the default for RPi now I believe (in master). So next major release - whenever that will be.

Or juts live on the edge and run a snapshot :slight_smile:

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.