diff options
Diffstat (limited to 'drivers/xen/xenbus/xenbus_probe_frontend.c')
| -rw-r--r-- | drivers/xen/xenbus/xenbus_probe_frontend.c | 69 |
1 files changed, 53 insertions, 16 deletions
diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c index f20c5f178b40..a31b54d48839 100644 --- a/drivers/xen/xenbus/xenbus_probe_frontend.c +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c | |||
| @@ -135,7 +135,7 @@ static int read_backend_details(struct xenbus_device *xendev) | |||
| 135 | return xenbus_read_otherend_details(xendev, "backend-id", "backend"); | 135 | return xenbus_read_otherend_details(xendev, "backend-id", "backend"); |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | static int is_device_connecting(struct device *dev, void *data) | 138 | static int is_device_connecting(struct device *dev, void *data, bool ignore_nonessential) |
| 139 | { | 139 | { |
| 140 | struct xenbus_device *xendev = to_xenbus_device(dev); | 140 | struct xenbus_device *xendev = to_xenbus_device(dev); |
| 141 | struct device_driver *drv = data; | 141 | struct device_driver *drv = data; |
| @@ -152,16 +152,41 @@ static int is_device_connecting(struct device *dev, void *data) | |||
| 152 | if (drv && (dev->driver != drv)) | 152 | if (drv && (dev->driver != drv)) |
| 153 | return 0; | 153 | return 0; |
| 154 | 154 | ||
| 155 | if (ignore_nonessential) { | ||
| 156 | /* With older QEMU, for PVonHVM guests the guest config files | ||
| 157 | * could contain: vfb = [ 'vnc=1, vnclisten=0.0.0.0'] | ||
| 158 | * which is nonsensical as there is no PV FB (there can be | ||
| 159 | * a PVKB) running as HVM guest. */ | ||
| 160 | |||
| 161 | if ((strncmp(xendev->nodename, "device/vkbd", 11) == 0)) | ||
| 162 | return 0; | ||
| 163 | |||
| 164 | if ((strncmp(xendev->nodename, "device/vfb", 10) == 0)) | ||
| 165 | return 0; | ||
| 166 | } | ||
| 155 | xendrv = to_xenbus_driver(dev->driver); | 167 | xendrv = to_xenbus_driver(dev->driver); |
| 156 | return (xendev->state < XenbusStateConnected || | 168 | return (xendev->state < XenbusStateConnected || |
| 157 | (xendev->state == XenbusStateConnected && | 169 | (xendev->state == XenbusStateConnected && |
| 158 | xendrv->is_ready && !xendrv->is_ready(xendev))); | 170 | xendrv->is_ready && !xendrv->is_ready(xendev))); |
| 159 | } | 171 | } |
| 172 | static int essential_device_connecting(struct device *dev, void *data) | ||
| 173 | { | ||
| 174 | return is_device_connecting(dev, data, true /* ignore PV[KBB+FB] */); | ||
| 175 | } | ||
| 176 | static int non_essential_device_connecting(struct device *dev, void *data) | ||
| 177 | { | ||
| 178 | return is_device_connecting(dev, data, false); | ||
| 179 | } | ||
| 160 | 180 | ||
| 161 | static int exists_connecting_device(struct device_driver *drv) | 181 | static int exists_essential_connecting_device(struct device_driver *drv) |
| 162 | { | 182 | { |
| 163 | return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, | 183 | return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, |
| 164 | is_device_connecting); | 184 | essential_device_connecting); |
| 185 | } | ||
| 186 | static int exists_non_essential_connecting_device(struct device_driver *drv) | ||
| 187 | { | ||
| 188 | return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, | ||
| 189 | non_essential_device_connecting); | ||
| 165 | } | 190 | } |
| 166 | 191 | ||
| 167 | static int print_device_status(struct device *dev, void *data) | 192 | static int print_device_status(struct device *dev, void *data) |
| @@ -192,6 +217,23 @@ static int print_device_status(struct device *dev, void *data) | |||
| 192 | /* We only wait for device setup after most initcalls have run. */ | 217 | /* We only wait for device setup after most initcalls have run. */ |
| 193 | static int ready_to_wait_for_devices; | 218 | static int ready_to_wait_for_devices; |
| 194 | 219 | ||
| 220 | static bool wait_loop(unsigned long start, unsigned int max_delay, | ||
| 221 | unsigned int *seconds_waited) | ||
| 222 | { | ||
| 223 | if (time_after(jiffies, start + (*seconds_waited+5)*HZ)) { | ||
| 224 | if (!*seconds_waited) | ||
| 225 | printk(KERN_WARNING "XENBUS: Waiting for " | ||
| 226 | "devices to initialise: "); | ||
| 227 | *seconds_waited += 5; | ||
| 228 | printk("%us...", max_delay - *seconds_waited); | ||
| 229 | if (*seconds_waited == max_delay) | ||
| 230 | return true; | ||
| 231 | } | ||
| 232 | |||
| 233 | schedule_timeout_interruptible(HZ/10); | ||
| 234 | |||
| 235 | return false; | ||
| 236 | } | ||
| 195 | /* | 237 | /* |
| 196 | * On a 5-minute timeout, wait for all devices currently configured. We need | 238 | * On a 5-minute timeout, wait for all devices currently configured. We need |
| 197 | * to do this to guarantee that the filesystems and / or network devices | 239 | * 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) | |||
| 215 | if (!ready_to_wait_for_devices || !xen_domain()) | 257 | if (!ready_to_wait_for_devices || !xen_domain()) |
| 216 | return; | 258 | return; |
| 217 | 259 | ||
| 218 | while (exists_connecting_device(drv)) { | 260 | while (exists_non_essential_connecting_device(drv)) |
| 219 | if (time_after(jiffies, start + (seconds_waited+5)*HZ)) { | 261 | if (wait_loop(start, 30, &seconds_waited)) |
| 220 | if (!seconds_waited) | 262 | break; |
| 221 | printk(KERN_WARNING "XENBUS: Waiting for " | 263 | |
| 222 | "devices to initialise: "); | 264 | /* Skips PVKB and PVFB check.*/ |
| 223 | seconds_waited += 5; | 265 | while (exists_essential_connecting_device(drv)) |
| 224 | printk("%us...", 300 - seconds_waited); | 266 | if (wait_loop(start, 270, &seconds_waited)) |
| 225 | if (seconds_waited == 300) | 267 | break; |
| 226 | break; | ||
| 227 | } | ||
| 228 | |||
| 229 | schedule_timeout_interruptible(HZ/10); | ||
| 230 | } | ||
| 231 | 268 | ||
| 232 | if (seconds_waited) | 269 | if (seconds_waited) |
| 233 | printk("\n"); | 270 | printk("\n"); |
