Project

General

Profile

Actions

Bug #13899

closed

usbecm should bind to interface association

Added by Joshua M. Clulow 4 months ago. Updated 4 months ago.

Status:
Closed
Priority:
Normal
Category:
driver - device drivers
Start date:
Due date:
% Done:

100%

Estimated time:
Difficulty:
Medium
Tags:
Gerrit CR:

Description

According to the USB Communications Device Class (Revision 1.2) specification:

In the case where the device does not choose to identify itself at the device level with the Communications Device Class code, the device shall employ a USB Common Class Feature mechanism that associates multiple interfaces on the device with a single driver in the host. This mechanism is specified in the Interface Association Descriptor ECN to USB 2.0.

Some ZTE Mobile Broadband devices (e.g., vendor 19D2 device 1405) appear to have opted for this configuration for their ethernet interface. While usbecm will bind to a device that identifies as ECM (e.g., usbif,class2.6) it will not presently bind to an interface association (e.g., usbia,class2.6). By adding the appropriate alias, the driver will bind the the IA level and appears to locate the subordinate interfaces and work correctly.

Actions #1

Updated by Electric Monk 4 months ago

  • Gerrit CR set to 1575
Actions #2

Updated by Joshua M. Clulow 4 months ago

Note that I realised this was the case because snoop was failing on the NIC with EIO:

# snoop -r -d usbecm0
snoop: cannot open "usbecm0": I/O error

I dug into this with DTrace, and found roughly where the problem arose:

# dtrace -F -n 'fbt:usbecm::entry { printf(" "); self->x = 1; }'  -n 'fbt:usbecm::return { self->x = 0; trace((int)arg1); }' -n 'fbt::usb*:entry /self->x/ { printf(" "); } fbt::usb*:return /self->x/ { trace((int)arg1); }'
...

    CPU FUNCTION
      0  -> usbecm_m_start
      0   | usbecm_m_start:entry
      0    -> usb_serialize_access
      0    <- usb_serialize_access                        1
      0    -> usbecm_open_pipes
      0     | usbecm_open_pipes:entry
...
      0          <- usba_sync_set_alt_if                -14
      0        <- usba_pipe_setup_func_call             -14
      0      <- usb_set_alt_if                          -14
      0      -> usb_dprintf2
      0        -> usba_vlog
      0          -> usb_vprintf
      0          <- usb_vprintf                           0
      0        <- usba_vlog                               0
      0      <- usb_dprintf2                              0
      0    <- usbecm_open_pipes                         -14
      0  <- usbecm_m_start                                5

In this context, -14 is USB_INVALID_PERM ("dip does not own the interface to be set." according to the manual). Indeed this appeared to be the case, because we were requesting an interface that was indeed part of the IA, but from the wrong dip: the interface itself, where we had bound in error, rather than the IA one node up.

Actions #3

Updated by Joshua M. Clulow 4 months ago

Testing Notes

I built the change and installed it. I looked at prtconf output in four combinations: before and after the change, with the device removed and inserted. This highlights the nodes that are specific to the device in both cases and allows us to compare easily:

Before Change

$ diff -u before_prtconf_{removed,inserted}.txt
--- before_prtconf_removed.txt    2021-06-26 23:01:31.443136450 -0700
+++ before_prtconf_inserted.txt    2021-06-26 23:02:05.103053833 -0700
@@ -10,6 +10,13 @@
         pci8086,2064 (pciex8086,1911) [Intel Corporation Xeon E3-1200 v5/v6 / E3-1500 v5 / 6th/7th/8th Gen Core Processor Gaussian Mixture Model]
         pci8086,2064 (pciex8086,a12f) [Intel Corporation 100 Series/C230 Series Chipset Family USB 3.0 xHCI Controller], instance #0 (driver name: xhci)
             device, instance #1 (driver name: usb_mid)
