aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/pci
diff options
context:
space:
mode:
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2013-02-28 09:05:41 -0500
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2013-03-01 10:54:21 -0500
commit884ac2978a295b7df3c4a686d3bff6932bbbb460 (patch)
tree4b2d8a9a6635ac4bed522f93ad9ad838b2e2d7f7 /arch/x86/pci
parentc79c49826270b8b0061b2fca840fc3f013c8a78a (diff)
xen/pci: We don't do multiple MSI's.
There is no hypercall to setup multiple MSI per PCI device. As such with these two new commits: - 08261d87f7d1b6253ab3223756625a5c74532293 PCI/MSI: Enable multiple MSIs with pci_enable_msi_block_auto() - 5ca72c4f7c412c2002363218901eba5516c476b1 AHCI: Support multiple MSIs we would call the PHYSDEVOP_map_pirq 'nvec' times with the same contents of the PCI device. Sander discovered that we would get the same PIRQ value 'nvec' times and return said values to the caller. That of course meant that the device was configured only with one MSI and AHCI would fail with: ahci 0000:00:11.0: version 3.0 xen: registering gsi 19 triggering 0 polarity 1 xen: --> pirq=19 -> irq=19 (gsi=19) (XEN) [2013-02-27 19:43:07] IOAPIC[0]: Set PCI routing entry (6-19 -> 0x99 -> IRQ 19 Mode:1 Active:1) ahci 0000:00:11.0: AHCI 0001.0200 32 slots 4 ports 6 Gbps 0xf impl SATA mode ahci 0000:00:11.0: flags: 64bit ncq sntf ilck pm led clo pmp pio slum part ahci: probe of 0000:00:11.0 failed with error -22 That is b/c in ahci_host_activate the second call to devm_request_threaded_irq would return -EINVAL as we passed in (on the second run) an IRQ that was never initialized. CC: stable@vger.kernel.org Reported-and-Tested-by: Sander Eikelenboom <linux@eikelenboom.it> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'arch/x86/pci')
-rw-r--r--arch/x86/pci/xen.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 56ab74989cf1..94e76620460f 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -162,6 +162,9 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
162 struct msi_desc *msidesc; 162 struct msi_desc *msidesc;
163 int *v; 163 int *v;
164 164
165 if (type == PCI_CAP_ID_MSI && nvec > 1)
166 return 1;
167
165 v = kzalloc(sizeof(int) * max(1, nvec), GFP_KERNEL); 168 v = kzalloc(sizeof(int) * max(1, nvec), GFP_KERNEL);
166 if (!v) 169 if (!v)
167 return -ENOMEM; 170 return -ENOMEM;
@@ -220,6 +223,9 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
220 struct msi_desc *msidesc; 223 struct msi_desc *msidesc;
221 struct msi_msg msg; 224 struct msi_msg msg;
222 225
226 if (type == PCI_CAP_ID_MSI && nvec > 1)
227 return 1;
228
223 list_for_each_entry(msidesc, &dev->msi_list, list) { 229 list_for_each_entry(msidesc, &dev->msi_list, list) {
224 __read_msi_msg(msidesc, &msg); 230 __read_msi_msg(msidesc, &msg);
225 pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) | 231 pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) |
@@ -263,6 +269,9 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
263 int ret = 0; 269 int ret = 0;
264 struct msi_desc *msidesc; 270 struct msi_desc *msidesc;
265 271
272 if (type == PCI_CAP_ID_MSI && nvec > 1)
273 return 1;
274
266 list_for_each_entry(msidesc, &dev->msi_list, list) { 275 list_for_each_entry(msidesc, &dev->msi_list, list) {
267 struct physdev_map_pirq map_irq; 276 struct physdev_map_pirq map_irq;
268 domid_t domid; 277 domid_t domid;