Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: 8524/1: driver cohandle -EPROBE_DEFER from bus_type.match()

Allow implementations of the match() callback in struct bus_type to
return errors and if it's -EPROBE_DEFER then queue the device for
deferred probing.

This is useful to buses such as AMBA in which devices are registered
before their matching information can be retrieved from the HW
(typically because a clock driver hasn't probed yet).

[changed if-else code structure, adjusted documentation to match the code,
extended comments]

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by

Tomeu Vizoso and committed by
Russell King
656b8035 17f29d36

+31 -6
+4 -2
Documentation/driver-model/porting.txt
··· 340 340 341 341 int (*match)(struct device * dev, struct device_driver * drv); 342 342 343 - match should return '1' if the driver supports the device, and '0' 344 - otherwise. 343 + match should return positive value if the driver supports the device, 344 + and zero otherwise. It may also return error code (for example 345 + -EPROBE_DEFER) if determining that given driver supports the device is 346 + not possible. 345 347 346 348 When a device is registered, the bus's list of drivers is iterated 347 349 over. bus->match() is called for each one until a match is found.
+22 -2
drivers/base/dd.c
··· 560 560 struct device_attach_data *data = _data; 561 561 struct device *dev = data->dev; 562 562 bool async_allowed; 563 + int ret; 563 564 564 565 /* 565 566 * Check if device has already been claimed. This may ··· 571 570 if (dev->driver) 572 571 return -EBUSY; 573 572 574 - if (!driver_match_device(drv, dev)) 573 + ret = driver_match_device(drv, dev); 574 + if (ret == 0) { 575 + /* no match */ 575 576 return 0; 577 + } else if (ret == -EPROBE_DEFER) { 578 + dev_dbg(dev, "Device match requests probe deferral\n"); 579 + driver_deferred_probe_add(dev); 580 + } else if (ret < 0) { 581 + dev_dbg(dev, "Bus failed to match device: %d", ret); 582 + return ret; 583 + } /* ret > 0 means positive match */ 576 584 577 585 async_allowed = driver_allows_async_probing(drv); 578 586 ··· 701 691 static int __driver_attach(struct device *dev, void *data) 702 692 { 703 693 struct device_driver *drv = data; 694 + int ret; 704 695 705 696 /* 706 697 * Lock device and try to bind to it. We drop the error ··· 713 702 * is an error. 714 703 */ 715 704 716 - if (!driver_match_device(drv, dev)) 705 + ret = driver_match_device(drv, dev); 706 + if (ret == 0) { 707 + /* no match */ 717 708 return 0; 709 + } else if (ret == -EPROBE_DEFER) { 710 + dev_dbg(dev, "Device match requests probe deferral\n"); 711 + driver_deferred_probe_add(dev); 712 + } else if (ret < 0) { 713 + dev_dbg(dev, "Bus failed to match device: %d", ret); 714 + return ret; 715 + } /* ret > 0 means positive match */ 718 716 719 717 if (dev->parent) /* Needed for USB */ 720 718 device_lock(dev->parent);
+5 -2
include/linux/device.h
··· 70 70 * @dev_groups: Default attributes of the devices on the bus. 71 71 * @drv_groups: Default attributes of the device drivers on the bus. 72 72 * @match: Called, perhaps multiple times, whenever a new device or driver 73 - * is added for this bus. It should return a nonzero value if the 74 - * given device can be handled by the given driver. 73 + * is added for this bus. It should return a positive value if the 74 + * given device can be handled by the given driver and zero 75 + * otherwise. It may also return error code if determining that 76 + * the driver supports the device is not possible. In case of 77 + * -EPROBE_DEFER it will queue the device for deferred probing. 75 78 * @uevent: Called when a device is added, removed, or a few other things 76 79 * that generate uevents to add the environment variables. 77 80 * @probe: Called when a new device or driver add to this bus, and callback