+            communications, instance #4 (driver name: usb_mid)
+                interface-association, instance #0 (driver name: usb_ia)
+                    ethernet, instance #0 (driver name: usbecm)
+                    data
+                storage, instance #5 (driver name: scsa2usb)
+                    disk, instance #8 (driver name: sd)
+                    disk, instance #9 (driver name: sd)
         pci8086,2064 (pciex8086,a131) [Intel Corporation 100 Series/C230 Series Chipset Family Thermal Subsystem]
         pci8086,2064 (pciex8086,a13a) [Intel Corporation 100 Series/C230 Series Chipset Family MEI Controller #1]
         pci8086,a110 (pciex8086,a110) [Intel Corporation 100 Series/C230 Series Chipset Family PCI Express Root Port #1], instance #0 (driver name: pcieb)

After Change

$ diff -u after_prtconf_{removed,inserted}.txt
--- after_prtconf_removed.txt    2021-06-26 23:10:06.222021457 -0700
+++ after_prtconf_inserted.txt    2021-06-26 23:10:50.645438977 -0700
@@ -10,6 +10,11 @@
         pci8086,2064 (pciex8086,1911) [Intel Corporation Xeon E3-1200 v5/v6 / E3-1500 v5 / 6th/7th/8th Gen Core Processor Gaussian Mixture Model]
         pci8086,2064 (pciex8086,a12f) [Intel Corporation 100 Series/C230 Series Chipset Family USB 3.0 xHCI Controller], instance #0 (driver name: xhci)
             device, instance #1 (driver name: usb_mid)
+            communications, instance #4 (driver name: usb_mid)
+                interface-association, instance #1 (driver name: usbecm)
+                storage, instance #5 (driver name: scsa2usb)
+                    disk, instance #8 (driver name: sd)
+                    disk, instance #9 (driver name: sd)
         pci8086,2064 (pciex8086,a131) [Intel Corporation 100 Series/C230 Series Chipset Family Thermal Subsystem]
         pci8086,2064 (pciex8086,a13a) [Intel Corporation 100 Series/C230 Series Chipset Family MEI Controller #1]
         pci8086,a110 (pciex8086,a110) [Intel Corporation 100 Series/C230 Series Chipset Family PCI Express Root Port #1], instance #0 (driver name: pcieb)

Note that the alias is also present, and snoop works correctly:

$ grep usbecm /etc/driver_aliases
usbecm "usb,class2.6.0" 
usbecm "usb430,a4a2" 
usbecm "usbif,class2.6" 
usbecm "usbia,class2.6" 

$ pfexec snoop -r -d usbecm1
Using device usbecm1 (promiscuous mode)
 UNSPECIFIED -> ff02::16     ICMPv6 Group membership report - MLDv2
 UNSPECIFIED -> ff02::16     ICMPv6 Group membership report - MLDv2
 UNSPECIFIED -> ff02::1:ffb7:ef08 ICMPv6 Neighbor solicitation
fe80::364b:50ff:feb7:ef08 -> ff02::16     ICMPv6 Group membership report - MLDv2
fe80::364b:50ff:feb7:ef08 -> ff02::2      ICMPv6 Router solicitation
fe80::364b:50ff:feb7:ef08 -> ff02::16     ICMPv6 Group membership report - MLDv2
...

Comparing Before & After

$ diff -u {before,after}_prtconf_inserted.txt
--- before_prtconf_inserted.txt    2021-06-26 23:02:05.103053833 -0700
+++ after_prtconf_inserted.txt    2021-06-26 23:10:50.645438977 -0700
@@ -11,9 +11,7 @@
         pci8086,2064 (pciex8086,a12f) [Intel Corporation 100 Series/C230 Series Chipset Family USB 3.0 xHCI Controller], instance #0 (driver name: xhci)
             device, instance #1 (driver name: usb_mid)
             communications, instance #4 (driver name: usb_mid)
-                interface-association, instance #0 (driver name: usb_ia)
-                    ethernet, instance #0 (driver name: usbecm)
-                    data
+                interface-association, instance #1 (driver name: usbecm)
                 storage, instance #5 (driver name: scsa2usb)
                     disk, instance #8 (driver name: sd)
                     disk, instance #9 (driver name: sd)
Actions #4

Updated by Electric Monk 4 months ago

  • Status changed from New to Closed
  • % Done changed from 0 to 100

git commit d67c7e5398eea7064dd670882e5992ac756c6fe6

commit  d67c7e5398eea7064dd670882e5992ac756c6fe6
Author: Joshua M. Clulow <josh@sysmgr.org>
Date:   2021-06-29T18:37:33.000Z

    13899 usbecm should bind to interface association
    Reviewed by: Toomas Soome <tsoome@me.com>
    Approved by: Robert Mustacchi <rm@fingolfin.org>

Actions

Also available in: Atom PDF