patch "USB: Fix device driver race" added to usb-linus
Subsystems (2)
This is a note to let you know that I've just added the patch titled
USB: Fix device driver race
to my usb git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
in the usb-linus branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will hopefully also be merged in Linus's tree for the next -rc kernel release.
If you have any questions about this process, please let me know.
From d5643d2249b279077427b2c2b2ffae9b70c95b0b Mon Sep 17 00:00:00 2001
From: Bastien Nocera <[email protected]>
Date: Tue, 18 Aug 2020 13:04:45 +0200
Subject: USB: Fix device driver race
When a new device with a specialised device driver is plugged in, the new driver will be modprobe()'d but the driver core will attach the "generic" driver to the device.
After that, nothing will trigger a reprobe when the modprobe()'d device driver has finished initialising, as the device has the "generic" driver attached to it.
Trigger a reprobe ourselves when new specialised drivers get registered.
--- drivers/usb/core/driver.c | 40 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-)
drivers/usb/core/driver.c +38 -2
@@ -905,6 +905,35 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)return 0 ; } +static bool is_dev_usb_generic_driver (struct device *dev) +{ +struct usb_device_driver *udd = dev->driver ? +to_usb_device_driver (dev->driver) :NULL ; + +return udd == &usb_generic_driver; +} + +static int __usb_bus_reprobe_drivers (struct device *dev,void *data) +{ +struct usb_device_driver *new_udriver = data; +struct usb_device *udev; +int ret; + +if (!is_dev_usb_generic_driver (dev)) +return 0 ; + + udev =to_usb_device (dev); +if (usb_device_match_id (udev, new_udriver->id_table) ==NULL && + (!new_udriver->match || new_udriver->match (udev) !=0 )) +return 0 ; + + ret =device_reprobe (dev); +if (ret && ret != -EPROBE_DEFER ) +dev_err (dev,"Failed to reprobe device (error %d)\n" , ret); + +return 0 ; +} +/** * usb_register_device_driver - register a USB device (not interface) driver * @new_udriver: USB operations for the device driver
@@ -934,13 +963,20 @@ int usb_register_device_driver(struct usb_device_driver *new_udriver, retval =driver_register (&new_udriver->drvwrap.driver); -if (!retval) +if (!retval) {pr_info ("%s: registered new device driver %s\n" , usbcore_name, new_udriver->name); -else +/* +* Check whether any device could be better served with +* this new driver +*/ +bus_for_each_dev (&usb_bus_type,NULL , new_udriver, + __usb_bus_reprobe_drivers); + }else {printk (KERN_ERR "%s: error %d registering device " " driver %s\n" , usbcore_name, retval, new_udriver->name); + }return retval; }
Signature · 1 line
2.28.0