aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/driver.c
diff options
context:
space:
mode:
authorBastien Nocera <[email protected]>2020-10-22 13:55:20 +0000
committerGreg Kroah-Hartman <[email protected]>2020-10-28 12:24:58 +0000
commit0942d59b0af46511d59dbf5bd69ec4a64d1a854c (patch)
tree44706a2b20b1129aaf102044c32e7ee99f4bc417 /drivers/usb/core/driver.c
parentusb: host: ehci-tegra: Fix error handling in tegra_ehci_probe() (diff)
downloadkernel-0942d59b0af46511d59dbf5bd69ec4a64d1a854c.tar.gz
kernel-0942d59b0af46511d59dbf5bd69ec4a64d1a854c.zip
usbcore: Check both id_table and match() when both available
From: Bastien Nocera <[email protected]> When a USB device driver has both an id_table and a match() function, make sure to check both to find a match, first matching the id_table, then checking the match() function. This makes it possible to have module autoloading done through the id_table when devices are plugged in, before checking for further device eligibility in the match() function. Cc: <[email protected]> # 5.8 Cc: Greg Kroah-Hartman <[email protected]> Cc: Alan Stern <[email protected]> Co-developed-by: M. Vefa Bicakci <[email protected]> Tested-by: Bastien Nocera <[email protected]> Signed-off-by: Bastien Nocera <[email protected]> Signed-off-by: M. Vefa Bicakci <[email protected]> Tested-by: Pan (Pany) YUAN <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
Diffstat (limited to 'drivers/usb/core/driver.c')
-rw-r--r--drivers/usb/core/driver.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 98b7449c11f3..4dfa44d6cc3c 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -839,6 +839,22 @@ const struct usb_device_id *usb_device_match_id(struct usb_device *udev,
return NULL;
}
+bool usb_driver_applicable(struct usb_device *udev,
+ struct usb_device_driver *udrv)
+{
+ if (udrv->id_table && udrv->match)
+ return usb_device_match_id(udev, udrv->id_table) != NULL &&
+ udrv->match(udev);
+
+ if (udrv->id_table)
+ return usb_device_match_id(udev, udrv->id_table) != NULL;
+
+ if (udrv->match)
+ return udrv->match(udev);
+
+ return false;
+}
+
static int usb_device_match(struct device *dev, struct device_driver *drv)
{
/* devices and interfaces are handled separately */
@@ -853,17 +869,14 @@ static int usb_device_match(struct device *dev, struct device_driver *drv)
udev = to_usb_device(dev);
udrv = to_usb_device_driver(drv);
- if (udrv->id_table)
- return usb_device_match_id(udev, udrv->id_table) != NULL;
-
- if (udrv->match)
- return udrv->match(udev);
-
/* If the device driver under consideration does not have a
* id_table or a match function, then let the driver's probe
* function decide.
*/
- return 1;
+ if (!udrv->id_table && !udrv->match)
+ return 1;
+
+ return usb_driver_applicable(udev, udrv);
} else if (is_usb_interface(dev)) {
struct usb_interface *intf;
@@ -941,8 +954,7 @@ static int __usb_bus_reprobe_drivers(struct device *dev, void *data)
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))
+ if (!usb_driver_applicable(udev, new_udriver))
return 0;
ret = device_reprobe(dev);