Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 49b420a1 authored by Ming Lei's avatar Ming Lei Committed by Greg Kroah-Hartman
Browse files

driver core: check bus->match without holding device lock



This patch moves bus->match out from driver_probe_device and
does not hold device lock to check the match between a device
and a driver.

The idea has been verified by the commit 6cd49586,
which leads to a faster boot. But the commit 6cd49586 has
the following drawbacks: 1),only does the quick check in
the path of __driver_attach->driver_probe_device, not in other
paths; 2),for a matched device and driver, check the same match
twice. It is a waste of cpu ,especially for some drivers with long
device id table (eg. usb-storage driver).

This patch adds a helper of driver_match_device to check the match
in all paths, and testes the match only once.

Signed-off-by: default avatarMing Lei <tom.leiming@gmail.com>
Acked-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 4a67a1bc
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -86,6 +86,11 @@ extern void bus_remove_driver(struct device_driver *drv);

extern void driver_detach(struct device_driver *drv);
extern int driver_probe_device(struct device_driver *drv, struct device *dev);
static inline int driver_match_device(struct device_driver *drv,
				      struct device *dev)
{
	return drv->bus->match && drv->bus->match(dev, drv);
}

extern void sysdev_shutdown(void);

+1 −1
Original line number Diff line number Diff line
@@ -198,7 +198,7 @@ static ssize_t driver_bind(struct device_driver *drv,
	int err = -ENODEV;

	dev = bus_find_device_by_name(bus, NULL, buf);
	if (dev && dev->driver == NULL) {
	if (dev && dev->driver == NULL && driver_match_device(drv, dev)) {
		if (dev->parent)	/* Needed for USB */
			down(&dev->parent->sem);
		down(&dev->sem);
+7 −12
Original line number Diff line number Diff line
@@ -189,14 +189,8 @@ int wait_for_device_probe(void)
 * @drv: driver to bind a device to
 * @dev: device to try to bind to the driver
 *
 * First, we call the bus's match function, if one present, which should
 * compare the device IDs the driver supports with the device IDs of the
 * device. Note we don't do this ourselves because we don't know the
 * format of the ID structures, nor what is to be considered a match and
 * what is not.
 *
 * This function returns 1 if a match is found, -ENODEV if the device is
 * not registered, and 0 otherwise.
 * This function returns -ENODEV if the device is not registered,
 * 1 if the device is bound sucessfully and 0 otherwise.
 *
 * This function must be called with @dev->sem held.  When called for a
 * USB interface, @dev->parent->sem must be held as well.
@@ -207,21 +201,22 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)

	if (!device_is_registered(dev))
		return -ENODEV;
	if (drv->bus->match && !drv->bus->match(dev, drv))
		goto done;

	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
		 drv->bus->name, __func__, dev_name(dev), drv->name);

	ret = really_probe(dev, drv);

done:
	return ret;
}

static int __device_attach(struct device_driver *drv, void *data)
{
	struct device *dev = data;

	if (!driver_match_device(drv, dev))
		return 0;

	return driver_probe_device(drv, dev);
}

@@ -274,7 +269,7 @@ static int __driver_attach(struct device *dev, void *data)
	 * is an error.
	 */

	if (drv->bus->match && !drv->bus->match(dev, drv))
	if (!driver_match_device(drv, dev))
		return 0;

	if (dev->parent)	/* Needed for USB */