diff options
| -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 | } |
