aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew@wil.cx>2009-07-01 14:24:30 -0700
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-07-01 14:24:30 -0700
commit46b952a3c3a94afa339bd4961a4f3d1482436599 (patch)
treef531c057dd8bf6b7ab552774e41a907c99a6577f /drivers/pci/pci.c
parent944c54e7fc5ccf961bef2b5449958436b85de459 (diff)
downloadkernel_samsung_aries-46b952a3c3a94afa339bd4961a4f3d1482436599.zip
kernel_samsung_aries-46b952a3c3a94afa339bd4961a4f3d1482436599.tar.gz
kernel_samsung_aries-46b952a3c3a94afa339bd4961a4f3d1482436599.tar.bz2
PCI: Fix IRQ swizzling for ARI-enabled devices
For many purposes, including interrupt-swizzling, devices with ARI enabled behave as if they have one device (number 0) and 256 functions. This probably hasn't bitten us in practice because all ARI devices I've seen are also IOV devices, and IOV devices are required to use MSI. This isn't guaranteed, and there are legitimate reasons to use ARI without IOV, and hence potentially use pin-based interrupts. Signed-off-by: Matthew Wilcox <willy@linux.intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index d5d6f56..dbd0f94 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1517,11 +1517,20 @@ void pci_enable_ari(struct pci_dev *dev)
*
* Perform INTx swizzling for a device behind one level of bridge. This is
* required by section 9.1 of the PCI-to-PCI bridge specification for devices
- * behind bridges on add-in cards.
+ * behind bridges on add-in cards. For devices with ARI enabled, the slot
+ * number is always 0 (see the Implementation Note in section 2.2.8.1 of
+ * the PCI Express Base Specification, Revision 2.1)
*/
u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin)
{
- return (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1;
+ int slot;
+
+ if (pci_ari_enabled(dev->bus))
+ slot = 0;
+ else
+ slot = PCI_SLOT(dev->devfn);
+
+ return (((pin - 1) + slot) % 4) + 1;
}
int