diff options
author | Qing He <qing.he@intel.com> | 2010-10-11 10:30:09 -0400 |
---|---|---|
committer | Stefano Stabellini <stefano.stabellini@eu.citrix.com> | 2010-10-22 16:25:44 -0400 |
commit | f731e3ef02b4744f4d7ca2f63539b900e47db31f (patch) | |
tree | 865ef6f817c372b99f0b36dc6f2638df087d51e7 /drivers/xen/events.c | |
parent | 38aa66fcb79e0a46c24bba96b6f2b851a6ec2037 (diff) |
xen: remap MSIs into pirqs when running as initial domain
Implement xen_create_msi_irq to create an msi and remap it as pirq.
Use xen_create_msi_irq to implement an initial domain specific version
of setup_msi_irqs.
Signed-off-by: Qing He <qing.he@intel.com>
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/xen/events.c')
-rw-r--r-- | drivers/xen/events.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index c649ac0aaeef..a7d9555e664d 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/bootmem.h> | 29 | #include <linux/bootmem.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/irqnr.h> | 31 | #include <linux/irqnr.h> |
32 | #include <linux/pci.h> | ||
32 | 33 | ||
33 | #include <asm/desc.h> | 34 | #include <asm/desc.h> |
34 | #include <asm/ptrace.h> | 35 | #include <asm/ptrace.h> |
@@ -656,6 +657,10 @@ out: | |||
656 | return irq; | 657 | return irq; |
657 | } | 658 | } |
658 | 659 | ||
660 | #ifdef CONFIG_PCI_MSI | ||
661 | #include <linux/msi.h> | ||
662 | #include "../pci/msi.h" | ||
663 | |||
659 | void xen_allocate_pirq_msi(char *name, int *irq, int *pirq) | 664 | void xen_allocate_pirq_msi(char *name, int *irq, int *pirq) |
660 | { | 665 | { |
661 | spin_lock(&irq_mapping_update_lock); | 666 | spin_lock(&irq_mapping_update_lock); |
@@ -678,6 +683,61 @@ out: | |||
678 | spin_unlock(&irq_mapping_update_lock); | 683 | spin_unlock(&irq_mapping_update_lock); |
679 | } | 684 | } |
680 | 685 | ||
686 | int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type) | ||
687 | { | ||
688 | int irq = -1; | ||
689 | struct physdev_map_pirq map_irq; | ||
690 | int rc; | ||
691 | int pos; | ||
692 | u32 table_offset, bir; | ||
693 | |||
694 | memset(&map_irq, 0, sizeof(map_irq)); | ||
695 | map_irq.domid = DOMID_SELF; | ||
696 | map_irq.type = MAP_PIRQ_TYPE_MSI; | ||
697 | map_irq.index = -1; | ||
698 | map_irq.pirq = -1; | ||
699 | map_irq.bus = dev->bus->number; | ||
700 | map_irq.devfn = dev->devfn; | ||
701 | |||
702 | if (type == PCI_CAP_ID_MSIX) { | ||
703 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | ||
704 | |||
705 | pci_read_config_dword(dev, msix_table_offset_reg(pos), | ||
706 | &table_offset); | ||
707 | bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); | ||
708 | |||
709 | map_irq.table_base = pci_resource_start(dev, bir); | ||
710 | map_irq.entry_nr = msidesc->msi_attrib.entry_nr; | ||
711 | } | ||
712 | |||
713 | spin_lock(&irq_mapping_update_lock); | ||
714 | |||
715 | irq = find_unbound_irq(); | ||
716 | |||
717 | if (irq == -1) | ||
718 | goto out; | ||
719 | |||
720 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); | ||
721 | if (rc) { | ||
722 | printk(KERN_WARNING "xen map irq failed %d\n", rc); | ||
723 | |||
724 | irq_free_desc(irq); | ||
725 | |||
726 | irq = -1; | ||
727 | goto out; | ||
728 | } | ||
729 | irq_info[irq] = mk_pirq_info(0, map_irq.pirq, 0, map_irq.index); | ||
730 | |||
731 | set_irq_chip_and_handler_name(irq, &xen_pirq_chip, | ||
732 | handle_level_irq, | ||
733 | (type == PCI_CAP_ID_MSIX) ? "msi-x":"msi"); | ||
734 | |||
735 | out: | ||
736 | spin_unlock(&irq_mapping_update_lock); | ||
737 | return irq; | ||
738 | } | ||
739 | #endif | ||
740 | |||
681 | int xen_destroy_irq(int irq) | 741 | int xen_destroy_irq(int irq) |
682 | { | 742 | { |
683 | struct irq_desc *desc; | 743 | struct irq_desc *desc; |