usbcore: Check both id_table and match() when both available
From: Bastien Nocera <hadess@hadess.net> 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: <stable@vger.kernel.org> # 5.8 Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Alan Stern <stern@rowland.harvard.edu> Co-developed-by: M. Vefa Bicakci <m.v.b@runbox.com> Tested-by: Bastien Nocera <hadess@hadess.net> Signed-off-by: Bastien Nocera <hadess@hadess.net> Signed-off-by: M. Vefa Bicakci <m.v.b@runbox.com> Tested-by: Pan (Pany) YUAN <pany@fedoraproject.org> Link: https://lore.kernel.org/r/20201022135521.375211-2-m.v.b@runbox.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									32d174d2d5
								
							
						
					
					
						commit
						0942d59b0a
					
				@ -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);
 | 
			
		||||
 | 
			
		||||
@ -205,9 +205,7 @@ static int __check_for_non_generic_match(struct device_driver *drv, void *data)
 | 
			
		||||
	udrv = to_usb_device_driver(drv);
 | 
			
		||||
	if (udrv == &usb_generic_driver)
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (usb_device_match_id(udev, udrv->id_table) != NULL)
 | 
			
		||||
		return 1;
 | 
			
		||||
	return (udrv->match && udrv->match(udev));
 | 
			
		||||
	return usb_driver_applicable(udev, udrv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool usb_generic_driver_match(struct usb_device *udev)
 | 
			
		||||
 | 
			
		||||
@ -74,6 +74,8 @@ extern int usb_match_device(struct usb_device *dev,
 | 
			
		||||
			    const struct usb_device_id *id);
 | 
			
		||||
extern const struct usb_device_id *usb_device_match_id(struct usb_device *udev,
 | 
			
		||||
				const struct usb_device_id *id);
 | 
			
		||||
extern bool usb_driver_applicable(struct usb_device *udev,
 | 
			
		||||
				  struct usb_device_driver *udrv);
 | 
			
		||||
extern void usb_forced_unbind_intf(struct usb_interface *intf);
 | 
			
		||||
extern void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user