diff options
author | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2013-02-28 09:05:41 -0500 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2013-03-01 10:54:21 -0500 |
commit | 884ac2978a295b7df3c4a686d3bff6932bbbb460 (patch) | |
tree | 4b2d8a9a6635ac4bed522f93ad9ad838b2e2d7f7 /arch/x86/pci/xen.c | |
parent | c79c49826270b8b0061b2fca840fc3f013c8a78a (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/xen.c')
-rw-r--r-- | arch/x86/pci/xen.c | 9 |
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; |