diff options
author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2008-12-11 11:24:23 -0700 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-01-07 11:12:50 -0800 |
commit | 57c2cf71c12318b72ebaa5720d210476b6bac4d4 (patch) | |
tree | ba071276800dc24d9232fd124c4678b2a86f86b5 | |
parent | 12b955ff63db0b75cfc2d4939696c57b31891ec6 (diff) | |
download | kernel_samsung_crespo-57c2cf71c12318b72ebaa5720d210476b6bac4d4.zip kernel_samsung_crespo-57c2cf71c12318b72ebaa5720d210476b6bac4d4.tar.gz kernel_samsung_crespo-57c2cf71c12318b72ebaa5720d210476b6bac4d4.tar.bz2 |
PCI: add pci_swizzle_interrupt_pin()
This patch adds pci_swizzle_interrupt_pin(), which implements the
INTx swizzling algorithm specified in Table 9-1 of the "PCI-to-PCI
Bridge Architecture Specification," revision 1.2.
There are many architecture-specific implementations of this
swizzle that can be replaced by this common one.
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r-- | drivers/pci/pci.c | 16 | ||||
-rw-r--r-- | include/linux/pci.h | 1 |
2 files changed, 16 insertions, 1 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index bd52ca4..d4d71fa 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1366,6 +1366,20 @@ void pci_enable_ari(struct pci_dev *dev) bridge->ari_enabled = 1; } +/** + * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge + * @dev: the PCI device + * @pin: the INTx pin (1=INTA, 2=INTB, 3=INTD, 4=INTD) + * + * 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. + */ +u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin) +{ + return (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1; +} + int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge) { @@ -1376,7 +1390,7 @@ pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge) return -1; while (dev->bus->self) { - pin = (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1; + pin = pci_swizzle_interrupt_pin(dev, pin); dev = dev->bus->self; } *bridge = dev; diff --git a/include/linux/pci.h b/include/linux/pci.h index bfcb39c..58357d1 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -532,6 +532,7 @@ int __must_check pci_bus_add_device(struct pci_dev *dev); void pci_read_bridge_bases(struct pci_bus *child); struct resource *pci_find_parent_resource(const struct pci_dev *dev, struct resource *res); +u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin); int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge); extern struct pci_dev *pci_dev_get(struct pci_dev *dev); extern void pci_dev_put(struct pci_dev *dev); |