9
0
Fork 0

base: Introduce deferred probing

As expected, we would need deferred probing sooner or later. This is
a first approach to allow devices to return -EPROBE_DEFER and get
sorted into a list of deferred devices that will be re-probed later.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
Sebastian Hesselbarth 2015-04-15 00:53:15 +02:00 committed by Sascha Hauer
parent 11045f866d
commit ab3da15bc1
2 changed files with 54 additions and 3 deletions

View File

@ -29,6 +29,7 @@
#include <console.h>
#include <linux/ctype.h>
#include <errno.h>
#include <init.h>
#include <fs.h>
#include <of.h>
#include <linux/list.h>
@ -43,6 +44,7 @@ LIST_HEAD(driver_list);
EXPORT_SYMBOL(driver_list);
static LIST_HEAD(active);
static LIST_HEAD(deferred);
struct device_d *get_device_by_name(const char *name)
{
@ -88,13 +90,20 @@ int device_probe(struct device_d *dev)
list_add(&dev->active, &active);
ret = dev->bus->probe(dev);
if (ret) {
if (ret == 0)
return 0;
if (ret == -EPROBE_DEFER) {
list_del(&dev->active);
dev_err(dev, "probe failed: %s\n", strerror(-ret));
list_add(&dev->active, &deferred);
dev_dbg(dev, "probe deferred\n");
return ret;
}
return 0;
list_del(&dev->active);
dev_err(dev, "probe failed: %s\n", strerror(-ret));
return ret;
}
int device_detect(struct device_d *dev)
@ -213,6 +222,47 @@ int unregister_device(struct device_d *old_dev)
}
EXPORT_SYMBOL(unregister_device);
/*
* Loop over list of deferred devices as long as at least one
* device is successfully probed. Devices that again request
* deferral are re-added to deferred list in device_probe().
* For devices finally left in deferred list -EPROBE_DEFER
* becomes a fatal error.
*/
static int device_probe_deferred(void)
{
struct device_d *dev, *tmp;
struct driver_d *drv;
bool success;
do {
success = false;
if (list_empty(&deferred))
break;
list_for_each_entry_safe(dev, tmp, &deferred, active) {
list_del(&dev->active);
dev_dbg(dev, "re-probe device\n");
bus_for_each_driver(dev->bus, drv) {
if (match(drv, dev))
continue;
success = true;
break;
}
}
} while (success);
if (list_empty(&deferred))
return 0;
list_for_each_entry(dev, &deferred, active)
dev_err(dev, "probe permanently deferred\n");
return 0;
}
late_initcall(device_probe_deferred);
struct driver_d *get_driver_by_name(const char *name)
{
struct driver_d *drv;

View File

@ -132,6 +132,7 @@
#define ERESTARTNOINTR 513
#define ERESTARTNOHAND 514 /* restart if no handler.. */
#define ENOIOCTLCMD 515 /* No ioctl command */
#define EPROBE_DEFER 517 /* Driver requests probe retry */
#define ENOTSUPP 524 /* Operation is not supported */