|
@@ -135,7 +135,7 @@ static int read_backend_details(struct xenbus_device *xendev)
|
|
|
return xenbus_read_otherend_details(xendev, "backend-id", "backend");
|
|
|
}
|
|
|
|
|
|
-static int is_device_connecting(struct device *dev, void *data)
|
|
|
+static int is_device_connecting(struct device *dev, void *data, bool ignore_nonessential)
|
|
|
{
|
|
|
struct xenbus_device *xendev = to_xenbus_device(dev);
|
|
|
struct device_driver *drv = data;
|
|
@@ -152,16 +152,41 @@ static int is_device_connecting(struct device *dev, void *data)
|
|
|
if (drv && (dev->driver != drv))
|
|
|
return 0;
|
|
|
|
|
|
+ if (ignore_nonessential) {
|
|
|
+ /* With older QEMU, for PVonHVM guests the guest config files
|
|
|
+ * could contain: vfb = [ 'vnc=1, vnclisten=0.0.0.0']
|
|
|
+ * which is nonsensical as there is no PV FB (there can be
|
|
|
+ * a PVKB) running as HVM guest. */
|
|
|
+
|
|
|
+ if ((strncmp(xendev->nodename, "device/vkbd", 11) == 0))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if ((strncmp(xendev->nodename, "device/vfb", 10) == 0))
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
xendrv = to_xenbus_driver(dev->driver);
|
|
|
return (xendev->state < XenbusStateConnected ||
|
|
|
(xendev->state == XenbusStateConnected &&
|
|
|
xendrv->is_ready && !xendrv->is_ready(xendev)));
|
|
|
}
|
|
|
+static int essential_device_connecting(struct device *dev, void *data)
|
|
|
+{
|
|
|
+ return is_device_connecting(dev, data, true /* ignore PV[KBB+FB] */);
|
|
|
+}
|
|
|
+static int non_essential_device_connecting(struct device *dev, void *data)
|
|
|
+{
|
|
|
+ return is_device_connecting(dev, data, false);
|
|
|
+}
|
|
|
|
|
|
-static int exists_connecting_device(struct device_driver *drv)
|
|
|
+static int exists_essential_connecting_device(struct device_driver *drv)
|
|
|
{
|
|
|
return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
|
|
|
- is_device_connecting);
|
|
|
+ essential_device_connecting);
|
|
|
+}
|
|
|
+static int exists_non_essential_connecting_device(struct device_driver *drv)
|
|
|
+{
|
|
|
+ return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
|
|
|
+ non_essential_device_connecting);
|
|
|
}
|
|
|
|
|
|
static int print_device_status(struct device *dev, void *data)
|
|
@@ -192,6 +217,23 @@ static int print_device_status(struct device *dev, void *data)
|
|
|
/* We only wait for device setup after most initcalls have run. */
|
|
|
static int ready_to_wait_for_devices;
|
|
|
|
|
|
+static bool wait_loop(unsigned long start, unsigned int max_delay,
|
|
|
+ unsigned int *seconds_waited)
|
|
|
+{
|
|
|
+ if (time_after(jiffies, start + (*seconds_waited+5)*HZ)) {
|
|
|
+ if (!*seconds_waited)
|
|
|
+ printk(KERN_WARNING "XENBUS: Waiting for "
|
|
|
+ "devices to initialise: ");
|
|
|
+ *seconds_waited += 5;
|
|
|
+ printk("%us...", max_delay - *seconds_waited);
|
|
|
+ if (*seconds_waited == max_delay)
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ schedule_timeout_interruptible(HZ/10);
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
/*
|
|
|
* On a 5-minute timeout, wait for all devices currently configured. We need
|
|
|
* to do this to guarantee that the filesystems and / or network devices
|
|
@@ -215,19 +257,14 @@ static void wait_for_devices(struct xenbus_driver *xendrv)
|
|
|
if (!ready_to_wait_for_devices || !xen_domain())
|
|
|
return;
|
|
|
|
|
|
- while (exists_connecting_device(drv)) {
|
|
|
- if (time_after(jiffies, start + (seconds_waited+5)*HZ)) {
|
|
|
- if (!seconds_waited)
|
|
|
- printk(KERN_WARNING "XENBUS: Waiting for "
|
|
|
- "devices to initialise: ");
|
|
|
- seconds_waited += 5;
|
|
|
- printk("%us...", 300 - seconds_waited);
|
|
|
- if (seconds_waited == 300)
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- schedule_timeout_interruptible(HZ/10);
|
|
|
- }
|
|
|
+ while (exists_non_essential_connecting_device(drv))
|
|
|
+ if (wait_loop(start, 30, &seconds_waited))
|
|
|
+ break;
|
|
|
+
|
|
|
+ /* Skips PVKB and PVFB check.*/
|
|
|
+ while (exists_essential_connecting_device(drv))
|
|
|
+ if (wait_loop(start, 270, &seconds_waited))
|
|
|
+ break;
|
|
|
|
|
|
if (seconds_waited)
|
|
|
printk("\n");
|