diff options
-rw-r--r-- | arch/x86/pci/xen.c | 68 | ||||
-rw-r--r-- | drivers/xen/events.c | 30 | ||||
-rw-r--r-- | include/xen/events.h | 4 |
3 files changed, 43 insertions, 59 deletions
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 0d5087eeced8..93e42152d8d0 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
@@ -86,7 +86,7 @@ static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq, | |||
86 | 86 | ||
87 | static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | 87 | static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) |
88 | { | 88 | { |
89 | int irq, pirq, ret = 0; | 89 | int irq, pirq; |
90 | struct msi_desc *msidesc; | 90 | struct msi_desc *msidesc; |
91 | struct msi_msg msg; | 91 | struct msi_msg msg; |
92 | 92 | ||
@@ -94,39 +94,32 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
94 | __read_msi_msg(msidesc, &msg); | 94 | __read_msi_msg(msidesc, &msg); |
95 | pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) | | 95 | pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) | |
96 | ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff); | 96 | ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff); |
97 | if (xen_irq_from_pirq(pirq) >= 0 && msg.data == XEN_PIRQ_MSI_DATA) { | 97 | if (msg.data != XEN_PIRQ_MSI_DATA || |
98 | irq = xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ? | 98 | xen_irq_from_pirq(pirq) < 0) { |
99 | "msi-x" : "msi", &pirq, 0); | 99 | pirq = xen_allocate_pirq_msi(dev, msidesc); |
100 | if (irq < 0) | 100 | if (pirq < 0) |
101 | goto error; | 101 | goto error; |
102 | ret = set_irq_msi(irq, msidesc); | 102 | xen_msi_compose_msg(dev, pirq, &msg); |
103 | if (ret < 0) | 103 | __write_msi_msg(msidesc, &msg); |
104 | goto error_while; | 104 | dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq); |
105 | printk(KERN_DEBUG "xen: msi already setup: msi --> irq=%d" | 105 | } else { |
106 | " pirq=%d\n", irq, pirq); | 106 | dev_dbg(&dev->dev, |
107 | return 0; | 107 | "xen: msi already bound to pirq=%d\n", pirq); |
108 | } | 108 | } |
109 | irq = xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ? | 109 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, |
110 | "msi-x" : "msi", &pirq, 1); | 110 | (type == PCI_CAP_ID_MSIX) ? |
111 | if (irq < 0 || pirq < 0) | 111 | "msi-x" : "msi"); |
112 | if (irq < 0) | ||
112 | goto error; | 113 | goto error; |
113 | printk(KERN_DEBUG "xen: msi --> irq=%d, pirq=%d\n", irq, pirq); | 114 | dev_dbg(&dev->dev, |
114 | xen_msi_compose_msg(dev, pirq, &msg); | 115 | "xen: msi --> pirq=%d --> irq=%d\n", pirq, irq); |
115 | ret = set_irq_msi(irq, msidesc); | ||
116 | if (ret < 0) | ||
117 | goto error_while; | ||
118 | write_msi_msg(irq, &msg); | ||
119 | } | 116 | } |
120 | return 0; | 117 | return 0; |
121 | 118 | ||
122 | error_while: | ||
123 | unbind_from_irqhandler(irq, NULL); | ||
124 | error: | 119 | error: |
125 | if (ret == -ENODEV) | 120 | dev_err(&dev->dev, |
126 | dev_err(&dev->dev, "Xen PCI frontend has not registered" \ | 121 | "Xen PCI frontend has not registered MSI/MSI-X support!\n"); |
127 | " MSI/MSI-X support!\n"); | 122 | return -ENODEV; |
128 | |||
129 | return ret; | ||
130 | } | 123 | } |
131 | 124 | ||
132 | /* | 125 | /* |
@@ -152,28 +145,19 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
152 | goto error; | 145 | goto error; |
153 | i = 0; | 146 | i = 0; |
154 | list_for_each_entry(msidesc, &dev->msi_list, list) { | 147 | list_for_each_entry(msidesc, &dev->msi_list, list) { |
155 | irq = xen_allocate_pirq_msi( | 148 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], |
156 | (type == PCI_CAP_ID_MSIX) ? | 149 | (type == PCI_CAP_ID_MSIX) ? |
157 | "pcifront-msi-x" : "pcifront-msi", | 150 | "pcifront-msi-x" : |
158 | &v[i], 0); | 151 | "pcifront-msi"); |
159 | if (irq < 0) { | 152 | if (irq < 0) |
160 | ret = -1; | ||
161 | goto free; | 153 | goto free; |
162 | } | ||
163 | ret = set_irq_msi(irq, msidesc); | ||
164 | if (ret) | ||
165 | goto error_while; | ||
166 | i++; | 154 | i++; |
167 | } | 155 | } |
168 | kfree(v); | 156 | kfree(v); |
169 | return 0; | 157 | return 0; |
170 | 158 | ||
171 | error_while: | ||
172 | unbind_from_irqhandler(irq, NULL); | ||
173 | error: | 159 | error: |
174 | if (ret == -ENODEV) | 160 | dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n"); |
175 | dev_err(&dev->dev, "Xen PCI frontend has not registered" \ | ||
176 | " MSI/MSI-X support!\n"); | ||
177 | free: | 161 | free: |
178 | kfree(v); | 162 | kfree(v); |
179 | return ret; | 163 | return ret; |
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index c21066fc30be..1033f6284f31 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -647,12 +647,12 @@ out: | |||
647 | #include <linux/msi.h> | 647 | #include <linux/msi.h> |
648 | #include "../pci/msi.h" | 648 | #include "../pci/msi.h" |
649 | 649 | ||
650 | static int find_unbound_pirq(int type) | 650 | int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc) |
651 | { | 651 | { |
652 | int rc; | 652 | int rc; |
653 | struct physdev_get_free_pirq op_get_free_pirq; | 653 | struct physdev_get_free_pirq op_get_free_pirq; |
654 | 654 | ||
655 | op_get_free_pirq.type = type; | 655 | op_get_free_pirq.type = MAP_PIRQ_TYPE_MSI; |
656 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq); | 656 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq); |
657 | 657 | ||
658 | WARN_ONCE(rc == -ENOSYS, | 658 | WARN_ONCE(rc == -ENOSYS, |
@@ -661,9 +661,10 @@ static int find_unbound_pirq(int type) | |||
661 | return rc ? -1 : op_get_free_pirq.pirq; | 661 | return rc ? -1 : op_get_free_pirq.pirq; |
662 | } | 662 | } |
663 | 663 | ||
664 | int xen_allocate_pirq_msi(char *name, int *pirq, int alloc_pirq) | 664 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, |
665 | int pirq, const char *name) | ||
665 | { | 666 | { |
666 | int irq; | 667 | int irq, ret; |
667 | 668 | ||
668 | spin_lock(&irq_mapping_update_lock); | 669 | spin_lock(&irq_mapping_update_lock); |
669 | 670 | ||
@@ -671,24 +672,21 @@ int xen_allocate_pirq_msi(char *name, int *pirq, int alloc_pirq) | |||
671 | if (irq == -1) | 672 | if (irq == -1) |
672 | goto out; | 673 | goto out; |
673 | 674 | ||
674 | if (alloc_pirq) { | ||
675 | *pirq = find_unbound_pirq(MAP_PIRQ_TYPE_MSI); | ||
676 | if (*pirq == -1) { | ||
677 | xen_free_irq(irq); | ||
678 | irq = -1; | ||
679 | goto out; | ||
680 | } | ||
681 | } | ||
682 | |||
683 | set_irq_chip_and_handler_name(irq, &xen_pirq_chip, | 675 | set_irq_chip_and_handler_name(irq, &xen_pirq_chip, |
684 | handle_level_irq, name); | 676 | handle_level_irq, name); |
685 | 677 | ||
686 | irq_info[irq] = mk_pirq_info(0, *pirq, 0, 0); | 678 | irq_info[irq] = mk_pirq_info(0, pirq, 0, 0); |
687 | pirq_to_irq[*pirq] = irq; | 679 | pirq_to_irq[pirq] = irq; |
688 | 680 | ret = set_irq_msi(irq, msidesc); | |
681 | if (ret < 0) | ||
682 | goto error_irq; | ||
689 | out: | 683 | out: |
690 | spin_unlock(&irq_mapping_update_lock); | 684 | spin_unlock(&irq_mapping_update_lock); |
691 | return irq; | 685 | return irq; |
686 | error_irq: | ||
687 | spin_unlock(&irq_mapping_update_lock); | ||
688 | xen_free_irq(irq); | ||
689 | return -1; | ||
692 | } | 690 | } |
693 | 691 | ||
694 | int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type) | 692 | int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type) |
diff --git a/include/xen/events.h b/include/xen/events.h index f70536af921c..18bf825bac66 100644 --- a/include/xen/events.h +++ b/include/xen/events.h | |||
@@ -75,7 +75,9 @@ int xen_allocate_pirq(unsigned gsi, int shareable, char *name); | |||
75 | int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name); | 75 | 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 | int xen_allocate_pirq_msi(char *name, int *pirq, int alloc_pirq); | 78 | int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc); |
79 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, | ||
80 | int pirq, const char *name); | ||
79 | int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type); | 81 | int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type); |
80 | #endif | 82 | #endif |
81 | 83 | ||