diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/xen/balloon.c | 38 | ||||
| -rw-r--r-- | drivers/xen/events.c | 3 | ||||
| -rw-r--r-- | drivers/xen/manage.c | 37 | ||||
| -rw-r--r-- | drivers/xen/xenbus/xenbus_probe.c | 48 |
4 files changed, 68 insertions, 58 deletions
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index d31505b6f7a4..420433613584 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c | |||
| @@ -66,8 +66,6 @@ struct balloon_stats { | |||
| 66 | /* We aim for 'current allocation' == 'target allocation'. */ | 66 | /* We aim for 'current allocation' == 'target allocation'. */ |
| 67 | unsigned long current_pages; | 67 | unsigned long current_pages; |
| 68 | unsigned long target_pages; | 68 | unsigned long target_pages; |
| 69 | /* We may hit the hard limit in Xen. If we do then we remember it. */ | ||
| 70 | unsigned long hard_limit; | ||
| 71 | /* | 69 | /* |
| 72 | * Drivers may alter the memory reservation independently, but they | 70 | * Drivers may alter the memory reservation independently, but they |
| 73 | * must inform the balloon driver so we avoid hitting the hard limit. | 71 | * must inform the balloon driver so we avoid hitting the hard limit. |
| @@ -136,6 +134,8 @@ static void balloon_append(struct page *page) | |||
| 136 | list_add(&page->lru, &ballooned_pages); | 134 | list_add(&page->lru, &ballooned_pages); |
| 137 | balloon_stats.balloon_low++; | 135 | balloon_stats.balloon_low++; |
| 138 | } | 136 | } |
| 137 | |||
| 138 | totalram_pages--; | ||
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */ | 141 | /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */ |
| @@ -156,6 +156,8 @@ static struct page *balloon_retrieve(void) | |||
| 156 | else | 156 | else |
| 157 | balloon_stats.balloon_low--; | 157 | balloon_stats.balloon_low--; |
| 158 | 158 | ||
| 159 | totalram_pages++; | ||
| 160 | |||
| 159 | return page; | 161 | return page; |
| 160 | } | 162 | } |
| 161 | 163 | ||
| @@ -181,7 +183,7 @@ static void balloon_alarm(unsigned long unused) | |||
| 181 | 183 | ||
| 182 | static unsigned long current_target(void) | 184 | static unsigned long current_target(void) |
| 183 | { | 185 | { |
| 184 | unsigned long target = min(balloon_stats.target_pages, balloon_stats.hard_limit); | 186 | unsigned long target = balloon_stats.target_pages; |
| 185 | 187 | ||
| 186 | target = min(target, | 188 | target = min(target, |
| 187 | balloon_stats.current_pages + | 189 | balloon_stats.current_pages + |
| @@ -217,23 +219,10 @@ static int increase_reservation(unsigned long nr_pages) | |||
| 217 | set_xen_guest_handle(reservation.extent_start, frame_list); | 219 | set_xen_guest_handle(reservation.extent_start, frame_list); |
| 218 | reservation.nr_extents = nr_pages; | 220 | reservation.nr_extents = nr_pages; |
| 219 | rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); | 221 | rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); |
| 220 | if (rc < nr_pages) { | 222 | if (rc < 0) |
| 221 | if (rc > 0) { | ||
| 222 | int ret; | ||
| 223 | |||
| 224 | /* We hit the Xen hard limit: reprobe. */ | ||
| 225 | reservation.nr_extents = rc; | ||
| 226 | ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, | ||
| 227 | &reservation); | ||
| 228 | BUG_ON(ret != rc); | ||
| 229 | } | ||
| 230 | if (rc >= 0) | ||
| 231 | balloon_stats.hard_limit = (balloon_stats.current_pages + rc - | ||
| 232 | balloon_stats.driver_pages); | ||
| 233 | goto out; | 223 | goto out; |
| 234 | } | ||
| 235 | 224 | ||
| 236 | for (i = 0; i < nr_pages; i++) { | 225 | for (i = 0; i < rc; i++) { |
| 237 | page = balloon_retrieve(); | 226 | page = balloon_retrieve(); |
| 238 | BUG_ON(page == NULL); | 227 | BUG_ON(page == NULL); |
| 239 | 228 | ||
| @@ -259,13 +248,12 @@ static int increase_reservation(unsigned long nr_pages) | |||
| 259 | __free_page(page); | 248 | __free_page(page); |
| 260 | } | 249 | } |
| 261 | 250 | ||
| 262 | balloon_stats.current_pages += nr_pages; | 251 | balloon_stats.current_pages += rc; |
| 263 | totalram_pages = balloon_stats.current_pages; | ||
| 264 | 252 | ||
| 265 | out: | 253 | out: |
| 266 | spin_unlock_irqrestore(&balloon_lock, flags); | 254 | spin_unlock_irqrestore(&balloon_lock, flags); |
| 267 | 255 | ||
| 268 | return 0; | 256 | return rc < 0 ? rc : rc != nr_pages; |
| 269 | } | 257 | } |
| 270 | 258 | ||
| 271 | static int decrease_reservation(unsigned long nr_pages) | 259 | static int decrease_reservation(unsigned long nr_pages) |
| @@ -323,7 +311,6 @@ static int decrease_reservation(unsigned long nr_pages) | |||
| 323 | BUG_ON(ret != nr_pages); | 311 | BUG_ON(ret != nr_pages); |
| 324 | 312 | ||
| 325 | balloon_stats.current_pages -= nr_pages; | 313 | balloon_stats.current_pages -= nr_pages; |
| 326 | totalram_pages = balloon_stats.current_pages; | ||
| 327 | 314 | ||
| 328 | spin_unlock_irqrestore(&balloon_lock, flags); | 315 | spin_unlock_irqrestore(&balloon_lock, flags); |
| 329 | 316 | ||
| @@ -367,7 +354,6 @@ static void balloon_process(struct work_struct *work) | |||
| 367 | static void balloon_set_new_target(unsigned long target) | 354 | static void balloon_set_new_target(unsigned long target) |
| 368 | { | 355 | { |
| 369 | /* No need for lock. Not read-modify-write updates. */ | 356 | /* No need for lock. Not read-modify-write updates. */ |
| 370 | balloon_stats.hard_limit = ~0UL; | ||
| 371 | balloon_stats.target_pages = target; | 357 | balloon_stats.target_pages = target; |
| 372 | schedule_work(&balloon_worker); | 358 | schedule_work(&balloon_worker); |
| 373 | } | 359 | } |
| @@ -422,12 +408,10 @@ static int __init balloon_init(void) | |||
| 422 | pr_info("xen_balloon: Initialising balloon driver.\n"); | 408 | pr_info("xen_balloon: Initialising balloon driver.\n"); |
| 423 | 409 | ||
| 424 | balloon_stats.current_pages = min(xen_start_info->nr_pages, max_pfn); | 410 | balloon_stats.current_pages = min(xen_start_info->nr_pages, max_pfn); |
| 425 | totalram_pages = balloon_stats.current_pages; | ||
| 426 | balloon_stats.target_pages = balloon_stats.current_pages; | 411 | balloon_stats.target_pages = balloon_stats.current_pages; |
| 427 | balloon_stats.balloon_low = 0; | 412 | balloon_stats.balloon_low = 0; |
| 428 | balloon_stats.balloon_high = 0; | 413 | balloon_stats.balloon_high = 0; |
| 429 | balloon_stats.driver_pages = 0UL; | 414 | balloon_stats.driver_pages = 0UL; |
| 430 | balloon_stats.hard_limit = ~0UL; | ||
| 431 | 415 | ||
| 432 | init_timer(&balloon_timer); | 416 | init_timer(&balloon_timer); |
| 433 | balloon_timer.data = 0; | 417 | balloon_timer.data = 0; |
| @@ -472,9 +456,6 @@ module_exit(balloon_exit); | |||
| 472 | BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages)); | 456 | BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages)); |
| 473 | BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low)); | 457 | BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low)); |
| 474 | BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high)); | 458 | BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high)); |
| 475 | BALLOON_SHOW(hard_limit_kb, | ||
| 476 | (balloon_stats.hard_limit!=~0UL) ? "%lu\n" : "???\n", | ||
| 477 | (balloon_stats.hard_limit!=~0UL) ? PAGES2KB(balloon_stats.hard_limit) : 0); | ||
| 478 | BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages)); | 459 | BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages)); |
| 479 | 460 | ||
| 480 | static ssize_t show_target_kb(struct sys_device *dev, struct sysdev_attribute *attr, | 461 | static ssize_t show_target_kb(struct sys_device *dev, struct sysdev_attribute *attr, |
| @@ -544,7 +525,6 @@ static struct attribute *balloon_info_attrs[] = { | |||
| 544 | &attr_current_kb.attr, | 525 | &attr_current_kb.attr, |
| 545 | &attr_low_kb.attr, | 526 | &attr_low_kb.attr, |
| 546 | &attr_high_kb.attr, | 527 | &attr_high_kb.attr, |
| 547 | &attr_hard_limit_kb.attr, | ||
| 548 | &attr_driver_kb.attr, | 528 | &attr_driver_kb.attr, |
| 549 | NULL | 529 | NULL |
| 550 | }; | 530 | }; |
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 2f57276e87a2..ce602dd09bc1 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
| @@ -474,6 +474,9 @@ static void unbind_from_irq(unsigned int irq) | |||
| 474 | bind_evtchn_to_cpu(evtchn, 0); | 474 | bind_evtchn_to_cpu(evtchn, 0); |
| 475 | 475 | ||
| 476 | evtchn_to_irq[evtchn] = -1; | 476 | evtchn_to_irq[evtchn] = -1; |
| 477 | } | ||
| 478 | |||
| 479 | if (irq_info[irq].type != IRQT_UNBOUND) { | ||
| 477 | irq_info[irq] = mk_unbound_info(); | 480 | irq_info[irq] = mk_unbound_info(); |
| 478 | 481 | ||
| 479 | dynamic_irq_cleanup(irq); | 482 | dynamic_irq_cleanup(irq); |
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 10d03d7931c4..c4997930afc7 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
| @@ -43,7 +43,6 @@ static int xen_suspend(void *data) | |||
| 43 | if (err) { | 43 | if (err) { |
| 44 | printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n", | 44 | printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n", |
| 45 | err); | 45 | err); |
| 46 | dpm_resume_noirq(PMSG_RESUME); | ||
| 47 | return err; | 46 | return err; |
| 48 | } | 47 | } |
| 49 | 48 | ||
| @@ -69,7 +68,6 @@ static int xen_suspend(void *data) | |||
| 69 | } | 68 | } |
| 70 | 69 | ||
| 71 | sysdev_resume(); | 70 | sysdev_resume(); |
| 72 | dpm_resume_noirq(PMSG_RESUME); | ||
| 73 | 71 | ||
| 74 | return 0; | 72 | return 0; |
| 75 | } | 73 | } |
| @@ -81,6 +79,12 @@ static void do_suspend(void) | |||
| 81 | 79 | ||
| 82 | shutting_down = SHUTDOWN_SUSPEND; | 80 | shutting_down = SHUTDOWN_SUSPEND; |
| 83 | 81 | ||
| 82 | err = stop_machine_create(); | ||
| 83 | if (err) { | ||
| 84 | printk(KERN_ERR "xen suspend: failed to setup stop_machine %d\n", err); | ||
| 85 | goto out; | ||
| 86 | } | ||
| 87 | |||
| 84 | #ifdef CONFIG_PREEMPT | 88 | #ifdef CONFIG_PREEMPT |
| 85 | /* If the kernel is preemptible, we need to freeze all the processes | 89 | /* If the kernel is preemptible, we need to freeze all the processes |
| 86 | to prevent them from being in the middle of a pagetable update | 90 | to prevent them from being in the middle of a pagetable update |
| @@ -88,29 +92,32 @@ static void do_suspend(void) | |||
| 88 | err = freeze_processes(); | 92 | err = freeze_processes(); |
| 89 | if (err) { | 93 | if (err) { |
| 90 | printk(KERN_ERR "xen suspend: freeze failed %d\n", err); | 94 | printk(KERN_ERR "xen suspend: freeze failed %d\n", err); |
| 91 | return; | 95 | goto out_destroy_sm; |
| 92 | } | 96 | } |
| 93 | #endif | 97 | #endif |
| 94 | 98 | ||
| 95 | err = dpm_suspend_start(PMSG_SUSPEND); | 99 | err = dpm_suspend_start(PMSG_SUSPEND); |
| 96 | if (err) { | 100 | if (err) { |
| 97 | printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err); | 101 | printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err); |
| 98 | goto out; | 102 | goto out_thaw; |
| 99 | } | 103 | } |
| 100 | 104 | ||
| 101 | printk(KERN_DEBUG "suspending xenstore...\n"); | ||
| 102 | xs_suspend(); | ||
| 103 | |||
| 104 | err = dpm_suspend_noirq(PMSG_SUSPEND); | 105 | err = dpm_suspend_noirq(PMSG_SUSPEND); |
| 105 | if (err) { | 106 | if (err) { |
| 106 | printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err); | 107 | printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err); |
| 107 | goto resume_devices; | 108 | goto out_resume; |
| 108 | } | 109 | } |
| 109 | 110 | ||
| 111 | printk(KERN_DEBUG "suspending xenstore...\n"); | ||
| 112 | xs_suspend(); | ||
| 113 | |||
| 110 | err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); | 114 | err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); |
| 115 | |||
| 116 | dpm_resume_noirq(PMSG_RESUME); | ||
| 117 | |||
| 111 | if (err) { | 118 | if (err) { |
| 112 | printk(KERN_ERR "failed to start xen_suspend: %d\n", err); | 119 | printk(KERN_ERR "failed to start xen_suspend: %d\n", err); |
| 113 | goto out; | 120 | cancelled = 1; |
| 114 | } | 121 | } |
| 115 | 122 | ||
| 116 | if (!cancelled) { | 123 | if (!cancelled) { |
| @@ -119,17 +126,21 @@ static void do_suspend(void) | |||
| 119 | } else | 126 | } else |
| 120 | xs_suspend_cancel(); | 127 | xs_suspend_cancel(); |
| 121 | 128 | ||
| 122 | dpm_resume_noirq(PMSG_RESUME); | 129 | out_resume: |
| 123 | |||
| 124 | resume_devices: | ||
| 125 | dpm_resume_end(PMSG_RESUME); | 130 | dpm_resume_end(PMSG_RESUME); |
| 126 | 131 | ||
| 127 | /* Make sure timer events get retriggered on all CPUs */ | 132 | /* Make sure timer events get retriggered on all CPUs */ |
| 128 | clock_was_set(); | 133 | clock_was_set(); |
| 129 | out: | 134 | |
| 135 | out_thaw: | ||
| 130 | #ifdef CONFIG_PREEMPT | 136 | #ifdef CONFIG_PREEMPT |
| 131 | thaw_processes(); | 137 | thaw_processes(); |
| 138 | |||
| 139 | out_destroy_sm: | ||
| 132 | #endif | 140 | #endif |
| 141 | stop_machine_destroy(); | ||
| 142 | |||
| 143 | out: | ||
| 133 | shutting_down = SHUTDOWN_INVALID; | 144 | shutting_down = SHUTDOWN_INVALID; |
| 134 | } | 145 | } |
| 135 | #endif /* CONFIG_PM_SLEEP */ | 146 | #endif /* CONFIG_PM_SLEEP */ |
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index d42e25d5968d..649fcdf114b7 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c | |||
| @@ -454,21 +454,21 @@ static ssize_t xendev_show_nodename(struct device *dev, | |||
| 454 | { | 454 | { |
| 455 | return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename); | 455 | return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename); |
| 456 | } | 456 | } |
| 457 | DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL); | 457 | static DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL); |
| 458 | 458 | ||
| 459 | static ssize_t xendev_show_devtype(struct device *dev, | 459 | static ssize_t xendev_show_devtype(struct device *dev, |
| 460 | struct device_attribute *attr, char *buf) | 460 | struct device_attribute *attr, char *buf) |
| 461 | { | 461 | { |
| 462 | return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype); | 462 | return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype); |
| 463 | } | 463 | } |
| 464 | DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL); | 464 | static DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL); |
| 465 | 465 | ||
| 466 | static ssize_t xendev_show_modalias(struct device *dev, | 466 | static ssize_t xendev_show_modalias(struct device *dev, |
| 467 | struct device_attribute *attr, char *buf) | 467 | struct device_attribute *attr, char *buf) |
| 468 | { | 468 | { |
| 469 | return sprintf(buf, "xen:%s\n", to_xenbus_device(dev)->devicetype); | 469 | return sprintf(buf, "xen:%s\n", to_xenbus_device(dev)->devicetype); |
| 470 | } | 470 | } |
| 471 | DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL); | 471 | static DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL); |
| 472 | 472 | ||
| 473 | int xenbus_probe_node(struct xen_bus_type *bus, | 473 | int xenbus_probe_node(struct xen_bus_type *bus, |
| 474 | const char *type, | 474 | const char *type, |
| @@ -843,7 +843,7 @@ postcore_initcall(xenbus_probe_init); | |||
| 843 | 843 | ||
| 844 | MODULE_LICENSE("GPL"); | 844 | MODULE_LICENSE("GPL"); |
| 845 | 845 | ||
| 846 | static int is_disconnected_device(struct device *dev, void *data) | 846 | static int is_device_connecting(struct device *dev, void *data) |
| 847 | { | 847 | { |
| 848 | struct xenbus_device *xendev = to_xenbus_device(dev); | 848 | struct xenbus_device *xendev = to_xenbus_device(dev); |
| 849 | struct device_driver *drv = data; | 849 | struct device_driver *drv = data; |
| @@ -861,14 +861,15 @@ static int is_disconnected_device(struct device *dev, void *data) | |||
| 861 | return 0; | 861 | return 0; |
| 862 | 862 | ||
| 863 | xendrv = to_xenbus_driver(dev->driver); | 863 | xendrv = to_xenbus_driver(dev->driver); |
| 864 | return (xendev->state != XenbusStateConnected || | 864 | return (xendev->state < XenbusStateConnected || |
| 865 | (xendrv->is_ready && !xendrv->is_ready(xendev))); | 865 | (xendev->state == XenbusStateConnected && |
| 866 | xendrv->is_ready && !xendrv->is_ready(xendev))); | ||
| 866 | } | 867 | } |
| 867 | 868 | ||
| 868 | static int exists_disconnected_device(struct device_driver *drv) | 869 | static int exists_connecting_device(struct device_driver *drv) |
| 869 | { | 870 | { |
| 870 | return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, | 871 | return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, |
| 871 | is_disconnected_device); | 872 | is_device_connecting); |
| 872 | } | 873 | } |
| 873 | 874 | ||
| 874 | static int print_device_status(struct device *dev, void *data) | 875 | static int print_device_status(struct device *dev, void *data) |
| @@ -884,10 +885,13 @@ static int print_device_status(struct device *dev, void *data) | |||
| 884 | /* Information only: is this too noisy? */ | 885 | /* Information only: is this too noisy? */ |
| 885 | printk(KERN_INFO "XENBUS: Device with no driver: %s\n", | 886 | printk(KERN_INFO "XENBUS: Device with no driver: %s\n", |
| 886 | xendev->nodename); | 887 | xendev->nodename); |
| 887 | } else if (xendev->state != XenbusStateConnected) { | 888 | } else if (xendev->state < XenbusStateConnected) { |
| 889 | enum xenbus_state rstate = XenbusStateUnknown; | ||
| 890 | if (xendev->otherend) | ||
| 891 | rstate = xenbus_read_driver_state(xendev->otherend); | ||
| 888 | printk(KERN_WARNING "XENBUS: Timeout connecting " | 892 | printk(KERN_WARNING "XENBUS: Timeout connecting " |
| 889 | "to device: %s (state %d)\n", | 893 | "to device: %s (local state %d, remote state %d)\n", |
| 890 | xendev->nodename, xendev->state); | 894 | xendev->nodename, xendev->state, rstate); |
| 891 | } | 895 | } |
| 892 | 896 | ||
| 893 | return 0; | 897 | return 0; |
| @@ -897,7 +901,7 @@ static int print_device_status(struct device *dev, void *data) | |||
| 897 | static int ready_to_wait_for_devices; | 901 | static int ready_to_wait_for_devices; |
| 898 | 902 | ||
| 899 | /* | 903 | /* |
| 900 | * On a 10 second timeout, wait for all devices currently configured. We need | 904 | * On a 5-minute timeout, wait for all devices currently configured. We need |
| 901 | * to do this to guarantee that the filesystems and / or network devices | 905 | * to do this to guarantee that the filesystems and / or network devices |
| 902 | * needed for boot are available, before we can allow the boot to proceed. | 906 | * needed for boot are available, before we can allow the boot to proceed. |
| 903 | * | 907 | * |
| @@ -912,18 +916,30 @@ static int ready_to_wait_for_devices; | |||
| 912 | */ | 916 | */ |
| 913 | static void wait_for_devices(struct xenbus_driver *xendrv) | 917 | static void wait_for_devices(struct xenbus_driver *xendrv) |
| 914 | { | 918 | { |
| 915 | unsigned long timeout = jiffies + 10*HZ; | 919 | unsigned long start = jiffies; |
| 916 | struct device_driver *drv = xendrv ? &xendrv->driver : NULL; | 920 | struct device_driver *drv = xendrv ? &xendrv->driver : NULL; |
| 921 | unsigned int seconds_waited = 0; | ||
| 917 | 922 | ||
| 918 | if (!ready_to_wait_for_devices || !xen_domain()) | 923 | if (!ready_to_wait_for_devices || !xen_domain()) |
| 919 | return; | 924 | return; |
| 920 | 925 | ||
| 921 | while (exists_disconnected_device(drv)) { | 926 | while (exists_connecting_device(drv)) { |
| 922 | if (time_after(jiffies, timeout)) | 927 | if (time_after(jiffies, start + (seconds_waited+5)*HZ)) { |
| 923 | break; | 928 | if (!seconds_waited) |
| 929 | printk(KERN_WARNING "XENBUS: Waiting for " | ||
| 930 | "devices to initialise: "); | ||
| 931 | seconds_waited += 5; | ||
| 932 | printk("%us...", 300 - seconds_waited); | ||
| 933 | if (seconds_waited == 300) | ||
| 934 | break; | ||
| 935 | } | ||
| 936 | |||
| 924 | schedule_timeout_interruptible(HZ/10); | 937 | schedule_timeout_interruptible(HZ/10); |
| 925 | } | 938 | } |
| 926 | 939 | ||
| 940 | if (seconds_waited) | ||
| 941 | printk("\n"); | ||
| 942 | |||
| 927 | bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, | 943 | bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, |
| 928 | print_device_status); | 944 | print_device_status); |
| 929 | } | 945 | } |
