diff options
Diffstat (limited to 'drivers/xen')
-rw-r--r-- | drivers/xen/balloon.c | 16 | ||||
-rw-r--r-- | drivers/xen/events.c | 380 | ||||
-rw-r--r-- | drivers/xen/manage.c | 143 | ||||
-rw-r--r-- | drivers/xen/platform-pci.c | 3 |
4 files changed, 261 insertions, 281 deletions
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 8c81cd24ed8..043af8ad6b6 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c | |||
@@ -246,7 +246,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages) | |||
246 | set_phys_to_machine(pfn, frame_list[i]); | 246 | set_phys_to_machine(pfn, frame_list[i]); |
247 | 247 | ||
248 | /* Link back into the page tables if not highmem. */ | 248 | /* Link back into the page tables if not highmem. */ |
249 | if (pfn < max_low_pfn) { | 249 | if (!xen_hvm_domain() && pfn < max_low_pfn) { |
250 | int ret; | 250 | int ret; |
251 | ret = HYPERVISOR_update_va_mapping( | 251 | ret = HYPERVISOR_update_va_mapping( |
252 | (unsigned long)__va(pfn << PAGE_SHIFT), | 252 | (unsigned long)__va(pfn << PAGE_SHIFT), |
@@ -293,7 +293,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) | |||
293 | 293 | ||
294 | scrub_page(page); | 294 | scrub_page(page); |
295 | 295 | ||
296 | if (!PageHighMem(page)) { | 296 | if (!xen_hvm_domain() && !PageHighMem(page)) { |
297 | ret = HYPERVISOR_update_va_mapping( | 297 | ret = HYPERVISOR_update_va_mapping( |
298 | (unsigned long)__va(pfn << PAGE_SHIFT), | 298 | (unsigned long)__va(pfn << PAGE_SHIFT), |
299 | __pte_ma(0), 0); | 299 | __pte_ma(0), 0); |
@@ -309,7 +309,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) | |||
309 | /* No more mappings: invalidate P2M and add to balloon. */ | 309 | /* No more mappings: invalidate P2M and add to balloon. */ |
310 | for (i = 0; i < nr_pages; i++) { | 310 | for (i = 0; i < nr_pages; i++) { |
311 | pfn = mfn_to_pfn(frame_list[i]); | 311 | pfn = mfn_to_pfn(frame_list[i]); |
312 | set_phys_to_machine(pfn, INVALID_P2M_ENTRY); | 312 | __set_phys_to_machine(pfn, INVALID_P2M_ENTRY); |
313 | balloon_append(pfn_to_page(pfn)); | 313 | balloon_append(pfn_to_page(pfn)); |
314 | } | 314 | } |
315 | 315 | ||
@@ -429,15 +429,19 @@ EXPORT_SYMBOL(free_xenballooned_pages); | |||
429 | 429 | ||
430 | static int __init balloon_init(void) | 430 | static int __init balloon_init(void) |
431 | { | 431 | { |
432 | unsigned long pfn, extra_pfn_end; | 432 | unsigned long pfn, nr_pages, extra_pfn_end; |
433 | struct page *page; | 433 | struct page *page; |
434 | 434 | ||
435 | if (!xen_pv_domain()) | 435 | if (!xen_domain()) |
436 | return -ENODEV; | 436 | return -ENODEV; |
437 | 437 | ||
438 | pr_info("xen/balloon: Initialising balloon driver.\n"); | 438 | pr_info("xen/balloon: Initialising balloon driver.\n"); |
439 | 439 | ||
440 | balloon_stats.current_pages = min(xen_start_info->nr_pages, max_pfn); | 440 | if (xen_pv_domain()) |
441 | nr_pages = xen_start_info->nr_pages; | ||
442 | else | ||
443 | nr_pages = max_pfn; | ||
444 | balloon_stats.current_pages = min(nr_pages, max_pfn); | ||
441 | balloon_stats.target_pages = balloon_stats.current_pages; | 445 | balloon_stats.target_pages = balloon_stats.current_pages; |
442 | balloon_stats.balloon_low = 0; | 446 | balloon_stats.balloon_low = 0; |
443 | balloon_stats.balloon_high = 0; | 447 | balloon_stats.balloon_high = 0; |
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 74681478100..65f5068afd8 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -114,7 +114,7 @@ struct cpu_evtchn_s { | |||
114 | static __initdata struct cpu_evtchn_s init_evtchn_mask = { | 114 | static __initdata struct cpu_evtchn_s init_evtchn_mask = { |
115 | .bits[0 ... (NR_EVENT_CHANNELS/BITS_PER_LONG)-1] = ~0ul, | 115 | .bits[0 ... (NR_EVENT_CHANNELS/BITS_PER_LONG)-1] = ~0ul, |
116 | }; | 116 | }; |
117 | static struct cpu_evtchn_s *cpu_evtchn_mask_p = &init_evtchn_mask; | 117 | static struct cpu_evtchn_s __refdata *cpu_evtchn_mask_p = &init_evtchn_mask; |
118 | 118 | ||
119 | static inline unsigned long *cpu_evtchn_mask(int cpu) | 119 | static inline unsigned long *cpu_evtchn_mask(int cpu) |
120 | { | 120 | { |
@@ -277,7 +277,7 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) | |||
277 | 277 | ||
278 | BUG_ON(irq == -1); | 278 | BUG_ON(irq == -1); |
279 | #ifdef CONFIG_SMP | 279 | #ifdef CONFIG_SMP |
280 | cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu)); | 280 | cpumask_copy(irq_to_desc(irq)->irq_data.affinity, cpumask_of(cpu)); |
281 | #endif | 281 | #endif |
282 | 282 | ||
283 | clear_bit(chn, cpu_evtchn_mask(cpu_from_irq(irq))); | 283 | clear_bit(chn, cpu_evtchn_mask(cpu_from_irq(irq))); |
@@ -294,7 +294,7 @@ static void init_evtchn_cpu_bindings(void) | |||
294 | 294 | ||
295 | /* By default all event channels notify CPU#0. */ | 295 | /* By default all event channels notify CPU#0. */ |
296 | for_each_irq_desc(i, desc) { | 296 | for_each_irq_desc(i, desc) { |
297 | cpumask_copy(desc->affinity, cpumask_of(0)); | 297 | cpumask_copy(desc->irq_data.affinity, cpumask_of(0)); |
298 | } | 298 | } |
299 | #endif | 299 | #endif |
300 | 300 | ||
@@ -376,81 +376,69 @@ static void unmask_evtchn(int port) | |||
376 | put_cpu(); | 376 | put_cpu(); |
377 | } | 377 | } |
378 | 378 | ||
379 | static int get_nr_hw_irqs(void) | 379 | static int xen_allocate_irq_dynamic(void) |
380 | { | 380 | { |
381 | int ret = 1; | 381 | int first = 0; |
382 | int irq; | ||
382 | 383 | ||
383 | #ifdef CONFIG_X86_IO_APIC | 384 | #ifdef CONFIG_X86_IO_APIC |
384 | ret = get_nr_irqs_gsi(); | 385 | /* |
386 | * For an HVM guest or domain 0 which see "real" (emulated or | ||
387 | * actual repectively) GSIs we allocate dynamic IRQs | ||
388 | * e.g. those corresponding to event channels or MSIs | ||
389 | * etc. from the range above those "real" GSIs to avoid | ||
390 | * collisions. | ||
391 | */ | ||
392 | if (xen_initial_domain() || xen_hvm_domain()) | ||
393 | first = get_nr_irqs_gsi(); | ||
385 | #endif | 394 | #endif |
386 | 395 | ||
387 | return ret; | 396 | retry: |
388 | } | 397 | irq = irq_alloc_desc_from(first, -1); |
389 | 398 | ||
390 | static int find_unbound_pirq(int type) | 399 | if (irq == -ENOMEM && first > NR_IRQS_LEGACY) { |
391 | { | 400 | printk(KERN_ERR "Out of dynamic IRQ space and eating into GSI space. You should increase nr_irqs\n"); |
392 | int rc, i; | 401 | first = max(NR_IRQS_LEGACY, first - NR_IRQS_LEGACY); |
393 | struct physdev_get_free_pirq op_get_free_pirq; | 402 | goto retry; |
394 | op_get_free_pirq.type = type; | 403 | } |
395 | 404 | ||
396 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq); | 405 | if (irq < 0) |
397 | if (!rc) | 406 | panic("No available IRQ to bind to: increase nr_irqs!\n"); |
398 | return op_get_free_pirq.pirq; | ||
399 | 407 | ||
400 | for (i = 0; i < nr_irqs; i++) { | 408 | return irq; |
401 | if (pirq_to_irq[i] < 0) | ||
402 | return i; | ||
403 | } | ||
404 | return -1; | ||
405 | } | 409 | } |
406 | 410 | ||
407 | static int find_unbound_irq(void) | 411 | static int xen_allocate_irq_gsi(unsigned gsi) |
408 | { | 412 | { |
409 | struct irq_data *data; | 413 | int irq; |
410 | int irq, res; | ||
411 | int bottom = get_nr_hw_irqs(); | ||
412 | int top = nr_irqs-1; | ||
413 | |||
414 | if (bottom == nr_irqs) | ||
415 | goto no_irqs; | ||
416 | 414 | ||
417 | /* This loop starts from the top of IRQ space and goes down. | 415 | /* |
418 | * We need this b/c if we have a PCI device in a Xen PV guest | 416 | * A PV guest has no concept of a GSI (since it has no ACPI |
419 | * we do not have an IO-APIC (though the backend might have them) | 417 | * nor access to/knowledge of the physical APICs). Therefore |
420 | * mapped in. To not have a collision of physical IRQs with the Xen | 418 | * all IRQs are dynamically allocated from the entire IRQ |
421 | * event channels start at the top of the IRQ space for virtual IRQs. | 419 | * space. |
422 | */ | 420 | */ |
423 | for (irq = top; irq > bottom; irq--) { | 421 | if (xen_pv_domain() && !xen_initial_domain()) |
424 | data = irq_get_irq_data(irq); | 422 | return xen_allocate_irq_dynamic(); |
425 | /* only 15->0 have init'd desc; handle irq > 16 */ | ||
426 | if (!data) | ||
427 | break; | ||
428 | if (data->chip == &no_irq_chip) | ||
429 | break; | ||
430 | if (data->chip != &xen_dynamic_chip) | ||
431 | continue; | ||
432 | if (irq_info[irq].type == IRQT_UNBOUND) | ||
433 | return irq; | ||
434 | } | ||
435 | 423 | ||
436 | if (irq == bottom) | 424 | /* Legacy IRQ descriptors are already allocated by the arch. */ |
437 | goto no_irqs; | 425 | if (gsi < NR_IRQS_LEGACY) |
426 | return gsi; | ||
438 | 427 | ||
439 | res = irq_alloc_desc_at(irq, -1); | 428 | irq = irq_alloc_desc_at(gsi, -1); |
440 | 429 | if (irq < 0) | |
441 | if (WARN_ON(res != irq)) | 430 | panic("Unable to allocate to IRQ%d (%d)\n", gsi, irq); |
442 | return -1; | ||
443 | 431 | ||
444 | return irq; | 432 | return irq; |
445 | |||
446 | no_irqs: | ||
447 | panic("No available IRQ to bind to: increase nr_irqs!\n"); | ||
448 | } | 433 | } |
449 | 434 | ||
450 | static bool identity_mapped_irq(unsigned irq) | 435 | static void xen_free_irq(unsigned irq) |
451 | { | 436 | { |
452 | /* identity map all the hardware irqs */ | 437 | /* Legacy IRQ descriptors are managed by the arch. */ |
453 | return irq < get_nr_hw_irqs(); | 438 | if (irq < NR_IRQS_LEGACY) |
439 | return; | ||
440 | |||
441 | irq_free_desc(irq); | ||
454 | } | 442 | } |
455 | 443 | ||
456 | static void pirq_unmask_notify(int irq) | 444 | static void pirq_unmask_notify(int irq) |
@@ -486,7 +474,7 @@ static bool probing_irq(int irq) | |||
486 | return desc && desc->action == NULL; | 474 | return desc && desc->action == NULL; |
487 | } | 475 | } |
488 | 476 | ||
489 | static unsigned int startup_pirq(unsigned int irq) | 477 | static unsigned int __startup_pirq(unsigned int irq) |
490 | { | 478 | { |
491 | struct evtchn_bind_pirq bind_pirq; | 479 | struct evtchn_bind_pirq bind_pirq; |
492 | struct irq_info *info = info_for_irq(irq); | 480 | struct irq_info *info = info_for_irq(irq); |
@@ -524,9 +512,15 @@ out: | |||
524 | return 0; | 512 | return 0; |
525 | } | 513 | } |
526 | 514 | ||
527 | static void shutdown_pirq(unsigned int irq) | 515 | static unsigned int startup_pirq(struct irq_data *data) |
516 | { | ||
517 | return __startup_pirq(data->irq); | ||
518 | } | ||
519 | |||
520 | static void shutdown_pirq(struct irq_data *data) | ||
528 | { | 521 | { |
529 | struct evtchn_close close; | 522 | struct evtchn_close close; |
523 | unsigned int irq = data->irq; | ||
530 | struct irq_info *info = info_for_irq(irq); | 524 | struct irq_info *info = info_for_irq(irq); |
531 | int evtchn = evtchn_from_irq(irq); | 525 | int evtchn = evtchn_from_irq(irq); |
532 | 526 | ||
@@ -546,20 +540,20 @@ static void shutdown_pirq(unsigned int irq) | |||
546 | info->evtchn = 0; | 540 | info->evtchn = 0; |
547 | } | 541 | } |
548 | 542 | ||
549 | static void enable_pirq(unsigned int irq) | 543 | static void enable_pirq(struct irq_data *data) |
550 | { | 544 | { |
551 | startup_pirq(irq); | 545 | startup_pirq(data); |
552 | } | 546 | } |
553 | 547 | ||
554 | static void disable_pirq(unsigned int irq) | 548 | static void disable_pirq(struct irq_data *data) |
555 | { | 549 | { |
556 | } | 550 | } |
557 | 551 | ||
558 | static void ack_pirq(unsigned int irq) | 552 | static void ack_pirq(struct irq_data *data) |
559 | { | 553 | { |
560 | int evtchn = evtchn_from_irq(irq); | 554 | int evtchn = evtchn_from_irq(data->irq); |
561 | 555 | ||
562 | move_native_irq(irq); | 556 | move_native_irq(data->irq); |
563 | 557 | ||
564 | if (VALID_EVTCHN(evtchn)) { | 558 | if (VALID_EVTCHN(evtchn)) { |
565 | mask_evtchn(evtchn); | 559 | mask_evtchn(evtchn); |
@@ -567,23 +561,6 @@ static void ack_pirq(unsigned int irq) | |||
567 | } | 561 | } |
568 | } | 562 | } |
569 | 563 | ||
570 | static void end_pirq(unsigned int irq) | ||
571 | { | ||
572 | int evtchn = evtchn_from_irq(irq); | ||
573 | struct irq_desc *desc = irq_to_desc(irq); | ||
574 | |||
575 | if (WARN_ON(!desc)) | ||
576 | return; | ||
577 | |||
578 | if ((desc->status & (IRQ_DISABLED|IRQ_PENDING)) == | ||
579 | (IRQ_DISABLED|IRQ_PENDING)) { | ||
580 | shutdown_pirq(irq); | ||
581 | } else if (VALID_EVTCHN(evtchn)) { | ||
582 | unmask_evtchn(evtchn); | ||
583 | pirq_unmask_notify(irq); | ||
584 | } | ||
585 | } | ||
586 | |||
587 | static int find_irq_by_gsi(unsigned gsi) | 564 | static int find_irq_by_gsi(unsigned gsi) |
588 | { | 565 | { |
589 | int irq; | 566 | int irq; |
@@ -638,14 +615,7 @@ int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name) | |||
638 | goto out; /* XXX need refcount? */ | 615 | goto out; /* XXX need refcount? */ |
639 | } | 616 | } |
640 | 617 | ||
641 | /* If we are a PV guest, we don't have GSIs (no ACPI passed). Therefore | 618 | irq = xen_allocate_irq_gsi(gsi); |
642 | * we are using the !xen_initial_domain() to drop in the function.*/ | ||
643 | if (identity_mapped_irq(gsi) || (!xen_initial_domain() && | ||
644 | xen_pv_domain())) { | ||
645 | irq = gsi; | ||
646 | irq_alloc_desc_at(irq, -1); | ||
647 | } else | ||
648 | irq = find_unbound_irq(); | ||
649 | 619 | ||
650 | set_irq_chip_and_handler_name(irq, &xen_pirq_chip, | 620 | set_irq_chip_and_handler_name(irq, &xen_pirq_chip, |
651 | handle_level_irq, name); | 621 | handle_level_irq, name); |
@@ -658,7 +628,7 @@ int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name) | |||
658 | * this in the priv domain. */ | 628 | * this in the priv domain. */ |
659 | if (xen_initial_domain() && | 629 | if (xen_initial_domain() && |
660 | HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) { | 630 | HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) { |
661 | irq_free_desc(irq); | 631 | xen_free_irq(irq); |
662 | irq = -ENOSPC; | 632 | irq = -ENOSPC; |
663 | goto out; | 633 | goto out; |
664 | } | 634 | } |
@@ -674,87 +644,46 @@ out: | |||
674 | } | 644 | } |
675 | 645 | ||
676 | #ifdef CONFIG_PCI_MSI | 646 | #ifdef CONFIG_PCI_MSI |
677 | #include <linux/msi.h> | 647 | int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc) |
678 | #include "../pci/msi.h" | ||
679 | |||
680 | void xen_allocate_pirq_msi(char *name, int *irq, int *pirq, int alloc) | ||
681 | { | 648 | { |
682 | spin_lock(&irq_mapping_update_lock); | 649 | int rc; |
683 | 650 | struct physdev_get_free_pirq op_get_free_pirq; | |
684 | if (alloc & XEN_ALLOC_IRQ) { | ||
685 | *irq = find_unbound_irq(); | ||
686 | if (*irq == -1) | ||
687 | goto out; | ||
688 | } | ||
689 | |||
690 | if (alloc & XEN_ALLOC_PIRQ) { | ||
691 | *pirq = find_unbound_pirq(MAP_PIRQ_TYPE_MSI); | ||
692 | if (*pirq == -1) | ||
693 | goto out; | ||
694 | } | ||
695 | 651 | ||
696 | set_irq_chip_and_handler_name(*irq, &xen_pirq_chip, | 652 | op_get_free_pirq.type = MAP_PIRQ_TYPE_MSI; |
697 | handle_level_irq, name); | 653 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq); |
698 | 654 | ||
699 | irq_info[*irq] = mk_pirq_info(0, *pirq, 0, 0); | 655 | WARN_ONCE(rc == -ENOSYS, |
700 | pirq_to_irq[*pirq] = *irq; | 656 | "hypervisor does not support the PHYSDEVOP_get_free_pirq interface\n"); |
701 | 657 | ||
702 | out: | 658 | return rc ? -1 : op_get_free_pirq.pirq; |
703 | spin_unlock(&irq_mapping_update_lock); | ||
704 | } | 659 | } |
705 | 660 | ||
706 | int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type) | 661 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, |
662 | int pirq, int vector, const char *name) | ||
707 | { | 663 | { |
708 | int irq = -1; | 664 | int irq, ret; |
709 | struct physdev_map_pirq map_irq; | ||
710 | int rc; | ||
711 | int pos; | ||
712 | u32 table_offset, bir; | ||
713 | |||
714 | memset(&map_irq, 0, sizeof(map_irq)); | ||
715 | map_irq.domid = DOMID_SELF; | ||
716 | map_irq.type = MAP_PIRQ_TYPE_MSI; | ||
717 | map_irq.index = -1; | ||
718 | map_irq.pirq = -1; | ||
719 | map_irq.bus = dev->bus->number; | ||
720 | map_irq.devfn = dev->devfn; | ||
721 | |||
722 | if (type == PCI_CAP_ID_MSIX) { | ||
723 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | ||
724 | |||
725 | pci_read_config_dword(dev, msix_table_offset_reg(pos), | ||
726 | &table_offset); | ||
727 | bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); | ||
728 | |||
729 | map_irq.table_base = pci_resource_start(dev, bir); | ||
730 | map_irq.entry_nr = msidesc->msi_attrib.entry_nr; | ||
731 | } | ||
732 | 665 | ||
733 | spin_lock(&irq_mapping_update_lock); | 666 | spin_lock(&irq_mapping_update_lock); |
734 | 667 | ||
735 | irq = find_unbound_irq(); | 668 | irq = xen_allocate_irq_dynamic(); |
736 | |||
737 | if (irq == -1) | 669 | if (irq == -1) |
738 | goto out; | 670 | goto out; |
739 | 671 | ||
740 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); | ||
741 | if (rc) { | ||
742 | printk(KERN_WARNING "xen map irq failed %d\n", rc); | ||
743 | |||
744 | irq_free_desc(irq); | ||
745 | |||
746 | irq = -1; | ||
747 | goto out; | ||
748 | } | ||
749 | irq_info[irq] = mk_pirq_info(0, map_irq.pirq, 0, map_irq.index); | ||
750 | |||
751 | set_irq_chip_and_handler_name(irq, &xen_pirq_chip, | 672 | set_irq_chip_and_handler_name(irq, &xen_pirq_chip, |
752 | handle_level_irq, | 673 | handle_level_irq, name); |
753 | (type == PCI_CAP_ID_MSIX) ? "msi-x":"msi"); | ||
754 | 674 | ||
675 | irq_info[irq] = mk_pirq_info(0, pirq, 0, vector); | ||
676 | pirq_to_irq[pirq] = irq; | ||
677 | ret = irq_set_msi_desc(irq, msidesc); | ||
678 | if (ret < 0) | ||
679 | goto error_irq; | ||
755 | out: | 680 | out: |
756 | spin_unlock(&irq_mapping_update_lock); | 681 | spin_unlock(&irq_mapping_update_lock); |
757 | return irq; | 682 | return irq; |
683 | error_irq: | ||
684 | spin_unlock(&irq_mapping_update_lock); | ||
685 | xen_free_irq(irq); | ||
686 | return -1; | ||
758 | } | 687 | } |
759 | #endif | 688 | #endif |
760 | 689 | ||
@@ -779,11 +708,12 @@ int xen_destroy_irq(int irq) | |||
779 | printk(KERN_WARNING "unmap irq failed %d\n", rc); | 708 | printk(KERN_WARNING "unmap irq failed %d\n", rc); |
780 | goto out; | 709 | goto out; |
781 | } | 710 | } |
782 | pirq_to_irq[info->u.pirq.pirq] = -1; | ||
783 | } | 711 | } |
712 | pirq_to_irq[info->u.pirq.pirq] = -1; | ||
713 | |||
784 | irq_info[irq] = mk_unbound_info(); | 714 | irq_info[irq] = mk_unbound_info(); |
785 | 715 | ||
786 | irq_free_desc(irq); | 716 | xen_free_irq(irq); |
787 | 717 | ||
788 | out: | 718 | out: |
789 | spin_unlock(&irq_mapping_update_lock); | 719 | spin_unlock(&irq_mapping_update_lock); |
@@ -814,7 +744,7 @@ int bind_evtchn_to_irq(unsigned int evtchn) | |||
814 | irq = evtchn_to_irq[evtchn]; | 744 | irq = evtchn_to_irq[evtchn]; |
815 | 745 | ||
816 | if (irq == -1) { | 746 | if (irq == -1) { |
817 | irq = find_unbound_irq(); | 747 | irq = xen_allocate_irq_dynamic(); |
818 | 748 | ||
819 | set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, | 749 | set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, |
820 | handle_fasteoi_irq, "event"); | 750 | handle_fasteoi_irq, "event"); |
@@ -839,7 +769,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) | |||
839 | irq = per_cpu(ipi_to_irq, cpu)[ipi]; | 769 | irq = per_cpu(ipi_to_irq, cpu)[ipi]; |
840 | 770 | ||
841 | if (irq == -1) { | 771 | if (irq == -1) { |
842 | irq = find_unbound_irq(); | 772 | irq = xen_allocate_irq_dynamic(); |
843 | if (irq < 0) | 773 | if (irq < 0) |
844 | goto out; | 774 | goto out; |
845 | 775 | ||
@@ -864,6 +794,21 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) | |||
864 | return irq; | 794 | return irq; |
865 | } | 795 | } |
866 | 796 | ||
797 | static int bind_interdomain_evtchn_to_irq(unsigned int remote_domain, | ||
798 | unsigned int remote_port) | ||
799 | { | ||
800 | struct evtchn_bind_interdomain bind_interdomain; | ||
801 | int err; | ||
802 | |||
803 | bind_interdomain.remote_dom = remote_domain; | ||
804 | bind_interdomain.remote_port = remote_port; | ||
805 | |||
806 | err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, | ||
807 | &bind_interdomain); | ||
808 | |||
809 | return err ? : bind_evtchn_to_irq(bind_interdomain.local_port); | ||
810 | } | ||
811 | |||
867 | 812 | ||
868 | int bind_virq_to_irq(unsigned int virq, unsigned int cpu) | 813 | int bind_virq_to_irq(unsigned int virq, unsigned int cpu) |
869 | { | 814 | { |
@@ -875,7 +820,7 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu) | |||
875 | irq = per_cpu(virq_to_irq, cpu)[virq]; | 820 | irq = per_cpu(virq_to_irq, cpu)[virq]; |
876 | 821 | ||
877 | if (irq == -1) { | 822 | if (irq == -1) { |
878 | irq = find_unbound_irq(); | 823 | irq = xen_allocate_irq_dynamic(); |
879 | 824 | ||
880 | set_irq_chip_and_handler_name(irq, &xen_percpu_chip, | 825 | set_irq_chip_and_handler_name(irq, &xen_percpu_chip, |
881 | handle_percpu_irq, "virq"); | 826 | handle_percpu_irq, "virq"); |
@@ -934,7 +879,7 @@ static void unbind_from_irq(unsigned int irq) | |||
934 | if (irq_info[irq].type != IRQT_UNBOUND) { | 879 | if (irq_info[irq].type != IRQT_UNBOUND) { |
935 | irq_info[irq] = mk_unbound_info(); | 880 | irq_info[irq] = mk_unbound_info(); |
936 | 881 | ||
937 | irq_free_desc(irq); | 882 | xen_free_irq(irq); |
938 | } | 883 | } |
939 | 884 | ||
940 | spin_unlock(&irq_mapping_update_lock); | 885 | spin_unlock(&irq_mapping_update_lock); |
@@ -959,6 +904,29 @@ int bind_evtchn_to_irqhandler(unsigned int evtchn, | |||
959 | } | 904 | } |
960 | EXPORT_SYMBOL_GPL(bind_evtchn_to_irqhandler); | 905 | EXPORT_SYMBOL_GPL(bind_evtchn_to_irqhandler); |
961 | 906 | ||
907 | int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain, | ||
908 | unsigned int remote_port, | ||
909 | irq_handler_t handler, | ||
910 | unsigned long irqflags, | ||
911 | const char *devname, | ||
912 | void *dev_id) | ||
913 | { | ||
914 | int irq, retval; | ||
915 | |||
916 | irq = bind_interdomain_evtchn_to_irq(remote_domain, remote_port); | ||
917 | if (irq < 0) | ||
918 | return irq; | ||
919 | |||
920 | retval = request_irq(irq, handler, irqflags, devname, dev_id); | ||
921 | if (retval != 0) { | ||
922 | unbind_from_irq(irq); | ||
923 | return retval; | ||
924 | } | ||
925 | |||
926 | return irq; | ||
927 | } | ||
928 | EXPORT_SYMBOL_GPL(bind_interdomain_evtchn_to_irqhandler); | ||
929 | |||
962 | int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, | 930 | int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, |
963 | irq_handler_t handler, | 931 | irq_handler_t handler, |
964 | unsigned long irqflags, const char *devname, void *dev_id) | 932 | unsigned long irqflags, const char *devname, void *dev_id) |
@@ -990,7 +958,7 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi, | |||
990 | if (irq < 0) | 958 | if (irq < 0) |
991 | return irq; | 959 | return irq; |
992 | 960 | ||
993 | irqflags |= IRQF_NO_SUSPEND; | 961 | irqflags |= IRQF_NO_SUSPEND | IRQF_FORCE_RESUME; |
994 | retval = request_irq(irq, handler, irqflags, devname, dev_id); | 962 | retval = request_irq(irq, handler, irqflags, devname, dev_id); |
995 | if (retval != 0) { | 963 | if (retval != 0) { |
996 | unbind_from_irq(irq); | 964 | unbind_from_irq(irq); |
@@ -1234,11 +1202,12 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu) | |||
1234 | return 0; | 1202 | return 0; |
1235 | } | 1203 | } |
1236 | 1204 | ||
1237 | static int set_affinity_irq(unsigned irq, const struct cpumask *dest) | 1205 | static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest, |
1206 | bool force) | ||
1238 | { | 1207 | { |
1239 | unsigned tcpu = cpumask_first(dest); | 1208 | unsigned tcpu = cpumask_first(dest); |
1240 | 1209 | ||
1241 | return rebind_irq_to_cpu(irq, tcpu); | 1210 | return rebind_irq_to_cpu(data->irq, tcpu); |
1242 | } | 1211 | } |
1243 | 1212 | ||
1244 | int resend_irq_on_evtchn(unsigned int irq) | 1213 | int resend_irq_on_evtchn(unsigned int irq) |
@@ -1257,35 +1226,35 @@ int resend_irq_on_evtchn(unsigned int irq) | |||
1257 | return 1; | 1226 | return 1; |
1258 | } | 1227 | } |
1259 | 1228 | ||
1260 | static void enable_dynirq(unsigned int irq) | 1229 | static void enable_dynirq(struct irq_data *data) |
1261 | { | 1230 | { |
1262 | int evtchn = evtchn_from_irq(irq); | 1231 | int evtchn = evtchn_from_irq(data->irq); |
1263 | 1232 | ||
1264 | if (VALID_EVTCHN(evtchn)) | 1233 | if (VALID_EVTCHN(evtchn)) |
1265 | unmask_evtchn(evtchn); | 1234 | unmask_evtchn(evtchn); |
1266 | } | 1235 | } |
1267 | 1236 | ||
1268 | static void disable_dynirq(unsigned int irq) | 1237 | static void disable_dynirq(struct irq_data *data) |
1269 | { | 1238 | { |
1270 | int evtchn = evtchn_from_irq(irq); | 1239 | int evtchn = evtchn_from_irq(data->irq); |
1271 | 1240 | ||
1272 | if (VALID_EVTCHN(evtchn)) | 1241 | if (VALID_EVTCHN(evtchn)) |
1273 | mask_evtchn(evtchn); | 1242 | mask_evtchn(evtchn); |
1274 | } | 1243 | } |
1275 | 1244 | ||
1276 | static void ack_dynirq(unsigned int irq) | 1245 | static void ack_dynirq(struct irq_data *data) |
1277 | { | 1246 | { |
1278 | int evtchn = evtchn_from_irq(irq); | 1247 | int evtchn = evtchn_from_irq(data->irq); |
1279 | 1248 | ||
1280 | move_masked_irq(irq); | 1249 | move_masked_irq(data->irq); |
1281 | 1250 | ||
1282 | if (VALID_EVTCHN(evtchn)) | 1251 | if (VALID_EVTCHN(evtchn)) |
1283 | unmask_evtchn(evtchn); | 1252 | unmask_evtchn(evtchn); |
1284 | } | 1253 | } |
1285 | 1254 | ||
1286 | static int retrigger_dynirq(unsigned int irq) | 1255 | static int retrigger_dynirq(struct irq_data *data) |
1287 | { | 1256 | { |
1288 | int evtchn = evtchn_from_irq(irq); | 1257 | int evtchn = evtchn_from_irq(data->irq); |
1289 | struct shared_info *sh = HYPERVISOR_shared_info; | 1258 | struct shared_info *sh = HYPERVISOR_shared_info; |
1290 | int ret = 0; | 1259 | int ret = 0; |
1291 | 1260 | ||
@@ -1334,7 +1303,7 @@ static void restore_cpu_pirqs(void) | |||
1334 | 1303 | ||
1335 | printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq); | 1304 | printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq); |
1336 | 1305 | ||
1337 | startup_pirq(irq); | 1306 | __startup_pirq(irq); |
1338 | } | 1307 | } |
1339 | } | 1308 | } |
1340 | 1309 | ||
@@ -1445,7 +1414,6 @@ void xen_poll_irq(int irq) | |||
1445 | void xen_irq_resume(void) | 1414 | void xen_irq_resume(void) |
1446 | { | 1415 | { |
1447 | unsigned int cpu, irq, evtchn; | 1416 | unsigned int cpu, irq, evtchn; |
1448 | struct irq_desc *desc; | ||
1449 | 1417 | ||
1450 | init_evtchn_cpu_bindings(); | 1418 | init_evtchn_cpu_bindings(); |
1451 | 1419 | ||
@@ -1465,66 +1433,48 @@ void xen_irq_resume(void) | |||
1465 | restore_cpu_ipis(cpu); | 1433 | restore_cpu_ipis(cpu); |
1466 | } | 1434 | } |
1467 | 1435 | ||
1468 | /* | ||
1469 | * Unmask any IRQF_NO_SUSPEND IRQs which are enabled. These | ||
1470 | * are not handled by the IRQ core. | ||
1471 | */ | ||
1472 | for_each_irq_desc(irq, desc) { | ||
1473 | if (!desc->action || !(desc->action->flags & IRQF_NO_SUSPEND)) | ||
1474 | continue; | ||
1475 | if (desc->status & IRQ_DISABLED) | ||
1476 | continue; | ||
1477 | |||
1478 | evtchn = evtchn_from_irq(irq); | ||
1479 | if (evtchn == -1) | ||
1480 | continue; | ||
1481 | |||
1482 | unmask_evtchn(evtchn); | ||
1483 | } | ||
1484 | |||
1485 | restore_cpu_pirqs(); | 1436 | restore_cpu_pirqs(); |
1486 | } | 1437 | } |
1487 | 1438 | ||
1488 | static struct irq_chip xen_dynamic_chip __read_mostly = { | 1439 | static struct irq_chip xen_dynamic_chip __read_mostly = { |
1489 | .name = "xen-dyn", | 1440 | .name = "xen-dyn", |
1490 | 1441 | ||
1491 | .disable = disable_dynirq, | 1442 | .irq_disable = disable_dynirq, |
1492 | .mask = disable_dynirq, | 1443 | .irq_mask = disable_dynirq, |
1493 | .unmask = enable_dynirq, | 1444 | .irq_unmask = enable_dynirq, |
1494 | 1445 | ||
1495 | .eoi = ack_dynirq, | 1446 | .irq_eoi = ack_dynirq, |
1496 | .set_affinity = set_affinity_irq, | 1447 | .irq_set_affinity = set_affinity_irq, |
1497 | .retrigger = retrigger_dynirq, | 1448 | .irq_retrigger = retrigger_dynirq, |
1498 | }; | 1449 | }; |
1499 | 1450 | ||
1500 | static struct irq_chip xen_pirq_chip __read_mostly = { | 1451 | static struct irq_chip xen_pirq_chip __read_mostly = { |
1501 | .name = "xen-pirq", | 1452 | .name = "xen-pirq", |
1502 | 1453 | ||
1503 | .startup = startup_pirq, | 1454 | .irq_startup = startup_pirq, |
1504 | .shutdown = shutdown_pirq, | 1455 | .irq_shutdown = shutdown_pirq, |
1505 | 1456 | ||
1506 | .enable = enable_pirq, | 1457 | .irq_enable = enable_pirq, |
1507 | .unmask = enable_pirq, | 1458 | .irq_unmask = enable_pirq, |
1508 | 1459 | ||
1509 | .disable = disable_pirq, | 1460 | .irq_disable = disable_pirq, |
1510 | .mask = disable_pirq, | 1461 | .irq_mask = disable_pirq, |
1511 | 1462 | ||
1512 | .ack = ack_pirq, | 1463 | .irq_ack = ack_pirq, |
1513 | .end = end_pirq, | ||
1514 | 1464 | ||
1515 | .set_affinity = set_affinity_irq, | 1465 | .irq_set_affinity = set_affinity_irq, |
1516 | 1466 | ||
1517 | .retrigger = retrigger_dynirq, | 1467 | .irq_retrigger = retrigger_dynirq, |
1518 | }; | 1468 | }; |
1519 | 1469 | ||
1520 | static struct irq_chip xen_percpu_chip __read_mostly = { | 1470 | static struct irq_chip xen_percpu_chip __read_mostly = { |
1521 | .name = "xen-percpu", | 1471 | .name = "xen-percpu", |
1522 | 1472 | ||
1523 | .disable = disable_dynirq, | 1473 | .irq_disable = disable_dynirq, |
1524 | .mask = disable_dynirq, | 1474 | .irq_mask = disable_dynirq, |
1525 | .unmask = enable_dynirq, | 1475 | .irq_unmask = enable_dynirq, |
1526 | 1476 | ||
1527 | .ack = ack_dynirq, | 1477 | .irq_ack = ack_dynirq, |
1528 | }; | 1478 | }; |
1529 | 1479 | ||
1530 | int xen_set_callback_via(uint64_t via) | 1480 | int xen_set_callback_via(uint64_t via) |
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index db8c4c4ac88..ebb292859b5 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
@@ -34,32 +34,38 @@ enum shutdown_state { | |||
34 | /* Ignore multiple shutdown requests. */ | 34 | /* Ignore multiple shutdown requests. */ |
35 | static enum shutdown_state shutting_down = SHUTDOWN_INVALID; | 35 | static enum shutdown_state shutting_down = SHUTDOWN_INVALID; |
36 | 36 | ||
37 | #ifdef CONFIG_PM_SLEEP | 37 | struct suspend_info { |
38 | static int xen_hvm_suspend(void *data) | 38 | int cancelled; |
39 | { | 39 | unsigned long arg; /* extra hypercall argument */ |
40 | struct sched_shutdown r = { .reason = SHUTDOWN_suspend }; | 40 | void (*pre)(void); |
41 | int *cancelled = data; | 41 | void (*post)(int cancelled); |
42 | 42 | }; | |
43 | BUG_ON(!irqs_disabled()); | ||
44 | |||
45 | *cancelled = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r); | ||
46 | 43 | ||
47 | xen_hvm_post_suspend(*cancelled); | 44 | static void xen_hvm_post_suspend(int cancelled) |
45 | { | ||
46 | xen_arch_hvm_post_suspend(cancelled); | ||
48 | gnttab_resume(); | 47 | gnttab_resume(); |
48 | } | ||
49 | 49 | ||
50 | if (!*cancelled) { | 50 | static void xen_pre_suspend(void) |
51 | xen_irq_resume(); | 51 | { |
52 | xen_console_resume(); | 52 | xen_mm_pin_all(); |
53 | xen_timer_resume(); | 53 | gnttab_suspend(); |
54 | } | 54 | xen_arch_pre_suspend(); |
55 | } | ||
55 | 56 | ||
56 | return 0; | 57 | static void xen_post_suspend(int cancelled) |
58 | { | ||
59 | xen_arch_post_suspend(cancelled); | ||
60 | gnttab_resume(); | ||
61 | xen_mm_unpin_all(); | ||
57 | } | 62 | } |
58 | 63 | ||
64 | #ifdef CONFIG_PM_SLEEP | ||
59 | static int xen_suspend(void *data) | 65 | static int xen_suspend(void *data) |
60 | { | 66 | { |
67 | struct suspend_info *si = data; | ||
61 | int err; | 68 | int err; |
62 | int *cancelled = data; | ||
63 | 69 | ||
64 | BUG_ON(!irqs_disabled()); | 70 | BUG_ON(!irqs_disabled()); |
65 | 71 | ||
@@ -70,22 +76,20 @@ static int xen_suspend(void *data) | |||
70 | return err; | 76 | return err; |
71 | } | 77 | } |
72 | 78 | ||
73 | xen_mm_pin_all(); | 79 | if (si->pre) |
74 | gnttab_suspend(); | 80 | si->pre(); |
75 | xen_pre_suspend(); | ||
76 | 81 | ||
77 | /* | 82 | /* |
78 | * This hypercall returns 1 if suspend was cancelled | 83 | * This hypercall returns 1 if suspend was cancelled |
79 | * or the domain was merely checkpointed, and 0 if it | 84 | * or the domain was merely checkpointed, and 0 if it |
80 | * is resuming in a new domain. | 85 | * is resuming in a new domain. |
81 | */ | 86 | */ |
82 | *cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); | 87 | si->cancelled = HYPERVISOR_suspend(si->arg); |
83 | 88 | ||
84 | xen_post_suspend(*cancelled); | 89 | if (si->post) |
85 | gnttab_resume(); | 90 | si->post(si->cancelled); |
86 | xen_mm_unpin_all(); | ||
87 | 91 | ||
88 | if (!*cancelled) { | 92 | if (!si->cancelled) { |
89 | xen_irq_resume(); | 93 | xen_irq_resume(); |
90 | xen_console_resume(); | 94 | xen_console_resume(); |
91 | xen_timer_resume(); | 95 | xen_timer_resume(); |
@@ -99,7 +103,7 @@ static int xen_suspend(void *data) | |||
99 | static void do_suspend(void) | 103 | static void do_suspend(void) |
100 | { | 104 | { |
101 | int err; | 105 | int err; |
102 | int cancelled = 1; | 106 | struct suspend_info si; |
103 | 107 | ||
104 | shutting_down = SHUTDOWN_SUSPEND; | 108 | shutting_down = SHUTDOWN_SUSPEND; |
105 | 109 | ||
@@ -129,20 +133,29 @@ static void do_suspend(void) | |||
129 | goto out_resume; | 133 | goto out_resume; |
130 | } | 134 | } |
131 | 135 | ||
132 | if (xen_hvm_domain()) | 136 | si.cancelled = 1; |
133 | err = stop_machine(xen_hvm_suspend, &cancelled, cpumask_of(0)); | 137 | |
134 | else | 138 | if (xen_hvm_domain()) { |
135 | err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); | 139 | si.arg = 0UL; |
140 | si.pre = NULL; | ||
141 | si.post = &xen_hvm_post_suspend; | ||
142 | } else { | ||
143 | si.arg = virt_to_mfn(xen_start_info); | ||
144 | si.pre = &xen_pre_suspend; | ||
145 | si.post = &xen_post_suspend; | ||
146 | } | ||
147 | |||
148 | err = stop_machine(xen_suspend, &si, cpumask_of(0)); | ||
136 | 149 | ||
137 | dpm_resume_noirq(PMSG_RESUME); | 150 | dpm_resume_noirq(PMSG_RESUME); |
138 | 151 | ||
139 | if (err) { | 152 | if (err) { |
140 | printk(KERN_ERR "failed to start xen_suspend: %d\n", err); | 153 | printk(KERN_ERR "failed to start xen_suspend: %d\n", err); |
141 | cancelled = 1; | 154 | si.cancelled = 1; |
142 | } | 155 | } |
143 | 156 | ||
144 | out_resume: | 157 | out_resume: |
145 | if (!cancelled) { | 158 | if (!si.cancelled) { |
146 | xen_arch_resume(); | 159 | xen_arch_resume(); |
147 | xs_resume(); | 160 | xs_resume(); |
148 | } else | 161 | } else |
@@ -162,12 +175,39 @@ out: | |||
162 | } | 175 | } |
163 | #endif /* CONFIG_PM_SLEEP */ | 176 | #endif /* CONFIG_PM_SLEEP */ |
164 | 177 | ||
178 | struct shutdown_handler { | ||
179 | const char *command; | ||
180 | void (*cb)(void); | ||
181 | }; | ||
182 | |||
183 | static void do_poweroff(void) | ||
184 | { | ||
185 | shutting_down = SHUTDOWN_POWEROFF; | ||
186 | orderly_poweroff(false); | ||
187 | } | ||
188 | |||
189 | static void do_reboot(void) | ||
190 | { | ||
191 | shutting_down = SHUTDOWN_POWEROFF; /* ? */ | ||
192 | ctrl_alt_del(); | ||
193 | } | ||
194 | |||
165 | static void shutdown_handler(struct xenbus_watch *watch, | 195 | static void shutdown_handler(struct xenbus_watch *watch, |
166 | const char **vec, unsigned int len) | 196 | const char **vec, unsigned int len) |
167 | { | 197 | { |
168 | char *str; | 198 | char *str; |
169 | struct xenbus_transaction xbt; | 199 | struct xenbus_transaction xbt; |
170 | int err; | 200 | int err; |
201 | static struct shutdown_handler handlers[] = { | ||
202 | { "poweroff", do_poweroff }, | ||
203 | { "halt", do_poweroff }, | ||
204 | { "reboot", do_reboot }, | ||
205 | #ifdef CONFIG_PM_SLEEP | ||
206 | { "suspend", do_suspend }, | ||
207 | #endif | ||
208 | {NULL, NULL}, | ||
209 | }; | ||
210 | static struct shutdown_handler *handler; | ||
171 | 211 | ||
172 | if (shutting_down != SHUTDOWN_INVALID) | 212 | if (shutting_down != SHUTDOWN_INVALID) |
173 | return; | 213 | return; |
@@ -184,7 +224,14 @@ static void shutdown_handler(struct xenbus_watch *watch, | |||
184 | return; | 224 | return; |
185 | } | 225 | } |
186 | 226 | ||
187 | xenbus_write(xbt, "control", "shutdown", ""); | 227 | for (handler = &handlers[0]; handler->command; handler++) { |
228 | if (strcmp(str, handler->command) == 0) | ||
229 | break; | ||
230 | } | ||
231 | |||
232 | /* Only acknowledge commands which we are prepared to handle. */ | ||
233 | if (handler->cb) | ||
234 | xenbus_write(xbt, "control", "shutdown", ""); | ||
188 | 235 | ||
189 | err = xenbus_transaction_end(xbt, 0); | 236 | err = xenbus_transaction_end(xbt, 0); |
190 | if (err == -EAGAIN) { | 237 | if (err == -EAGAIN) { |
@@ -192,17 +239,8 @@ static void shutdown_handler(struct xenbus_watch *watch, | |||
192 | goto again; | 239 | goto again; |
193 | } | 240 | } |
194 | 241 | ||
195 | if (strcmp(str, "poweroff") == 0 || | 242 | if (handler->cb) { |
196 | strcmp(str, "halt") == 0) { | 243 | handler->cb(); |
197 | shutting_down = SHUTDOWN_POWEROFF; | ||
198 | orderly_poweroff(false); | ||
199 | } else if (strcmp(str, "reboot") == 0) { | ||
200 | shutting_down = SHUTDOWN_POWEROFF; /* ? */ | ||
201 | ctrl_alt_del(); | ||
202 | #ifdef CONFIG_PM_SLEEP | ||
203 | } else if (strcmp(str, "suspend") == 0) { | ||
204 | do_suspend(); | ||
205 | #endif | ||
206 | } else { | 244 | } else { |
207 | printk(KERN_INFO "Ignoring shutdown request: %s\n", str); | 245 | printk(KERN_INFO "Ignoring shutdown request: %s\n", str); |
208 | shutting_down = SHUTDOWN_INVALID; | 246 | shutting_down = SHUTDOWN_INVALID; |
@@ -281,27 +319,18 @@ static int shutdown_event(struct notifier_block *notifier, | |||
281 | return NOTIFY_DONE; | 319 | return NOTIFY_DONE; |
282 | } | 320 | } |
283 | 321 | ||
284 | static int __init __setup_shutdown_event(void) | ||
285 | { | ||
286 | /* Delay initialization in the PV on HVM case */ | ||
287 | if (xen_hvm_domain()) | ||
288 | return 0; | ||
289 | |||
290 | if (!xen_pv_domain()) | ||
291 | return -ENODEV; | ||
292 | |||
293 | return xen_setup_shutdown_event(); | ||
294 | } | ||
295 | |||
296 | int xen_setup_shutdown_event(void) | 322 | int xen_setup_shutdown_event(void) |
297 | { | 323 | { |
298 | static struct notifier_block xenstore_notifier = { | 324 | static struct notifier_block xenstore_notifier = { |
299 | .notifier_call = shutdown_event | 325 | .notifier_call = shutdown_event |
300 | }; | 326 | }; |
327 | |||
328 | if (!xen_domain()) | ||
329 | return -ENODEV; | ||
301 | register_xenstore_notifier(&xenstore_notifier); | 330 | register_xenstore_notifier(&xenstore_notifier); |
302 | 331 | ||
303 | return 0; | 332 | return 0; |
304 | } | 333 | } |
305 | EXPORT_SYMBOL_GPL(xen_setup_shutdown_event); | 334 | EXPORT_SYMBOL_GPL(xen_setup_shutdown_event); |
306 | 335 | ||
307 | subsys_initcall(__setup_shutdown_event); | 336 | subsys_initcall(xen_setup_shutdown_event); |
diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c index afbe041f42c..319dd0a94d5 100644 --- a/drivers/xen/platform-pci.c +++ b/drivers/xen/platform-pci.c | |||
@@ -156,9 +156,6 @@ static int __devinit platform_pci_init(struct pci_dev *pdev, | |||
156 | if (ret) | 156 | if (ret) |
157 | goto out; | 157 | goto out; |
158 | xenbus_probe(NULL); | 158 | xenbus_probe(NULL); |
159 | ret = xen_setup_shutdown_event(); | ||
160 | if (ret) | ||
161 | goto out; | ||
162 | return 0; | 159 | return 0; |
163 | 160 | ||
164 | out: | 161 | out: |