diff options
| -rw-r--r-- | arch/x86/pci/xen.c | 27 | ||||
| -rw-r--r-- | drivers/xen/events.c | 24 | ||||
| -rw-r--r-- | include/xen/events.h | 7 |
3 files changed, 43 insertions, 15 deletions
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index d7b5109f7a9c..25cd4a07d09f 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
| @@ -70,6 +70,9 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, | |||
| 70 | struct xen_pci_frontend_ops *xen_pci_frontend; | 70 | struct xen_pci_frontend_ops *xen_pci_frontend; |
| 71 | EXPORT_SYMBOL_GPL(xen_pci_frontend); | 71 | EXPORT_SYMBOL_GPL(xen_pci_frontend); |
| 72 | 72 | ||
| 73 | #define XEN_PIRQ_MSI_DATA (MSI_DATA_TRIGGER_EDGE | \ | ||
| 74 | MSI_DATA_LEVEL_ASSERT | (3 << 8) | MSI_DATA_VECTOR(0)) | ||
| 75 | |||
| 73 | static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq, | 76 | static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq, |
| 74 | struct msi_msg *msg) | 77 | struct msi_msg *msg) |
| 75 | { | 78 | { |
| @@ -83,12 +86,7 @@ static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq, | |||
| 83 | MSI_ADDR_REDIRECTION_CPU | | 86 | MSI_ADDR_REDIRECTION_CPU | |
| 84 | MSI_ADDR_DEST_ID(pirq); | 87 | MSI_ADDR_DEST_ID(pirq); |
| 85 | 88 | ||
| 86 | msg->data = | 89 | msg->data = XEN_PIRQ_MSI_DATA; |
| 87 | MSI_DATA_TRIGGER_EDGE | | ||
| 88 | MSI_DATA_LEVEL_ASSERT | | ||
| 89 | /* delivery mode reserved */ | ||
| 90 | (3 << 8) | | ||
| 91 | MSI_DATA_VECTOR(0); | ||
| 92 | } | 90 | } |
| 93 | 91 | ||
| 94 | static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | 92 | static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) |
| @@ -98,8 +96,23 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
| 98 | struct msi_msg msg; | 96 | struct msi_msg msg; |
| 99 | 97 | ||
| 100 | list_for_each_entry(msidesc, &dev->msi_list, list) { | 98 | list_for_each_entry(msidesc, &dev->msi_list, list) { |
| 99 | __read_msi_msg(msidesc, &msg); | ||
| 100 | pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) | | ||
| 101 | ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff); | ||
| 102 | if (xen_irq_from_pirq(pirq) >= 0 && msg.data == XEN_PIRQ_MSI_DATA) { | ||
| 103 | xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ? | ||
| 104 | "msi-x" : "msi", &irq, &pirq, XEN_ALLOC_IRQ); | ||
| 105 | if (irq < 0) | ||
| 106 | goto error; | ||
| 107 | ret = set_irq_msi(irq, msidesc); | ||
| 108 | if (ret < 0) | ||
| 109 | goto error_while; | ||
| 110 | printk(KERN_DEBUG "xen: msi already setup: msi --> irq=%d" | ||
| 111 | " pirq=%d\n", irq, pirq); | ||
| 112 | return 0; | ||
| 113 | } | ||
| 101 | xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ? | 114 | xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ? |
| 102 | "msi-x" : "msi", &irq, &pirq); | 115 | "msi-x" : "msi", &irq, &pirq, (XEN_ALLOC_IRQ | XEN_ALLOC_PIRQ)); |
| 103 | if (irq < 0 || pirq < 0) | 116 | if (irq < 0 || pirq < 0) |
| 104 | goto error; | 117 | goto error; |
| 105 | printk(KERN_DEBUG "xen: msi --> irq=%d, pirq=%d\n", irq, pirq); | 118 | printk(KERN_DEBUG "xen: msi --> irq=%d, pirq=%d\n", irq, pirq); |
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 7ab43c33f746..f78945ce8aeb 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
| @@ -668,17 +668,21 @@ out: | |||
| 668 | #include <linux/msi.h> | 668 | #include <linux/msi.h> |
| 669 | #include "../pci/msi.h" | 669 | #include "../pci/msi.h" |
| 670 | 670 | ||
| 671 | void xen_allocate_pirq_msi(char *name, int *irq, int *pirq) | 671 | void xen_allocate_pirq_msi(char *name, int *irq, int *pirq, int alloc) |
| 672 | { | 672 | { |
| 673 | spin_lock(&irq_mapping_update_lock); | 673 | spin_lock(&irq_mapping_update_lock); |
| 674 | 674 | ||
| 675 | *irq = find_unbound_irq(); | 675 | if (alloc & XEN_ALLOC_IRQ) { |
| 676 | if (*irq == -1) | 676 | *irq = find_unbound_irq(); |
| 677 | goto out; | 677 | if (*irq == -1) |
| 678 | goto out; | ||
| 679 | } | ||
| 678 | 680 | ||
| 679 | *pirq = find_unbound_pirq(MAP_PIRQ_TYPE_MSI); | 681 | if (alloc & XEN_ALLOC_PIRQ) { |
| 680 | if (*pirq == -1) | 682 | *pirq = find_unbound_pirq(MAP_PIRQ_TYPE_MSI); |
| 681 | goto out; | 683 | if (*pirq == -1) |
| 684 | goto out; | ||
| 685 | } | ||
| 682 | 686 | ||
| 683 | set_irq_chip_and_handler_name(*irq, &xen_pirq_chip, | 687 | set_irq_chip_and_handler_name(*irq, &xen_pirq_chip, |
| 684 | handle_level_irq, name); | 688 | handle_level_irq, name); |
| @@ -766,6 +770,7 @@ int xen_destroy_irq(int irq) | |||
| 766 | printk(KERN_WARNING "unmap irq failed %d\n", rc); | 770 | printk(KERN_WARNING "unmap irq failed %d\n", rc); |
| 767 | goto out; | 771 | goto out; |
| 768 | } | 772 | } |
| 773 | pirq_to_irq[info->u.pirq.pirq] = -1; | ||
| 769 | } | 774 | } |
| 770 | irq_info[irq] = mk_unbound_info(); | 775 | irq_info[irq] = mk_unbound_info(); |
| 771 | 776 | ||
| @@ -786,6 +791,11 @@ int xen_gsi_from_irq(unsigned irq) | |||
| 786 | return gsi_from_irq(irq); | 791 | return gsi_from_irq(irq); |
| 787 | } | 792 | } |
| 788 | 793 | ||
| 794 | int xen_irq_from_pirq(unsigned pirq) | ||
| 795 | { | ||
| 796 | return pirq_to_irq[pirq]; | ||
| 797 | } | ||
| 798 | |||
| 789 | int bind_evtchn_to_irq(unsigned int evtchn) | 799 | int bind_evtchn_to_irq(unsigned int evtchn) |
| 790 | { | 800 | { |
| 791 | int irq; | 801 | int irq; |
diff --git a/include/xen/events.h b/include/xen/events.h index 646dd17d3aa4..00f53ddcc062 100644 --- a/include/xen/events.h +++ b/include/xen/events.h | |||
| @@ -76,7 +76,9 @@ int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name); | |||
| 76 | 76 | ||
| 77 | #ifdef CONFIG_PCI_MSI | 77 | #ifdef CONFIG_PCI_MSI |
| 78 | /* Allocate an irq and a pirq to be used with MSIs. */ | 78 | /* Allocate an irq and a pirq to be used with MSIs. */ |
| 79 | void xen_allocate_pirq_msi(char *name, int *irq, int *pirq); | 79 | #define XEN_ALLOC_PIRQ (1 << 0) |
| 80 | #define XEN_ALLOC_IRQ (1 << 1) | ||
| 81 | void xen_allocate_pirq_msi(char *name, int *irq, int *pirq, int alloc_mask); | ||
| 80 | int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type); | 82 | int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type); |
| 81 | #endif | 83 | #endif |
| 82 | 84 | ||
| @@ -89,4 +91,7 @@ int xen_vector_from_irq(unsigned pirq); | |||
| 89 | /* Return gsi allocated to pirq */ | 91 | /* Return gsi allocated to pirq */ |
| 90 | int xen_gsi_from_irq(unsigned pirq); | 92 | int xen_gsi_from_irq(unsigned pirq); |
| 91 | 93 | ||
| 94 | /* Return irq from pirq */ | ||
| 95 | int xen_irq_from_pirq(unsigned pirq); | ||
| 96 | |||
| 92 | #endif /* _XEN_EVENTS_H */ | 97 | #endif /* _XEN_EVENTS_H */ |
