aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/pci/xen.c68
-rw-r--r--drivers/xen/events.c30
-rw-r--r--include/xen/events.h4
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
87static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 87static 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
122error_while:
123 unbind_from_irqhandler(irq, NULL);
124error: 119error:
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
171error_while:
172 unbind_from_irqhandler(irq, NULL);
173error: 159error:
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");
177free: 161free:
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
650static int find_unbound_pirq(int type) 650int 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
664int xen_allocate_pirq_msi(char *name, int *pirq, int alloc_pirq) 664int 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;
689out: 683out:
690 spin_unlock(&irq_mapping_update_lock); 684 spin_unlock(&irq_mapping_update_lock);
691 return irq; 685 return irq;
686error_irq:
687 spin_unlock(&irq_mapping_update_lock);
688 xen_free_irq(irq);
689 return -1;
692} 690}
693 691
694int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type) 692int 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);
75int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name); 75int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name);
76 76
77#ifdef CONFIG_PCI_MSI 77#ifdef CONFIG_PCI_MSI
78int xen_allocate_pirq_msi(char *name, int *pirq, int alloc_pirq); 78int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc);
79int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
80 int pirq, const char *name);
79int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type); 81int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type);
80#endif 82#endif
81 83