ia64/xen-unstable

changeset 11087:857854460d36

[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@xensource.com>
author kaf24@localhost.localdomain
date Sat Aug 12 15:50:25 2006 +0100 (2006-08-12)
parents 457c427c28fc
children 41399e5fdc9e
files linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Sat Aug 12 12:25:42 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Sat Aug 12 15:50:25 2006 +0100
     1.3 @@ -58,6 +58,8 @@ extern struct mutex xenwatch_mutex;
     1.4  
     1.5  static struct notifier_block *xenstore_chain;
     1.6  
     1.7 +static void wait_for_devices(struct xenbus_driver *xendrv);
     1.8 +
     1.9  /* If something in array of ids matches this device, return it. */
    1.10  static const struct xenbus_device_id *
    1.11  match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
    1.12 @@ -408,9 +410,18 @@ static int xenbus_register_driver_common
    1.13  
    1.14  int xenbus_register_frontend(struct xenbus_driver *drv)
    1.15  {
    1.16 +	int ret;
    1.17 +
    1.18  	drv->read_otherend_details = read_backend_details;
    1.19  
    1.20 -	return xenbus_register_driver_common(drv, &xenbus_frontend);
    1.21 +	ret = xenbus_register_driver_common(drv, &xenbus_frontend);
    1.22 +	if (ret)
    1.23 +		return ret;
    1.24 +
    1.25 +	/* If this driver is loaded as a module wait for devices to attach. */
    1.26 +	wait_for_devices(drv);
    1.27 +
    1.28 +	return 0;
    1.29  }
    1.30  EXPORT_SYMBOL_GPL(xenbus_register_frontend);
    1.31  
    1.32 @@ -1042,6 +1053,7 @@ postcore_initcall(xenbus_probe_init);
    1.33  static int is_disconnected_device(struct device *dev, void *data)
    1.34  {
    1.35  	struct xenbus_device *xendev = to_xenbus_device(dev);
    1.36 +	struct device_driver *drv = data;
    1.37  
    1.38  	/*
    1.39  	 * A device with no driver will never connect. We care only about
    1.40 @@ -1050,18 +1062,27 @@ static int is_disconnected_device(struct
    1.41  	if (!dev->driver)
    1.42  		return 0;
    1.43  
    1.44 +	/* Is this search limited to a particular driver? */
    1.45 +	if (drv && (dev->driver != drv))
    1.46 +		return 0;
    1.47 +
    1.48  	return (xendev->state != XenbusStateConnected);
    1.49  }
    1.50  
    1.51 -static int exists_disconnected_device(void)
    1.52 +static int exists_disconnected_device(struct device_driver *drv)
    1.53  {
    1.54 -	return bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL,
    1.55 +	return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
    1.56  				is_disconnected_device);
    1.57  }
    1.58  
    1.59  static int print_device_status(struct device *dev, void *data)
    1.60  {
    1.61  	struct xenbus_device *xendev = to_xenbus_device(dev);
    1.62 +	struct device_driver *drv = data;
    1.63 +
    1.64 +	/* Is this operation limited to a particular driver? */
    1.65 +	if (drv && (dev->driver != drv))
    1.66 +		return 0;
    1.67  
    1.68  	if (!dev->driver) {
    1.69  		/* Information only: is this too noisy? */
    1.70 @@ -1076,6 +1097,9 @@ static int print_device_status(struct de
    1.71  	return 0;
    1.72  }
    1.73  
    1.74 +/* We only wait for device setup after most initcalls have run. */
    1.75 +static int ready_to_wait_for_devices;
    1.76 +
    1.77  /*
    1.78   * On a 10 second timeout, wait for all devices currently configured.  We need
    1.79   * to do this to guarantee that the filesystems and / or network devices
    1.80 @@ -1090,20 +1114,29 @@ static int print_device_status(struct de
    1.81   * boot slightly, but of course needs tools or manual intervention to set up
    1.82   * those flags correctly.
    1.83   */
    1.84 -static int __init wait_for_devices(void)
    1.85 +static void wait_for_devices(struct xenbus_driver *xendrv)
    1.86  {
    1.87  	unsigned long timeout = jiffies + 10*HZ;
    1.88 +	struct device_driver *drv = xendrv ? &xendrv->driver : NULL;
    1.89  
    1.90 -	if (!is_running_on_xen())
    1.91 -		return -ENODEV;
    1.92 +	if (!ready_to_wait_for_devices || !is_running_on_xen())
    1.93 +		return;
    1.94  
    1.95 -	while (time_before(jiffies, timeout) && exists_disconnected_device())
    1.96 +	while (exists_disconnected_device(drv)) {
    1.97 +		if (time_after(jiffies, timeout))
    1.98 +			break;
    1.99  		schedule_timeout_interruptible(HZ/10);
   1.100 +	}
   1.101  
   1.102 -	bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL,
   1.103 +	bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
   1.104  			 print_device_status);
   1.105 +}
   1.106  
   1.107 +static int __init boot_wait_for_devices(void)
   1.108 +{
   1.109 +	ready_to_wait_for_devices = 1;
   1.110 +	wait_for_devices(NULL);
   1.111  	return 0;
   1.112  }
   1.113  
   1.114 -late_initcall(wait_for_devices);
   1.115 +late_initcall(boot_wait_for_devices);