# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxxx
# Node ID 857854460d3695afd926d28c69c524d953539abe
# Parent 457c427c28fcc65dc30c52c50662f404b3f6c475
[LINUX][XENBUS] Wait for devices to connect when frontend driver is loaded as a
module.
Thsi fixes problems where a driver is loaded from a script, and the
following parts of the script depend on devices having connected
by the time the modprobe/insmod returns.
Based on a tested patch from Rik van Riel at Red Hat.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c | 67 ++++++++++++-----
1 files changed, 50 insertions(+), 17 deletions(-)
diff -r 457c427c28fc -r 857854460d36
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Sat Aug 12
12:25:42 2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Sat Aug 12
15:50:25 2006 +0100
@@ -58,6 +58,8 @@ extern struct mutex xenwatch_mutex;
static struct notifier_block *xenstore_chain;
+static void wait_for_devices(struct xenbus_driver *xendrv);
+
/* If something in array of ids matches this device, return it. */
static const struct xenbus_device_id *
match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
@@ -408,9 +410,18 @@ static int xenbus_register_driver_common
int xenbus_register_frontend(struct xenbus_driver *drv)
{
+ int ret;
+
drv->read_otherend_details = read_backend_details;
- return xenbus_register_driver_common(drv, &xenbus_frontend);
+ ret = xenbus_register_driver_common(drv, &xenbus_frontend);
+ if (ret)
+ return ret;
+
+ /* If this driver is loaded as a module wait for devices to attach. */
+ wait_for_devices(drv);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(xenbus_register_frontend);
@@ -1042,6 +1053,7 @@ static int is_disconnected_device(struct
static int is_disconnected_device(struct device *dev, void *data)
{
struct xenbus_device *xendev = to_xenbus_device(dev);
+ struct device_driver *drv = data;
/*
* A device with no driver will never connect. We care only about
@@ -1050,18 +1062,27 @@ static int is_disconnected_device(struct
if (!dev->driver)
return 0;
+ /* Is this search limited to a particular driver? */
+ if (drv && (dev->driver != drv))
+ return 0;
+
return (xendev->state != XenbusStateConnected);
}
-static int exists_disconnected_device(void)
-{
- return bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL,
+static int exists_disconnected_device(struct device_driver *drv)
+{
+ return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
is_disconnected_device);
}
static int print_device_status(struct device *dev, void *data)
{
struct xenbus_device *xendev = to_xenbus_device(dev);
+ struct device_driver *drv = data;
+
+ /* Is this operation limited to a particular driver? */
+ if (drv && (dev->driver != drv))
+ return 0;
if (!dev->driver) {
/* Information only: is this too noisy? */
@@ -1075,6 +1096,9 @@ static int print_device_status(struct de
return 0;
}
+
+/* We only wait for device setup after most initcalls have run. */
+static int ready_to_wait_for_devices;
/*
* On a 10 second timeout, wait for all devices currently configured. We need
@@ -1090,20 +1114,29 @@ static int print_device_status(struct de
* boot slightly, but of course needs tools or manual intervention to set up
* those flags correctly.
*/
-static int __init wait_for_devices(void)
+static void wait_for_devices(struct xenbus_driver *xendrv)
{
unsigned long timeout = jiffies + 10*HZ;
-
- if (!is_running_on_xen())
- return -ENODEV;
-
- while (time_before(jiffies, timeout) && exists_disconnected_device())
+ struct device_driver *drv = xendrv ? &xendrv->driver : NULL;
+
+ if (!ready_to_wait_for_devices || !is_running_on_xen())
+ return;
+
+ while (exists_disconnected_device(drv)) {
+ if (time_after(jiffies, timeout))
+ break;
schedule_timeout_interruptible(HZ/10);
-
- bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL,
+ }
+
+ bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
print_device_status);
-
- return 0;
-}
-
-late_initcall(wait_for_devices);
+}
+
+static int __init boot_wait_for_devices(void)
+{
+ ready_to_wait_for_devices = 1;
+ wait_for_devices(NULL);
+ return 0;
+}
+
+late_initcall(boot_wait_for_devices);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|