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 | |
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
-rw-r--r-- | arch/x86/xen/enlighten.c | 27 | ||||
-rw-r--r-- | arch/x86/xen/mmu.c | 2 | ||||
-rw-r--r-- | arch/x86/xen/smp.c | 1 | ||||
-rw-r--r-- | arch/x86/xen/suspend.c | 17 | ||||
-rw-r--r-- | arch/x86/xen/time.c | 7 | ||||
-rw-r--r-- | arch/x86/xen/xen-asm_64.S | 4 | ||||
-rw-r--r-- | arch/x86/xen/xen-ops.h | 2 | ||||
-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 |
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 | */ |
139 | void xen_vcpu_restore(void) | 139 | void 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 */ |
188 | static void __init xen_build_mfn_list_list(void) | 188 | void 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 | ||
28 | void xen_post_suspend(int suspend_cancelled) | 29 | void 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 | ||
50 | static 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 | |||
47 | void xen_arch_resume(void) | 61 | void 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 | ||
103 | static void setup_runstate_info(int cpu) | 103 | void 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 | ||
449 | void xen_teardown_timer(int cpu) | 447 | void 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 |
100 | 1: jmp hypercall_iret | 100 | 1: jmp hypercall_iret |
101 | ENDPATCH(xen_sysret32) | 101 | ENDPATCH(xen_sysret32) |
102 | RELOC(xen_sysret32, 1b+1) | 102 | RELOC(xen_sysret32, 1b+1) |
@@ -151,7 +151,7 @@ ENTRY(xen_syscall32_target) | |||
151 | ENTRY(xen_sysenter_target) | 151 | ENTRY(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 |
156 | ENDPROC(xen_syscall32_target) | 156 | ENDPROC(xen_syscall32_target) |
157 | ENDPROC(xen_sysenter_target) | 157 | ENDPROC(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 | ||
26 | void xen_setup_mfn_list_list(void); | 26 | void xen_setup_mfn_list_list(void); |
27 | void xen_setup_shared_info(void); | 27 | void xen_setup_shared_info(void); |
28 | void xen_build_mfn_list_list(void); | ||
28 | void xen_setup_machphys_mapping(void); | 29 | void xen_setup_machphys_mapping(void); |
29 | pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn); | 30 | pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn); |
30 | void xen_ident_map_ISA(void); | 31 | void xen_ident_map_ISA(void); |
@@ -41,6 +42,7 @@ void __init xen_build_dynamic_phys_to_machine(void); | |||
41 | 42 | ||
42 | void xen_init_irq_ops(void); | 43 | void xen_init_irq_ops(void); |
43 | void xen_setup_timer(int cpu); | 44 | void xen_setup_timer(int cpu); |
45 | void xen_setup_runstate_info(int cpu); | ||
44 | void xen_teardown_timer(int cpu); | 46 | void xen_teardown_timer(int cpu); |
45 | cycle_t xen_clocksource_read(void); | 47 | cycle_t xen_clocksource_read(void); |
46 | void xen_setup_cpu_clockevents(void); | 48 | void 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 | ||
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 | } |