From: Yi Cong A similar reason was raised in ec51fbd1b8a2 (r8152: add USB device driver for config selection): Linux prioritizes probing non-vendor-specific configurations. Referring to the implementation of this patch, cfgselect is also used for ax88179 to override the default configuration selection. Signed-off-by: Yi Cong --- drivers/net/usb/ax88179_178a.c | 72 ++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 29cbe9ddd610..965d2a66695d 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -14,6 +14,7 @@ #include #include +#define MODULENAME "ax88179_178a" #define AX88179_PHY_ID 0x03 #define AX_EEPROM_LEN 0x100 #define AX88179_EEPROM_MAGIC 0x17900b95 @@ -1713,6 +1714,16 @@ static int ax88179_stop(struct usbnet *dev) return 0; } +static int ax88179_probe(struct usb_interface *intf, const struct usb_device_id *i) +{ + if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) { + printk("[YCDBG][%s:%d] bInterfaceClass:%d\n", __func__, __LINE__, intf->cur_altsetting->desc.bInterfaceClass); + return -ENODEV; + } + + return usbnet_probe(intf, i); +} + static const struct driver_info ax88179_info = { .description = "ASIX AX88179 USB 3.0 Gigabit Ethernet", .bind = ax88179_bind, @@ -1941,9 +1952,9 @@ static const struct usb_device_id products[] = { MODULE_DEVICE_TABLE(usb, products); static struct usb_driver ax88179_178a_driver = { - .name = "ax88179_178a", + .name = MODULENAME, .id_table = products, - .probe = usbnet_probe, + .probe = ax88179_probe, .suspend = ax88179_suspend, .resume = ax88179_resume, .reset_resume = ax88179_resume, @@ -1952,7 +1963,62 @@ static struct usb_driver ax88179_178a_driver = { .disable_hub_initiated_lpm = 1, }; -module_usb_driver(ax88179_178a_driver); +static int ax88179_cfgselector_probe(struct usb_device *udev) +{ + struct usb_host_config *c; + int i, num_configs; + + /* The vendor mode is not always config #1, so to find it out. */ + c = udev->config; + num_configs = udev->descriptor.bNumConfigurations; + for (i = 0; i < num_configs; (i++, c++)) { + struct usb_interface_descriptor *desc = NULL; + + if (!c->desc.bNumInterfaces) + continue; + desc = &c->intf_cache[0]->altsetting->desc; + if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC) + break; + } + + if (i == num_configs) + return -ENODEV; + + if (usb_set_configuration(udev, c->desc.bConfigurationValue)) { + dev_err(&udev->dev, "Failed to set configuration %d\n", + c->desc.bConfigurationValue); + return -ENODEV; + } + + return 0; +} + +static struct usb_device_driver ax88179_cfgselector_driver = { + .name = MODULENAME "-cfgselector", + .probe = ax88179_cfgselector_probe, + .id_table = products, + .generic_subclass = 1, + .supports_autosuspend = 1, +}; + +static int __init ax88179_driver_init(void) +{ + int ret; + + ret = usb_register_device_driver(&ax88179_cfgselector_driver, THIS_MODULE); + if (ret) + return ret; + return usb_register(&ax88179_178a_driver); +} + +static void __exit ax88179_driver_exit(void) +{ + usb_deregister(&ax88179_178a_driver); + usb_deregister_device_driver(&ax88179_cfgselector_driver); +} + +module_init(ax88179_driver_init); +module_exit(ax88179_driver_exit); MODULE_DESCRIPTION("ASIX AX88179/178A based USB 3.0/2.0 Gigabit Ethernet Devices"); MODULE_LICENSE("GPL"); -- 2.25.1