aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-03-15 13:47:56 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-15 13:47:56 -0400
commit010b8f4e264b0b6f596186574956dde2fa02df1c (patch)
tree277d599cc0147be3a3d5bfdf676510c0add154c0 /drivers/xen
parent397fae081869784d07cd4edde0ddf436ca2011e0 (diff)
parent71eef7d1e3d9df760897fdd2cad6949a8bcf1620 (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.c96
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> 647int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc)
648#include "../pci/msi.h"
649
650static 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
667void 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
689out: 658 return rc ? -1 : op_get_free_pirq.pirq;
690 spin_unlock(&irq_mapping_update_lock);
691} 659}
692 660
693int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type) 661int 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;
742out: 680out:
743 spin_unlock(&irq_mapping_update_lock); 681 spin_unlock(&irq_mapping_update_lock);
744 return irq; 682 return irq;
683error_irq:
684 spin_unlock(&irq_mapping_update_lock);
685 xen_free_irq(irq);
686 return -1;
745} 687}
746#endif 688#endif
747 689