diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-15 13:47:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-15 13:47:56 -0400 |
commit | 010b8f4e264b0b6f596186574956dde2fa02df1c (patch) | |
tree | 277d599cc0147be3a3d5bfdf676510c0add154c0 /drivers/xen | |
parent | 397fae081869784d07cd4edde0ddf436ca2011e0 (diff) | |
parent | 71eef7d1e3d9df760897fdd2cad6949a8bcf1620 (diff) |
Merge branch 'stable/irq.cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen
* 'stable/irq.cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
xen: events: remove dom0 specific xen_create_msi_irq
xen: events: use xen_bind_pirq_msi_to_irq from xen_create_msi_irq
xen: events: push set_irq_msi down into xen_create_msi_irq
xen: events: update pirq_to_irq in xen_create_msi_irq
xen: events: refactor xen_create_msi_irq slightly
xen: events: separate MSI PIRQ allocation from PIRQ binding to IRQ
xen: events: assume PHYSDEVOP_get_free_pirq exists
xen: pci: collapse apic_register_gsi_xen_hvm and xen_hvm_register_pirq
xen: events: return irq from xen_allocate_pirq_msi
xen: events: drop XEN_ALLOC_IRQ flag to xen_allocate_pirq_msi
xen: events: do not leak IRQ from xen_allocate_pirq_msi when no pirq available.
xen: pci: only define xen_initdom_setup_msi_irqs if CONFIG_XEN_DOM0
Diffstat (limited to 'drivers/xen')
-rw-r--r-- | drivers/xen/events.c | 96 |
1 files changed, 19 insertions, 77 deletions
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 89987a7bf26f..6befe6227159 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -644,104 +644,46 @@ out: | |||
644 | } | 644 | } |
645 | 645 | ||
646 | #ifdef CONFIG_PCI_MSI | 646 | #ifdef CONFIG_PCI_MSI |
647 | #include <linux/msi.h> | 647 | int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc) |
648 | #include "../pci/msi.h" | ||
649 | |||
650 | static int find_unbound_pirq(int type) | ||
651 | { | 648 | { |
652 | int rc, i; | 649 | int rc; |
653 | struct physdev_get_free_pirq op_get_free_pirq; | 650 | struct physdev_get_free_pirq op_get_free_pirq; |
654 | op_get_free_pirq.type = type; | ||
655 | 651 | ||
652 | op_get_free_pirq.type = MAP_PIRQ_TYPE_MSI; | ||
656 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq); | 653 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq); |
657 | if (!rc) | ||
658 | return op_get_free_pirq.pirq; | ||
659 | |||
660 | for (i = 0; i < nr_irqs; i++) { | ||
661 | if (pirq_to_irq[i] < 0) | ||
662 | return i; | ||
663 | } | ||
664 | return -1; | ||
665 | } | ||
666 | |||
667 | void xen_allocate_pirq_msi(char *name, int *irq, int *pirq, int alloc) | ||
668 | { | ||
669 | spin_lock(&irq_mapping_update_lock); | ||
670 | |||
671 | if (alloc & XEN_ALLOC_IRQ) { | ||
672 | *irq = xen_allocate_irq_dynamic(); | ||
673 | if (*irq == -1) | ||
674 | goto out; | ||
675 | } | ||
676 | |||
677 | if (alloc & XEN_ALLOC_PIRQ) { | ||
678 | *pirq = find_unbound_pirq(MAP_PIRQ_TYPE_MSI); | ||
679 | if (*pirq == -1) | ||
680 | goto out; | ||
681 | } | ||
682 | |||
683 | set_irq_chip_and_handler_name(*irq, &xen_pirq_chip, | ||
684 | handle_level_irq, name); | ||
685 | 654 | ||
686 | irq_info[*irq] = mk_pirq_info(0, *pirq, 0, 0); | 655 | WARN_ONCE(rc == -ENOSYS, |
687 | pirq_to_irq[*pirq] = *irq; | 656 | "hypervisor does not support the PHYSDEVOP_get_free_pirq interface\n"); |
688 | 657 | ||
689 | out: | 658 | return rc ? -1 : op_get_free_pirq.pirq; |
690 | spin_unlock(&irq_mapping_update_lock); | ||
691 | } | 659 | } |
692 | 660 | ||
693 | 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) | ||
694 | { | 663 | { |
695 | int irq = -1; | 664 | int irq, ret; |
696 | struct physdev_map_pirq map_irq; | ||
697 | int rc; | ||
698 | int pos; | ||
699 | u32 table_offset, bir; | ||
700 | |||
701 | memset(&map_irq, 0, sizeof(map_irq)); | ||
702 | map_irq.domid = DOMID_SELF; | ||
703 | map_irq.type = MAP_PIRQ_TYPE_MSI; | ||
704 | map_irq.index = -1; | ||
705 | map_irq.pirq = -1; | ||
706 | map_irq.bus = dev->bus->number; | ||
707 | map_irq.devfn = dev->devfn; | ||
708 | |||
709 | if (type == PCI_CAP_ID_MSIX) { | ||
710 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | ||
711 | |||
712 | pci_read_config_dword(dev, msix_table_offset_reg(pos), | ||
713 | &table_offset); | ||
714 | bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); | ||
715 | |||
716 | map_irq.table_base = pci_resource_start(dev, bir); | ||
717 | map_irq.entry_nr = msidesc->msi_attrib.entry_nr; | ||
718 | } | ||
719 | 665 | ||
720 | spin_lock(&irq_mapping_update_lock); | 666 | spin_lock(&irq_mapping_update_lock); |
721 | 667 | ||
722 | irq = xen_allocate_irq_dynamic(); | 668 | irq = xen_allocate_irq_dynamic(); |
723 | |||
724 | if (irq == -1) | 669 | if (irq == -1) |
725 | goto out; | 670 | goto out; |
726 | 671 | ||
727 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); | ||
728 | if (rc) { | ||
729 | printk(KERN_WARNING "xen map irq failed %d\n", rc); | ||
730 | |||
731 | xen_free_irq(irq); | ||
732 | |||
733 | irq = -1; | ||
734 | goto out; | ||
735 | } | ||
736 | irq_info[irq] = mk_pirq_info(0, map_irq.pirq, 0, map_irq.index); | ||
737 | |||
738 | set_irq_chip_and_handler_name(irq, &xen_pirq_chip, | 672 | set_irq_chip_and_handler_name(irq, &xen_pirq_chip, |
739 | handle_level_irq, | 673 | handle_level_irq, name); |
740 | (type == PCI_CAP_ID_MSIX) ? "msi-x":"msi"); | ||
741 | 674 | ||
675 | irq_info[irq] = mk_pirq_info(0, pirq, 0, vector); | ||
676 | pirq_to_irq[pirq] = irq; | ||
677 | ret = set_irq_msi(irq, msidesc); | ||
678 | if (ret < 0) | ||
679 | goto error_irq; | ||
742 | out: | 680 | out: |
743 | spin_unlock(&irq_mapping_update_lock); | 681 | spin_unlock(&irq_mapping_update_lock); |
744 | return irq; | 682 | return irq; |
683 | error_irq: | ||
684 | spin_unlock(&irq_mapping_update_lock); | ||
685 | xen_free_irq(irq); | ||
686 | return -1; | ||
745 | } | 687 | } |
746 | #endif | 688 | #endif |
747 | 689 | ||