diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-10 12:35:02 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-10 12:35:02 -0500 |
commit | ab1831b0b87851c874a75e4b3a8538e3d76b37d7 (patch) | |
tree | e2855518eb570ad09e2bdf5b3805cfa758e0abc3 /drivers/xen | |
parent | eae6fa9b0c3e2cb49cc157e906dd0ac52cfd7ca5 (diff) | |
parent | bc2c0303226ec716854d3c208c7f84fe7aa35cd7 (diff) |
Merge branch 'bugfix' of git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen
* 'bugfix' of git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen:
xen: try harder to balloon up under memory pressure.
Xen balloon: fix totalram_pages counting.
xen: explicitly create/destroy stop_machine workqueues outside suspend/resume region.
xen: improve error handling in do_suspend.
xen: don't leak IRQs over suspend/resume.
xen: call clock resume notifier on all CPUs
xen: use iret for return from 64b kernel to 32b usermode
xen: don't call dpm_resume_noirq() with interrupts disabled.
xen: register runstate info for boot CPU early
xen: register runstate on secondary CPUs
xen: register timer interrupt with IRQF_TIMER
xen: correctly restore pfn_to_mfn_list_list after resume
xen: restore runstate_info even if !have_vcpu_info_placement
xen: re-register runstate area earlier on resume.
xen: wait up to 5 minutes for device connetion
xen: improvement to wait_for_devices()
xen: fix is_disconnected_device/exists_disconnected_device
xen/xenbus: make DEVICE_ATTR()s static
Diffstat (limited to 'drivers/xen')
-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 d31505b6f7a..42043361358 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 2f57276e87a..ce602dd09bc 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 10d03d7931c..c4997930afc 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 d42e25d5968..649fcdf114b 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 | } |