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"); |