PCI: use common INTx swizzling loop
Subsystems (7)
cover PCI: use common INTx swizzling loop
This series adds a pci_common_swizzle() function in the PCI core and changes several architectures to use it instead of architecture-specific code.
Comments welcome.
Bjorn
---
Bjorn Helgaas (6):
PCI: x86/visws: use generic INTx swizzle from PCI core
PCI: sh: use generic INTx swizzle from PCI core
PCI: mips: use generic INTx swizzle from PCI core
PCI: arm: use generic INTx swizzle from PCI core
PCI: alpha: use generic INTx swizzle from PCI core
PCI: add pci_common_swizzle() for INTx swizzling
arch/alpha/kernel/pci.c | 18 ------------------ arch/alpha/kernel/pci_impl.h | 4 ++-- arch/arm/include/asm/mach/pci.h | 2 +- arch/arm/kernel/bios32.c | 27 --------------------------- arch/mips/pci/pci.c | 17 +---------------- arch/sh/drivers/pci/pci.c | 17 +---------------- arch/x86/pci/visws.c | 15 +-------------- drivers/pci/pci.c | 20 ++++++++++++++++++++ include/linux/pci.h | 1 + 9 files changed, 27 insertions(+), 94 deletions(-)
PATCH 1/6 PCI: add pci_common_swizzle() for INTx swizzling
This patch adds pci_common_swizzle(), which swizzles INTx values all the way up to a root bridge.
This common implementation can replace several architecture-specific ones. This should someday be combined with pci_get_interrupt_pin(), but I left it separate for now to make reviewing easier.
--- drivers/pci/pci.c | 20 ++++++++++++++++++++ include/linux/pci.h | 1 + 2 files changed, 21 insertions(+), 0 deletions(-)
drivers/pci/pci.c +20 -0
@@ -1369,6 +1369,26 @@ pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge) }/** +* pci_common_swizzle - swizzle INTx all the way to root bridge +* @dev: the PCI device +* @pinp: pointer to the INTx pin value (1=INTA, 2=INTB, 3=INTD, 4=INTD) +* +* Perform INTx swizzling for a device. This traverses through all PCI-to-PCI +* bridges all the way up to a PCI root bus. +*/ +u8 pci_common_swizzle (struct pci_dev *dev,u8 *pinp) +{ +u8 pin = *pinp; + +while (dev->bus->self) { + pin =pci_swizzle_interrupt_pin (dev, pin); + dev = dev->bus->self; + } + *pinp = pin; +return PCI_SLOT (dev->devfn); +} + +/** * pci_release_region - Release a PCI bar * @pdev: PCI device whose resources were previously reserved by pci_request_region * @bar: BAR to release
include/linux/pci.h +1 -0
@@ -529,6 +529,7 @@ 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); +u8 pci_common_swizzle (struct pci_dev *dev,u8 *pinp);extern struct pci_dev *pci_dev_get (struct pci_dev *dev);extern void pci_dev_put (struct pci_dev *dev);extern void pci_remove_bus (struct pci_bus *b);
Re: [PATCH 1/6] PCI: add pci_common_swizzle() for INTx swizzling
Quoted 8 lines · Bjorn Helgaas
This patch adds
pci_common_swizzle(), which swizzles INTx values all the way up to a root bridge.This common implementation can replace several architecture-specific ones. This should someday be combined with
pci_get_interrupt_pin(), but I left it separate for now to make reviewing easier.Signed-off-by Bjorn Helgaas <[email protected]>
We got acks from the arch maintainers on the previous series, so I'm assuming these ones are ok too (please pipe up if not, they're in my linux-next queue).
Thanks,
Signature · 1 line
Jesse Barnes, Intel Open Source Technology Center
PATCH 2/6 PCI: alpha: use generic INTx swizzle from PCI core
In reply to Bjorn HelgaasUse the generic pci_common_swizzle() instead of arch-specific code.
Note that pci_common_swizzle() loops based on dev->bus->self, not dev->bus->parent as the alpha common_swizzle() did. I think they are equivalent for this purpose.
--- arch/alpha/kernel/pci.c | 18 ------------------ arch/alpha/kernel/pci_impl.h | 4 ++-- 2 files changed, 2 insertions(+), 20 deletions(-)
arch/alpha/kernel/pci.c +0 -18
@@ -320,24 +320,6 @@ pcibios_update_irq(struct pci_dev *dev, int irq)pci_write_config_byte (dev,PCI_INTERRUPT_LINE , irq); } -/* Most Alphas have straight-forward swizzling needs. */ - -u8 __init -common_swizzle (struct pci_dev *dev,u8 *pinp) -{ -u8 pin = *pinp; - -while (dev->bus->parent) { - pin =pci_swizzle_interrupt_pin (dev, pin); -/* Move up the chain of bridges. */ - dev = dev->bus->self; - } - *pinp = pin; - -/* The slot is the slot of the last bridge. */ -return PCI_SLOT (dev->devfn); -} -void pcibios_resource_to_bus (struct pci_dev *dev,struct pci_bus_region *region,struct resource *res)
arch/alpha/kernel/pci_impl.h +2 -2
@@ -107,7 +107,7 @@ struct pci_iommu_arena;* Thus, each swizzle is ((pin-1) + (device#-4)) % 4 * * pci_swizzle_interrupt_pin() swizzles for exactly one bridge. The routine -* common_swizzle below handles multiple bridges. But there are a +* pci_common_swizzle() handles multiple bridges. But there are a * couple boards that do strange things. */
@@ -179,7 +179,7 @@ extern int pci_probe_only;extern unsigned long alpha_agpgart_size;extern void common_init_pci (void ); -extern u8 common_swizzle (struct pci_dev *,u8 *); +#define common_swizzle pci_common_swizzleextern struct pci_controller *alloc_pci_controller (void );extern struct resource *alloc_resource (void );
PATCH 3/6 PCI: arm: use generic INTx swizzle from PCI core
In reply to Bjorn HelgaasUse the generic pci_common_swizzle() instead of arch-specific code.
--- arch/arm/include/asm/mach/pci.h | 2 +- arch/arm/kernel/bios32.c | 27 --------------------------- 2 files changed, 1 insertions(+), 28 deletions(-)
arch/arm/include/asm/mach/pci.h +1 -1
@@ -42,7 +42,7 @@ struct pci_sys_data {/* * This is the standard PCI-PCI bridge swizzling algorithm. */ -u8 pci_std_swizzle (struct pci_dev *dev,u8 *pinp); +#define pci_std_swizzle pci_common_swizzle/* * Call this with your hw_pci struct to initialise the PCI system.
arch/arm/kernel/bios32.c +0 -27
@@ -480,33 +480,6 @@ EXPORT_SYMBOL(pcibios_bus_to_resource);#endif /* -* This is the standard PCI-PCI bridge swizzling algorithm: -* -* Dev: 0 1 2 3 -* A A B C D -* B B C D A -* C C D A B -* D D A B C -* ^^^^^^^^^^ irq pin on bridge -*/ -u8 __devinit pci_std_swizzle (struct pci_dev *dev,u8 *pinp) -{ -int pin = *pinp; - -while (dev->bus->self) { - pin =pci_swizzle_interrupt_pin (dev, pin); -/* -* move up the chain of bridges, -* swizzling as we go. -*/ - dev = dev->bus->self; - } - *pinp = pin; - -return PCI_SLOT (dev->devfn); -} - -/* * Swizzle the device pin each time we cross a bridge. * This might update pin and returns the slot number. */
PATCH 4/6 PCI: mips: use generic INTx swizzle from PCI core
In reply to Bjorn HelgaasUse the generic pci_common_swizzle() instead of arch-specific code.
Note that pci_common_swizzle() loops based on dev->bus->self, not dev->bus->parent as the mips common_swizzle() did. I think they are equivalent for this purpose.
--- arch/mips/pci/pci.c | 17 +---------------- 1 files changed, 1 insertions(+), 16 deletions(-)
arch/mips/pci/pci.c +1 -16
@@ -149,21 +149,6 @@ out: "Skipping PCI bus scan due to resource conflict\n"); } -static u8 __init common_swizzle (struct pci_dev *dev,u8 *pinp) -{ -u8 pin = *pinp; - -while (dev->bus->parent) { - pin =pci_swizzle_interrupt_pin (dev, pin); -/* Move up the chain of bridges. */ - dev = dev->bus->self; - } - *pinp = pin; - -/* The slot is the slot of the last bridge. */ -return PCI_SLOT (dev->devfn); -} -static int __init pcibios_init (void ) {struct pci_controller *hose;
@@ -172,7 +157,7 @@ static int __init pcibios_init(void)for (hose = hose_head; hose; hose = hose->next)pcibios_scanbus (hose); -pci_fixup_irqs (common_swizzle, pcibios_map_irq); +pci_fixup_irqs (pci_common_swizzle, pcibios_map_irq); pci_initialized =1 ;
PATCH 5/6 PCI: sh: use generic INTx swizzle from PCI core
In reply to Bjorn HelgaasUse the generic pci_common_swizzle() instead of arch-specific code.
Note that pci_common_swizzle() loops based on dev->bus->self, not dev->bus->parent as the sh simple_swizzle() did. I think they are equivalent for this purpose.
--- arch/sh/drivers/pci/pci.c | 17 +---------------- 1 files changed, 1 insertions(+), 16 deletions(-)
arch/sh/drivers/pci/pci.c +1 -16
@@ -21,21 +21,6 @@#include <linux/init.h> #include <asm/io.h> -static u8 __init simple_swizzle (struct pci_dev *dev,u8 *pinp) -{ -u8 pin = *pinp; - -while (dev->bus->parent) { - pin =pci_swizzle_interrupt_pin (dev, pin); -/* Move up the chain of bridges. */ - dev = dev->bus->self; - } - *pinp = pin; - -/* The slot is the slot of the last bridge. */ -return PCI_SLOT (dev->devfn); -} -static int __init pcibios_init (void ) {struct pci_channel *p;
@@ -56,7 +41,7 @@ static int __init pcibios_init(void) busno = bus->subordinate +1 ; } -pci_fixup_irqs (simple_swizzle, pcibios_map_platform_irq); +pci_fixup_irqs (pci_common_swizzle, pcibios_map_platform_irq);return 0 ; }
PATCH 6/6 PCI: x86/visws: use generic INTx swizzle from PCI core
In reply to Bjorn HelgaasUse the generic pci_common_swizzle() instead of arch-specific code.
--- arch/x86/pci/visws.c | 15 +-------------- 1 files changed, 1 insertions(+), 14 deletions(-)
arch/x86/pci/visws.c +1 -14
@@ -25,19 +25,6 @@ static void pci_visws_disable_irq(struct pci_dev *dev) { }unsigned int pci_bus0, pci_bus1; -static u8 __init visws_swizzle (struct pci_dev *dev,u8 *pinp) -{ -u8 pin = *pinp; - -while (dev->bus->self) {/* Move up the chain of bridges. */ - pin =pci_swizzle_interrupt_pin (dev, pin); - dev = dev->bus->self; - } - *pinp = pin; - -return PCI_SLOT (dev->devfn); -} -static int __init visws_map_irq (struct pci_dev *dev,u8 slot,u8 pin) {int irq, bus = dev->bus->number;
@@ -102,7 +89,7 @@ int __init pci_visws_init(void) raw_pci_ops = &pci_direct_conf1;pci_scan_bus_with_sysdata (pci_bus0);pci_scan_bus_with_sysdata (pci_bus1); -pci_fixup_irqs (visws_swizzle, visws_map_irq); +pci_fixup_irqs (pci_common_swizzle, visws_map_irq);pcibios_resource_survey ();return 0 ; }