aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-10 12:35:02 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-10 12:35:02 -0500
commitab1831b0b87851c874a75e4b3a8538e3d76b37d7 (patch)
treee2855518eb570ad09e2bdf5b3805cfa758e0abc3
parenteae6fa9b0c3e2cb49cc157e906dd0ac52cfd7ca5 (diff)
parentbc2c0303226ec716854d3c208c7f84fe7aa35cd7 (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
-rw-r--r--arch/x86/xen/enlighten.c27
-rw-r--r--arch/x86/xen/mmu.c2
-rw-r--r--arch/x86/xen/smp.c1
-rw-r--r--arch/x86/xen/suspend.c17
-rw-r--r--arch/x86/xen/time.c7
-rw-r--r--arch/x86/xen/xen-asm_64.S4
-rw-r--r--arch/x86/xen/xen-ops.h2
-rw-r--r--drivers/xen/balloon.c38
-rw-r--r--drivers/xen/events.c3
-rw-r--r--drivers/xen/manage.c37
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c48
11 files changed, 107 insertions, 79 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index c462cea8ef09..b8e45f164e2a 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -138,24 +138,23 @@ static void xen_vcpu_setup(int cpu)
138 */ 138 */
139void xen_vcpu_restore(void) 139void xen_vcpu_restore(void)
140{ 140{
141 if (have_vcpu_info_placement) { 141 int cpu;
142 int cpu;
143 142
144 for_each_online_cpu(cpu) { 143 for_each_online_cpu(cpu) {
145 bool other_cpu = (cpu != smp_processor_id()); 144 bool other_cpu = (cpu != smp_processor_id());
146 145
147 if (other_cpu && 146 if (other_cpu &&
148 HYPERVISOR_vcpu_op(VCPUOP_down, cpu, NULL)) 147 HYPERVISOR_vcpu_op(VCPUOP_down, cpu, NULL))
149 BUG(); 148 BUG();
150 149
151 xen_vcpu_setup(cpu); 150 xen_setup_runstate_info(cpu);
152 151
153 if (other_cpu && 152 if (have_vcpu_info_placement)
154 HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL)) 153 xen_vcpu_setup(cpu);
155 BUG();
156 }
157 154
158 BUG_ON(!have_vcpu_info_placement); 155 if (other_cpu &&
156 HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL))
157 BUG();
159 } 158 }
160} 159}
161 160
@@ -1180,6 +1179,8 @@ asmlinkage void __init xen_start_kernel(void)
1180 1179
1181 xen_raw_console_write("about to get started...\n"); 1180 xen_raw_console_write("about to get started...\n");
1182 1181
1182 xen_setup_runstate_info(0);
1183
1183 /* Start the world */ 1184 /* Start the world */
1184#ifdef CONFIG_X86_32 1185#ifdef CONFIG_X86_32
1185 i386_start_kernel(); 1186 i386_start_kernel();
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 3bf7b1d250ce..bf4cd6bfe959 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -185,7 +185,7 @@ static inline unsigned p2m_index(unsigned long pfn)
185} 185}
186 186
187/* Build the parallel p2m_top_mfn structures */ 187/* Build the parallel p2m_top_mfn structures */
188static void __init xen_build_mfn_list_list(void) 188void xen_build_mfn_list_list(void)
189{ 189{
190 unsigned pfn, idx; 190 unsigned pfn, idx;
191 191
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 738da0cb0d8b..64757c0ba5fc 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -295,6 +295,7 @@ static int __cpuinit xen_cpu_up(unsigned int cpu)
295 (unsigned long)task_stack_page(idle) - 295 (unsigned long)task_stack_page(idle) -
296 KERNEL_STACK_OFFSET + THREAD_SIZE; 296 KERNEL_STACK_OFFSET + THREAD_SIZE;
297#endif 297#endif
298 xen_setup_runstate_info(cpu);
298 xen_setup_timer(cpu); 299 xen_setup_timer(cpu);
299 xen_init_lock_cpu(cpu); 300 xen_init_lock_cpu(cpu);
300 301
diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
index 95be7b434724..987267f79bf5 100644
--- a/arch/x86/xen/suspend.c
+++ b/arch/x86/xen/suspend.c
@@ -1,4 +1,5 @@
1#include <linux/types.h> 1#include <linux/types.h>
2#include <linux/clockchips.h>
2 3
3#include <xen/interface/xen.h> 4#include <xen/interface/xen.h>
4#include <xen/grant_table.h> 5#include <xen/grant_table.h>
@@ -27,6 +28,8 @@ void xen_pre_suspend(void)
27 28
28void xen_post_suspend(int suspend_cancelled) 29void xen_post_suspend(int suspend_cancelled)
29{ 30{
31 xen_build_mfn_list_list();
32
30 xen_setup_shared_info(); 33 xen_setup_shared_info();
31 34
32 if (suspend_cancelled) { 35 if (suspend_cancelled) {
@@ -44,7 +47,19 @@ void xen_post_suspend(int suspend_cancelled)
44 47
45} 48}
46 49
50static void xen_vcpu_notify_restore(void *data)
51{
52 unsigned long reason = (unsigned long)data;
53
54 /* Boot processor notified via generic timekeeping_resume() */
55 if ( smp_processor_id() == 0)
56 return;
57
58 clockevents_notify(reason, NULL);
59}
60
47void xen_arch_resume(void) 61void xen_arch_resume(void)
48{ 62{
49 /* nothing */ 63 smp_call_function(xen_vcpu_notify_restore,
64 (void *)CLOCK_EVT_NOTIFY_RESUME, 1);
50} 65}
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index 0a5aa44299a5..9d1f853120d8 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -100,7 +100,7 @@ bool xen_vcpu_stolen(int vcpu)
100 return per_cpu(runstate, vcpu).state == RUNSTATE_runnable; 100 return per_cpu(runstate, vcpu).state == RUNSTATE_runnable;
101} 101}
102 102
103static void setup_runstate_info(int cpu) 103void xen_setup_runstate_info(int cpu)
104{ 104{
105 struct vcpu_register_runstate_memory_area area; 105 struct vcpu_register_runstate_memory_area area;
106 106
@@ -434,7 +434,7 @@ void xen_setup_timer(int cpu)
434 name = "<timer kasprintf failed>"; 434 name = "<timer kasprintf failed>";
435 435
436 irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt, 436 irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt,
437 IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING, 437 IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING|IRQF_TIMER,
438 name, NULL); 438 name, NULL);
439 439
440 evt = &per_cpu(xen_clock_events, cpu); 440 evt = &per_cpu(xen_clock_events, cpu);
@@ -442,8 +442,6 @@ void xen_setup_timer(int cpu)
442 442
443 evt->cpumask = cpumask_of(cpu); 443 evt->cpumask = cpumask_of(cpu);
444 evt->irq = irq; 444 evt->irq = irq;
445
446 setup_runstate_info(cpu);
447} 445}
448 446
449void xen_teardown_timer(int cpu) 447void xen_teardown_timer(int cpu)
@@ -494,6 +492,7 @@ __init void xen_time_init(void)
494 492
495 setup_force_cpu_cap(X86_FEATURE_TSC); 493 setup_force_cpu_cap(X86_FEATURE_TSC);
496 494
495 xen_setup_runstate_info(cpu);
497 xen_setup_timer(cpu); 496 xen_setup_timer(cpu);
498 xen_setup_cpu_clockevents(); 497 xen_setup_cpu_clockevents();
499} 498}
diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S
index 02f496a8dbaa..53adefda4275 100644
--- a/arch/x86/xen/xen-asm_64.S
+++ b/arch/x86/xen/xen-asm_64.S
@@ -96,7 +96,7 @@ ENTRY(xen_sysret32)
96 pushq $__USER32_CS 96 pushq $__USER32_CS
97 pushq %rcx 97 pushq %rcx
98 98
99 pushq $VGCF_in_syscall 99 pushq $0
1001: jmp hypercall_iret 1001: jmp hypercall_iret
101ENDPATCH(xen_sysret32) 101ENDPATCH(xen_sysret32)
102RELOC(xen_sysret32, 1b+1) 102RELOC(xen_sysret32, 1b+1)
@@ -151,7 +151,7 @@ ENTRY(xen_syscall32_target)
151ENTRY(xen_sysenter_target) 151ENTRY(xen_sysenter_target)
152 lea 16(%rsp), %rsp /* strip %rcx, %r11 */ 152 lea 16(%rsp), %rsp /* strip %rcx, %r11 */
153 mov $-ENOSYS, %rax 153 mov $-ENOSYS, %rax
154 pushq $VGCF_in_syscall 154 pushq $0
155 jmp hypercall_iret 155 jmp hypercall_iret
156ENDPROC(xen_syscall32_target) 156ENDPROC(xen_syscall32_target)
157ENDPROC(xen_sysenter_target) 157ENDPROC(xen_sysenter_target)
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 355fa6b99c9c..f9153a300bce 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -25,6 +25,7 @@ extern struct shared_info *HYPERVISOR_shared_info;
25 25
26void xen_setup_mfn_list_list(void); 26void xen_setup_mfn_list_list(void);
27void xen_setup_shared_info(void); 27void xen_setup_shared_info(void);
28void xen_build_mfn_list_list(void);
28void xen_setup_machphys_mapping(void); 29void xen_setup_machphys_mapping(void);
29pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn); 30pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn);
30void xen_ident_map_ISA(void); 31void xen_ident_map_ISA(void);
@@ -41,6 +42,7 @@ void __init xen_build_dynamic_phys_to_machine(void);
41 42
42void xen_init_irq_ops(void); 43void xen_init_irq_ops(void);
43void xen_setup_timer(int cpu); 44void xen_setup_timer(int cpu);
45void xen_setup_runstate_info(int cpu);
44void xen_teardown_timer(int cpu); 46void xen_teardown_timer(int cpu);
45cycle_t xen_clocksource_read(void); 47cycle_t xen_clocksource_read(void);
46void xen_setup_cpu_clockevents(void); 48void xen_setup_cpu_clockevents(void);
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
182static unsigned long current_target(void) 184static 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
271static int decrease_reservation(unsigned long nr_pages) 259static 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)
367static void balloon_set_new_target(unsigned long target) 354static 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);
472BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages)); 456BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages));
473BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low)); 457BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low));
474BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high)); 458BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high));
475BALLOON_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);
478BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages)); 459BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages));
479 460
480static ssize_t show_target_kb(struct sys_device *dev, struct sysdev_attribute *attr, 461static 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); 129out_resume:
123
124resume_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();
129out: 134
135out_thaw:
130#ifdef CONFIG_PREEMPT 136#ifdef CONFIG_PREEMPT
131 thaw_processes(); 137 thaw_processes();
138
139out_destroy_sm:
132#endif 140#endif
141 stop_machine_destroy();
142
143out:
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}
457DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL); 457static DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL);
458 458
459static ssize_t xendev_show_devtype(struct device *dev, 459static 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}
464DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL); 464static DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL);
465 465
466static ssize_t xendev_show_modalias(struct device *dev, 466static 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}
471DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL); 471static DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL);
472 472
473int xenbus_probe_node(struct xen_bus_type *bus, 473int 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
844MODULE_LICENSE("GPL"); 844MODULE_LICENSE("GPL");
845 845
846static int is_disconnected_device(struct device *dev, void *data) 846static 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
868static int exists_disconnected_device(struct device_driver *drv) 869static 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
874static int print_device_status(struct device *dev, void *data) 875static 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)
897static int ready_to_wait_for_devices; 901static 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 */
913static void wait_for_devices(struct xenbus_driver *xendrv) 917static 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}