Skip to contentSkip to conversation

PCI: unify P2P bridge INTx swizzling

PATCH Applied Bjorn Helgaas 7 participants 24 messages Dec 9, 2008 – Dec 16, 2008

Subsystems (10)
lore
Share & tools
lore
#0 lore raw

cover PCI: unify P2P bridge INTx swizzling

This series adds a pci_swizzle_interrupt_pin() function in the PCI core. Most architectures currently implement this independently.

After this series, many of the callers of pci_swizzle_interrupt_pin() follow a similar pattern. I'd like to consolidate those callers, too, but I haven't started that yet.

One strange thing I'd like to understand eventually is why the swizzle in acpi_pci_irq_derive() does something special for CardBus bridges, while no other architecture does.

Comments welcome.

These patches have been compile-tested on:

    alpha
    arm
    ia64
    mips
    powerpc (ppc64)
    sh
    x86 (32-bit)
    x86 (64-bit)

I've boot-tested these architectures:

    ia64
    x86 (32-bit)

I haven't compiled parisc for want of a cross-compiler.

Bjorn

---

Bjorn Helgaas (12):
PCI: x86: use generic pci_swizzle_interrupt_pin()
PCI: sh: use generic pci_swizzle_interrupt_pin()
PCI: powerpc: use generic pci_swizzle_interrupt_pin()
PCI: parisc: use generic pci_swizzle_interrupt_pin()
PCI: mips: use generic pci_swizzle_interrupt_pin()
PCI: arm: use generic pci_swizzle_interrupt_pin()
PCI: alpha: use generic pci_swizzle_interrupt_pin()
PCI: add pci_swizzle_interrupt_pin()
x86/PCI: minor logic simplications
x86/PCI: use config space encoding for interrupt pins
PCI: use config space encoding in pci_get_interrupt_pin() PCI Hotplug: cpqphp: use config space PCI interrupt pin encoding

 arch/alpha/kernel/pci.c           |    2 +
 arch/alpha/kernel/pci_impl.h      |    9 +-----
 arch/alpha/kernel/sys_dp264.c     |    2 +
 arch/alpha/kernel/sys_eiger.c     |    2 +
 arch/alpha/kernel/sys_miata.c     |    2 +
 arch/alpha/kernel/sys_noritake.c  |    2 +
 arch/alpha/kernel/sys_ruffian.c   |    2 +
 arch/alpha/kernel/sys_sable.c     |    2 +
 arch/arm/kernel/bios32.c          |    6 ++--
 arch/arm/mach-integrator/pci.c    |   11 +-------
 arch/mips/pci/pci-ip27.c          |    6 ----
 arch/mips/pci/pci.c               |    9 +-----
 arch/powerpc/kernel/prom_parse.c  |    7 +----
 arch/sh/drivers/pci/ops-cayman.c  |    9 +-----
 arch/sh/drivers/pci/pci.c         |    7 +----
 arch/x86/pci/irq.c                |   54 +++++++++++++++++--------------------
 arch/x86/pci/visws.c              |    7 +----
 drivers/parisc/dino.c             |    4 +--
 drivers/parisc/iosapic.c          |    3 +-
 drivers/pci/hotplug/cpqphp_ctrl.c |    4 +--
 drivers/pci/hotplug/cpqphp_pci.c  |    2 +
 drivers/pci/pci.c                 |   10 +++++--
 include/linux/pci.h               |    1 +
 23 files changed, 60 insertions(+), 103 deletions(-)
Signature · 1 line
Signature
#1 lore raw

PATCH 1/12 PCI Hotplug: cpqphp: use config space PCI interrupt pin encoding

This patch changes cpqphp to use interrupt pin values just as they come from PCI config space, i.e., 1=INTA, ..., 4=INTD.

pcibios_set_irq_routing() takes pin arguments in the range 0=INTA, ..., 3=INTD, so we'll adjust the pin just before calling it.

---
 drivers/pci/hotplug/cpqphp_ctrl.c |    4 ++--
 drivers/pci/hotplug/cpqphp_pci.c  |    2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)
drivers/pci/hotplug/cpqphp_ctrl.c +2 -2
index a60a252..d947221 100644
@@ -2604,7 +2604,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
 			for (cloop = 0; cloop < 4; cloop++) {
 				if (irqs.valid_INT & (0x01 << cloop)) {
 					rc = cpqhp_set_irq(func->bus, func->device,
-							   0x0A + cloop, irqs.interrupt[cloop]);
+							   cloop + 1, irqs.interrupt[cloop]);
 					if (rc)
 						goto free_and_out;
 				}
@@ -2945,7 +2945,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
 		}
 
 		if (!behind_bridge) {
-			rc = cpqhp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ);
+			rc = cpqhp_set_irq(func->bus, func->device, temp_byte, IRQ);
 			if (rc)
 				return 1;
 		} else {
drivers/pci/hotplug/cpqphp_pci.c +1 -1
index 0902193..125d287 100644
@@ -171,7 +171,7 @@ int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
 		fakebus->number = bus_num;
 		dbg("%s: dev %d, bus %d, pin %d, num %d\n",
 		    __func__, dev_num, bus_num, int_pin, irq_num);
-		rc = pcibios_set_irq_routing(fakedev, int_pin - 0x0a, irq_num);
+		rc = pcibios_set_irq_routing(fakedev, int_pin - 1, irq_num);
 		kfree(fakedev);
 		kfree(fakebus);
 		dbg("%s: rc %d\n", __func__, rc);
#2 lore raw

PATCH 2/12 PCI: use config space encoding in pci_get_interrupt_pin()

In reply to Bjorn Helgaas

This patch makes pci_get_interrupt_pin() return values encoded the same way as the "Interrupt Pin" value in PCI config space, i.e., 1=INTA, ..., 4=INTD.

pirq_bios_set() is the only in-tree caller of pci_get_interrupt_pin() and pci_get_interrupt_pin() is not exported.

---
 arch/x86/pci/irq.c |    2 +-
 drivers/pci/pci.c  |    4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)
arch/x86/pci/irq.c +1 -1
index bf69dbe..15c3e69 100644
@@ -534,7 +534,7 @@ static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq,
 {
 	struct pci_dev *bridge;
 	int pin = pci_get_interrupt_pin(dev, &bridge);
-	return pcibios_set_irq_routing(bridge, pin, irq);
+	return pcibios_set_irq_routing(bridge, pin - 1, irq);
 }
 
 #endif
drivers/pci/pci.c +2 -2
index 061d1ee..46f6821 100644
@@ -1345,9 +1345,9 @@ pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)
 	pin = dev->pin;
 	if (!pin)
 		return -1;
-	pin--;
+
 	while (dev->bus->self) {
-		pin = (pin + PCI_SLOT(dev->devfn)) % 4;
+		pin = (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1;
 		dev = dev->bus->self;
 	}
 	*bridge = dev;
#3 lore raw

PATCH 3/12 x86/PCI: use config space encoding for interrupt pins

In reply to Bjorn Helgaas

Keep "pin" encoded as it is in the "Interrupt Pin" value in PCI config space, i.e., 0=device doesn't use interrupts, 1=INTA, ..., 4=INTD.

This makes the bridge INTx swizzle match other architectures.

---
 arch/x86/pci/irq.c |   44 ++++++++++++++++++++------------------------
 1 files changed, 20 insertions(+), 24 deletions(-)
arch/x86/pci/irq.c +20 -24
index 15c3e69..5d1ce1c 100644
@@ -888,7 +888,6 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
 		dev_dbg(&dev->dev, "no interrupt pin\n");
 		return 0;
 	}
-	pin = pin - 1;
 
 	/* Find IRQ routing entry */
 
@@ -898,17 +897,17 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
 	info = pirq_get_info(dev);
 	if (!info) {
 		dev_dbg(&dev->dev, "PCI INT %c not found in routing table\n",
-			'A' + pin);
+			'A' + pin - 1);
 		return 0;
 	}
-	pirq = info->irq[pin].link;
-	mask = info->irq[pin].bitmap;
+	pirq = info->irq[pin - 1].link;
+	mask = info->irq[pin - 1].bitmap;
 	if (!pirq) {
-		dev_dbg(&dev->dev, "PCI INT %c not routed\n", 'A' + pin);
+		dev_dbg(&dev->dev, "PCI INT %c not routed\n", 'A' + pin - 1);
 		return 0;
 	}
 	dev_dbg(&dev->dev, "PCI INT %c -> PIRQ %02x, mask %04x, excl %04x",
-		'A' + pin, pirq, mask, pirq_table->exclusive_irqs);
+		'A' + pin - 1, pirq, mask, pirq_table->exclusive_irqs);
 	mask &= pcibios_irq_mask;
 
 	/* Work around broken HP Pavilion Notebooks which assign USB to
@@ -950,7 +949,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
 				newirq = i;
 		}
 	}
-	dev_dbg(&dev->dev, "PCI INT %c -> newirq %d", 'A' + pin, newirq);
+	dev_dbg(&dev->dev, "PCI INT %c -> newirq %d", 'A' + pin - 1, newirq);
 
 	/* Check if it is hardcoded */
 	if ((pirq & 0xf0) == 0xf0) {
@@ -978,18 +977,18 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
 			return 0;
 		}
 	}
-	dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", msg, 'A' + pin, irq);
+	dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", msg, 'A' + pin - 1, irq);
 
 	/* Update IRQ for all devices with the same pirq value */
 	while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) {
 		pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin);
 		if (!pin)
 			continue;
-		pin--;
+
 		info = pirq_get_info(dev2);
 		if (!info)
 			continue;
-		if (info->irq[pin].link == pirq) {
+		if (info->irq[pin - 1].link == pirq) {
 			/*
 			 * We refuse to override the dev->irq
 			 * information. Give a warning!
@@ -1056,9 +1055,8 @@ static void __init pcibios_fixup_irqs(void)
 			/*
 			 * interrupt pins are numbered starting from 1
 			 */
-			pin--;
 			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
-				PCI_SLOT(dev->devfn), pin);
+				PCI_SLOT(dev->devfn), pin - 1);
 			/*
 			 * Busses behind bridges are typically not listed in the
 			 * MP-table.  In this case we have to look up the IRQ
@@ -1071,22 +1069,22 @@ static void __init pcibios_fixup_irqs(void)
 				struct pci_dev *bridge = dev->bus->self;
 				int bus;
 
-				pin = (pin + PCI_SLOT(dev->devfn)) % 4;
+				pin = (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1;
 				bus = bridge->bus->number;
 				irq = IO_APIC_get_PCI_irq_vector(bus,
-						PCI_SLOT(bridge->devfn), pin);
+						PCI_SLOT(bridge->devfn), pin - 1);
 				if (irq >= 0)
 					dev_warn(&dev->dev,
 						"using bridge %s INT %c to "
 							"get IRQ %d\n",
 						 pci_name(bridge),
-						 'A' + pin, irq);
+						 'A' + pin - 1, irq);
 			}
 			if (irq >= 0) {
 				dev_info(&dev->dev,
 					"PCI->APIC IRQ transform: INT %c "
 						"-> IRQ %d\n",
-					'A' + pin, irq);
+					'A' + pin - 1, irq);
 				dev->irq = irq;
 			}
 		}
@@ -1221,12 +1219,10 @@ static int pirq_enable_irq(struct pci_dev *dev)
 	if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
 		char *msg = "";
 
-		pin--; /* interrupt pins are numbered starting from 1 */
-
 		if (io_apic_assign_pci_irqs) {
 			int irq;
 
-			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
+			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin - 1);
 			/*
 			 * Busses behind bridges are typically not listed in the MP-table.
 			 * In this case we have to look up the IRQ based on the parent bus,
@@ -1237,20 +1233,20 @@ static int pirq_enable_irq(struct pci_dev *dev)
 			while (irq < 0 && dev->bus->parent) { /* go back to the bridge */
 				struct pci_dev *bridge = dev->bus->self;
 
-				pin = (pin + PCI_SLOT(dev->devfn)) % 4;
+				pin = (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1;
 				irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
-						PCI_SLOT(bridge->devfn), pin);
+						PCI_SLOT(bridge->devfn), pin - 1);
 				if (irq >= 0)
 					dev_warn(&dev->dev, "using bridge %s "
 						 "INT %c to get IRQ %d\n",
-						 pci_name(bridge), 'A' + pin,
+						 pci_name(bridge), 'A' + pin - 1,
 						 irq);
 				dev = bridge;
 			}
 			dev = temp_dev;
 			if (irq >= 0) {
 				dev_info(&dev->dev, "PCI->APIC IRQ transform: "
-					 "INT %c -> IRQ %d\n", 'A' + pin, irq);
+					 "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
 				dev->irq = irq;
 				return 0;
 			} else
@@ -1269,7 +1265,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
 			return 0;
 
 		dev_warn(&dev->dev, "can't find IRQ for PCI INT %c%s\n",
-			 'A' + pin, msg);
+			 'A' + pin - 1, msg);
 	}
 	return 0;
 }
#4 lore raw

PATCH 4/12 x86/PCI: minor logic simplications

In reply to Bjorn Helgaas

Test "pin" immediately to simplify the subsequent code.

---
 arch/x86/pci/irq.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)
arch/x86/pci/irq.c +4 -4
index 5d1ce1c..6547497 100644
@@ -1042,6 +1042,9 @@ static void __init pcibios_fixup_irqs(void)
 	dev = NULL;
 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+		if (!pin)
+			continue;
+
 #ifdef CONFIG_X86_IO_APIC
 		/*
 		 * Recalculate IRQ numbers if we use the I/O APIC.
@@ -1049,9 +1052,6 @@ static void __init pcibios_fixup_irqs(void)
 		if (io_apic_assign_pci_irqs) {
 			int irq;
 
-			if (!pin)
-				continue;
-
 			/*
 			 * interrupt pins are numbered starting from 1
 			 */
@@ -1092,7 +1092,7 @@ static void __init pcibios_fixup_irqs(void)
 		/*
 		 * Still no IRQ? Try to lookup one...
 		 */
-		if (pin && !dev->irq)
+		if (!dev->irq)
 			pcibios_lookup_irq(dev, 0);
 	}
 }
#5 lore raw

PATCH 5/12 PCI: add pci_swizzle_interrupt_pin()

In reply to Bjorn Helgaas

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.

---
 drivers/pci/pci.c   |    8 +++++++-
 include/linux/pci.h |    1 +
 2 files changed, 8 insertions(+), 1 deletions(-)
drivers/pci/pci.c +7 -1
index 46f6821..5a882cc 100644
@@ -1337,6 +1337,12 @@ void pci_enable_ari(struct pci_dev *dev)
 	bridge->ari_enabled = 1;
 }
 
+u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin)
+{
+	/* This implements Table 9-1 of the PCI-to-PCI bridge spec */
+	return (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1;
+}
+
 int
 pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)
 {
@@ -1347,7 +1353,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;
include/linux/pci.h +1 -0
index feb4657..4be596f 100644
@@ -527,6 +527,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);
#6 lore raw

Re: [PATCH 05/12] PCI: add pci_swizzle_interrupt_pin()

drivers/pci/pci.c void pci_enable_ari(struct pci_dev *dev) · line 1345

Quoted 7 lines · Bjorn Helgaas
drivers/pci/pci.c +6 -0
+u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin)
+{
+	/* This implements Table 9-1 of the PCI-to-PCI bridge spec */
+	return (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1;
+}
+

Can you please add a banner comment to this function that gives at least a quick description of what this function is meant to do? Feel free to use kerneldoc.

Saying table X of document Y isn't immediately helpful.

David

#7 lore raw

Re: [PATCH 05/12] PCI: add pci_swizzle_interrupt_pin()

Quoted 13 lines · David Howells

Review

Quoted 7 lines · Bjorn Helgaas
(quoted diff) +6 -0
+u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin)
+{
+	/* This implements Table 9-1 of the PCI-to-PCI bridge spec */
+	return (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1;
+}
+

Can you please add a banner comment to this function that gives at least a quick description of what this function is meant to do? Feel free to use kerneldoc.

I'm not really a fan of comments that are bigger than the code and add little or no information, but if you like the following better, use it instead :-)

PCI: add pci_swizzle_interrupt_pin()

From: Bjorn Helgaas <[email protected]>

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.

---
 drivers/pci/pci.c   |   17 ++++++++++++++++-
 include/linux/pci.h |    1 +
 2 files changed, 17 insertions(+), 1 deletions(-)
drivers/pci/pci.c +16 -1
index 46f6821..c14a6b6 100644
@@ -1337,6 +1337,21 @@ 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)
+ *
+ * The PCI-to-PCI bridge specification requires INTx swizzling for
+ * devices behind bridges on add-in cards.  This performs the swizzle
+ * for one level of bridge.
+ */
+u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin)
+{
+	/* This implements Table 9-1 of the PCI-to-PCI bridge spec */
+	return (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1;
+}
+
 int
 pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)
 {
@@ -1347,7 +1362,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;
include/linux/pci.h +1 -0
index feb4657..4be596f 100644
@@ -527,6 +527,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);
#8 lore raw

Re: [PATCH 05/12] PCI: add pci_swizzle_interrupt_pin()

Quoted 9 lines · Bjorn Helgaas

+/**
+ * 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)
+ *
+ * The PCI-to-PCI bridge specification requires INTx swizzling for
+ * devices behind bridges on add-in cards. This performs the swizzle
+ * for one level of bridge.
+ */

Better.

drivers/pci/pci.c void pci_enable_ari(struct pci_dev *dev) · line 1351

Quoted 3 lines
drivers/pci/pci.c +3 -0
+u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin)
+{
+	/* This implements Table 9-1 of the PCI-to-PCI bridge spec */

I'd recommend merging this comment into the banner.

drivers/pci/pci.c void pci_enable_ari(struct pci_dev *dev) · line 1354

Quoted 3 lines
drivers/pci/pci.c +3 -0
+	return (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1;
+}
+

David

#9 lore raw

Re: [PATCH 05/12] PCI: add pci_swizzle_interrupt_pin()

Quoted 12 lines · David Howells
Quoted 9 lines · Bjorn Helgaas

+/**
+ * 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)
+ *
+ * The PCI-to-PCI bridge specification requires INTx swizzling for
+ * devices behind bridges on add-in cards. This performs the swizzle
+ * for one level of bridge.
+ */

Quoted 7 lines

Better.

Review

Quoted 3 lines
(quoted diff) +3 -0
+u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin)
+{
+	/* This implements Table 9-1 of the PCI-to-PCI bridge spec */

I'd recommend merging this comment into the banner.

OK. How's this? I suck at writing comments.

PCI: add pci_swizzle_interrupt_pin()

From: Bjorn Helgaas <[email protected]>

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.

---
 drivers/pci/pci.c   |   16 +++++++++++++++-
 include/linux/pci.h |    1 +
 2 files changed, 16 insertions(+), 1 deletions(-)
drivers/pci/pci.c +15 -1
index 46f6821..dfa26d1 100644
@@ -1337,6 +1337,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)
+ *
+ * The PCI-to-PCI bridge specification, section 9.1, requires INTx swizzling
+ * for devices behind bridges on add-in cards.  This performs the swizzle
+ * for one level of bridge.
+ */
+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)
 {
@@ -1347,7 +1361,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;
include/linux/pci.h +1 -0
index feb4657..4be596f 100644
@@ -527,6 +527,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);
#10 lore raw

Re: [PATCH 05/12] PCI: add pci_swizzle_interrupt_pin()

Quoted 9 lines · Bjorn Helgaas

+/**
+ * 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)
+ *
+ * The PCI-to-PCI bridge specification, section 9.1, requires INTx swizzling
+ * for devices behind bridges on add-in cards. This performs the swizzle
+ * for one level of bridge.
+ */

That's okay. It might be better to put the what before the why, though:

* 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.

David

#11 lore raw

Re: [PATCH 05/12] PCI: add pci_swizzle_interrupt_pin()

Quoted 12 lines · David Howells
Quoted 9 lines · Bjorn Helgaas

+/**
+ * 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)
+ *
+ * The PCI-to-PCI bridge specification, section 9.1, requires INTx swizzling
+ * for devices behind bridges on add-in cards. This performs the swizzle
+ * for one level of bridge.
+ */

Quoted 5 lines

That's okay. It might be better to put the what before the why, though:

* 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.

That *is* much better. Thanks for the wordsmithing.

PCI: add pci_swizzle_interrupt_pin()

From: Bjorn Helgaas <[email protected]>

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.

---
 drivers/pci/pci.c   |   16 +++++++++++++++-
 include/linux/pci.h |    1 +
 2 files changed, 16 insertions(+), 1 deletions(-)
drivers/pci/pci.c +15 -1
index 46f6821..388a32a 100644
@@ -1337,6 +1337,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)
 {
@@ -1347,7 +1361,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;
include/linux/pci.h +1 -0
index feb4657..4be596f 100644
@@ -527,6 +527,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);
#12 lore raw

PATCH 6/12 PCI: alpha: use generic pci_swizzle_interrupt_pin()

In reply to Bjorn Helgaas

Use the generic pci_swizzle_interrupt_pin() instead of arch-specific code.

---
 arch/alpha/kernel/pci.c          |    2 +-
 arch/alpha/kernel/pci_impl.h     |    9 ++-------
 arch/alpha/kernel/sys_dp264.c    |    2 +-
 arch/alpha/kernel/sys_eiger.c    |    2 +-
 arch/alpha/kernel/sys_miata.c    |    2 +-
 arch/alpha/kernel/sys_noritake.c |    2 +-
 arch/alpha/kernel/sys_ruffian.c  |    2 +-
 arch/alpha/kernel/sys_sable.c    |    2 +-
 8 files changed, 9 insertions(+), 14 deletions(-)
arch/alpha/kernel/pci.c +1 -1
index ff8cb63..b03d9f4 100644
@@ -328,7 +328,7 @@ common_swizzle(struct pci_dev *dev, u8 *pinp)
 	u8 pin = *pinp;
 
 	while (dev->bus->parent) {
-		pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+		pin = pci_swizzle_interrupt_pin(dev, pin);
 		/* Move up the chain of bridges. */
 		dev = dev->bus->self;
         }
arch/alpha/kernel/pci_impl.h +2 -7
index f8b7499..7336651 100644
@@ -106,16 +106,11 @@ struct pci_iommu_arena;
  *   Where A = pin 1, B = pin 2 and so on and pin=0 = default = A.
  *   Thus, each swizzle is ((pin-1) + (device#-4)) % 4
  *
- *   The following code swizzles for exactly one bridge.  The routine
+ *   pci_swizzle_interrupt_pin() swizzles for exactly one bridge.  The routine
  *   common_swizzle below handles multiple bridges.  But there are a
- *   couple boards that do strange things, so we define this here.
+ *   couple boards that do strange things.
  */
 
-static inline u8 bridge_swizzle(u8 pin, u8 slot) 
-{
-	return (((pin-1) + slot) % 4) + 1;
-}
-
 
 /* The following macro is used to implement the table-based irq mapping
    function for all single-bus Alphas.  */
arch/alpha/kernel/sys_dp264.c +1 -1
index c71b0fd..1d707a7 100644
@@ -481,7 +481,7 @@ monet_swizzle(struct pci_dev *dev, u8 *pinp)
 				slot = PCI_SLOT(dev->devfn);
 				break;
 			}
-			pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)) ;
+			pin = pci_swizzle_interrupt_pin(dev, pin);
 
 			/* Move up the chain of bridges.  */
 			dev = dev->bus->self;
arch/alpha/kernel/sys_eiger.c +1 -1
index 7ef3b6f..baf60f3 100644
@@ -204,7 +204,7 @@ eiger_swizzle(struct pci_dev *dev, u8 *pinp)
 			break;
 		}
 		/* Must be a card-based bridge.  */
-		pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+		pin = pci_swizzle_interrupt_pin(dev, pin);
 
 		/* Move up the chain of bridges.  */
 		dev = dev->bus->self;
arch/alpha/kernel/sys_miata.c +1 -1
index 910b43c..61ccd95 100644
@@ -219,7 +219,7 @@ miata_swizzle(struct pci_dev *dev, u8 *pinp)
 				slot = PCI_SLOT(dev->devfn) + 9;
 				break;
 			}
-			pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+			pin = pci_swizzle_interrupt_pin(dev, pin);
 
 			/* Move up the chain of bridges.  */
 			dev = dev->bus->self;
arch/alpha/kernel/sys_noritake.c +1 -1
index eb2a1d6..538876b 100644
@@ -257,7 +257,7 @@ noritake_swizzle(struct pci_dev *dev, u8 *pinp)
 				slot = PCI_SLOT(dev->devfn) + 15;
 				break;
 			}
-			pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)) ;
+			pin = pci_swizzle_interrupt_pin(dev, pin);
 
 			/* Move up the chain of bridges.  */
 			dev = dev->bus->self;
arch/alpha/kernel/sys_ruffian.c +1 -1
index 5b99cf3..f15a329 100644
@@ -160,7 +160,7 @@ ruffian_swizzle(struct pci_dev *dev, u8 *pinp)
 				slot = PCI_SLOT(dev->devfn) + 10;
 				break;
 			}
-			pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+			pin = pci_swizzle_interrupt_pin(dev, pin);
 
 			/* Move up the chain of bridges.  */
 			dev = dev->bus->self;
arch/alpha/kernel/sys_sable.c +1 -1
index a4555f4..d232e42 100644
@@ -425,7 +425,7 @@ lynx_swizzle(struct pci_dev *dev, u8 *pinp)
 				slot = PCI_SLOT(dev->devfn) + 11;
 				break;
 			}
-			pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)) ;
+			pin = pci_swizzle_interrupt_pin(dev, pin);
 
 			/* Move up the chain of bridges.  */
 			dev = dev->bus->self;
#13 lore raw

PATCH 7/12 PCI: arm: use generic pci_swizzle_interrupt_pin()

In reply to Bjorn Helgaas

Use the generic pci_swizzle_interrupt_pin() instead of arch-specific code.

---
 arch/arm/kernel/bios32.c       |    6 +++---
 arch/arm/mach-integrator/pci.c |   11 ++---------
 2 files changed, 5 insertions(+), 12 deletions(-)
arch/arm/kernel/bios32.c +3 -3
index 17a59b6..5c5a0bc 100644
@@ -491,17 +491,17 @@ EXPORT_SYMBOL(pcibios_bus_to_resource);
  */
 u8 __devinit pci_std_swizzle(struct pci_dev *dev, u8 *pinp)
 {
-	int pin = *pinp - 1;
+	int pin = *pinp;
 
 	while (dev->bus->self) {
-		pin = (pin + PCI_SLOT(dev->devfn)) & 3;
+		pin = pci_swizzle_interrupt_pin(dev, pin);
 		/*
 		 * move up the chain of bridges,
 		 * swizzling as we go.
 		 */
 		dev = dev->bus->self;
 	}
-	*pinp = pin + 1;
+	*pinp = pin;
 
 	return PCI_SLOT(dev->devfn);
 }
arch/arm/mach-integrator/pci.c +2 -9
index af7d3ff..2fdb954 100644
@@ -63,13 +63,7 @@
  *
  * Where A = pin 1, B = pin 2 and so on and pin=0 = default = A.
  * Thus, each swizzle is ((pin-1) + (device#-4)) % 4
- *
- * The following code swizzles for exactly one bridge.  
  */
-static inline int bridge_swizzle(int pin, unsigned int slot) 
-{
-	return (pin + slot) & 3;
-}
 
 /*
  * This routine handles multiple bridges.
@@ -81,15 +75,14 @@ static u8 __init integrator_swizzle(struct pci_dev *dev, u8 *pinp)
 	if (pin == 0)
 		pin = 1;
 
-	pin -= 1;
 	while (dev->bus->self) {
-		pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+		pin = pci_swizzle_interrupt_pin(dev, pin);
 		/*
 		 * move up the chain of bridges, swizzling as we go.
 		 */
 		dev = dev->bus->self;
 	}
-	*pinp = pin + 1;
+	*pinp = pin;
 
 	return PCI_SLOT(dev->devfn);
 }
#14 lore raw

PATCH 8/12 PCI: mips: use generic pci_swizzle_interrupt_pin()

In reply to Bjorn Helgaas

Use the generic pci_swizzle_interrupt_pin() instead of arch-specific code.

---
 arch/mips/pci/pci-ip27.c |    6 ------
 arch/mips/pci/pci.c      |    9 +--------
 2 files changed, 1 insertions(+), 14 deletions(-)
arch/mips/pci/pci-ip27.c +0 -6
index f97ab14..dda6f20 100644
@@ -146,12 +146,6 @@ int __devinit pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 	return 0;
 }
 
-/* Most MIPS systems have straight-forward swizzling needs.  */
-static inline u8 bridge_swizzle(u8 pin, u8 slot)
-{
-	return (((pin - 1) + slot) % 4) + 1;
-}
-
 static inline struct pci_dev *bridge_root_dev(struct pci_dev *dev)
 {
 	while (dev->bus->parent) {
arch/mips/pci/pci.c +1 -8
index a377e9d..dfad63c 100644
@@ -149,19 +149,12 @@ out:
 	       "Skipping PCI bus scan due to resource conflict\n");
 }
 
-/* Most MIPS systems have straight-forward swizzling needs.  */
-
-static inline u8 bridge_swizzle(u8 pin, u8 slot)
-{
-	return (((pin - 1) + slot) % 4) + 1;
-}
-
 static u8 __init common_swizzle(struct pci_dev *dev, u8 *pinp)
 {
 	u8 pin = *pinp;
 
 	while (dev->bus->parent) {
-		pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+		pin = pci_swizzle_interrupt_pin(dev, pin);
 		/* Move up the chain of bridges. */
 		dev = dev->bus->self;
         }
#16 lore raw

PATCH 9/12 PCI: parisc: use generic pci_swizzle_interrupt_pin()

In reply to Bjorn Helgaas

Use the generic pci_swizzle_interrupt_pin() instead of arch-specific code.

---
 drivers/parisc/dino.c    |    4 ++--
 drivers/parisc/iosapic.c |    3 +--
 2 files changed, 3 insertions(+), 4 deletions(-)
drivers/parisc/dino.c +2 -2
index 3bc54b3..77cc8bf 100644
@@ -547,7 +547,7 @@ dino_card_fixup(struct pci_dev *dev)
 	** The additional "-1" adjusts for skewing the IRQ<->slot.
 	*/
 	dino_cfg_read(dev->bus, dev->devfn, PCI_INTERRUPT_PIN, 1, &irq_pin); 
-	dev->irq = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ;
+	dev->irq = pci_swizzle_interrupt_pin(dev, irq_pin) - 1;
 
 	/* Shouldn't really need to do this but it's in case someone tries
 	** to bypass PCI services and look at the card themselves.
@@ -672,7 +672,7 @@ dino_fixup_bus(struct pci_bus *bus)
 			
 			dino_cfg_read(dev->bus, dev->devfn, 
 				      PCI_INTERRUPT_PIN, 1, &irq_pin);
-			irq_pin = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ;
+			irq_pin = pci_swizzle_interrupt_pin(dev, irq_pin) - 1;
 			printk(KERN_WARNING "Device %s has undefined IRQ, "
 					"setting to %d\n", pci_name(dev), irq_pin);
 			dino_cfg_write(dev->bus, dev->devfn, 
drivers/parisc/iosapic.c +1 -2
index 7beffca..f011ff5 100644
@@ -519,8 +519,7 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
 		**
 		** Advantage is it's really easy to implement.
 		*/
-		intr_pin = ((intr_pin-1)+PCI_SLOT(pcidev->devfn)) % 4;
-		intr_pin++;	/* convert back to INTA-D (1-4) */
+		intr_pin = pci_swizzle_interrupt_pin(pcidev, intr_pin);
 #endif /* PCI_BRIDGE_FUNCS */
 
 		/*
#17 lore raw

Re: [PATCH 09/12] PCI: parisc: use generic pci_swizzle_interrupt_pin()

Quoted 3 lines · Bjorn Helgaas

Use the generic pci_swizzle_interrupt_pin() instead of arch-specific code.

cool, ack.

#18 lore raw

PATCH 10/12 PCI: powerpc: use generic pci_swizzle_interrupt_pin()

In reply to Bjorn Helgaas

Use the generic pci_swizzle_interrupt_pin() instead of arch-specific code.

---
 arch/powerpc/kernel/prom_parse.c |    7 +------
 1 files changed, 1 insertions(+), 6 deletions(-)
arch/powerpc/kernel/prom_parse.c +1 -6
index a11d689..a377abe 100644
@@ -232,11 +232,6 @@ int of_pci_address_to_resource(struct device_node *dev, int bar,
 }
 EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
 
-static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
-{
-	return (((pin - 1) + slot) % 4) + 1;
-}
-
 int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
 {
 	struct device_node *dn, *ppnode;
@@ -306,7 +301,7 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
 		/* We can only get here if we hit a P2P bridge with no node,
 		 * let's do standard swizzling and try again
 		 */
-		lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
+		lspec = pci_swizzle_interrupt_pin(pdev, lspec);
 		pdev = ppdev;
 	}
 
Acked-by on v1 10/12
#19 lore raw

Re: [PATCH 10/12] PCI: powerpc: use generic pci_swizzle_interrupt_pin()

Quoted 4 lines · Bjorn Helgaas

Use the generic pci_swizzle_interrupt_pin() instead of arch-specific code.

---

Quoted 33 lines
 arch/powerpc/kernel/prom_parse.c |    7 +------
 1 files changed, 1 insertions(+), 6 deletions(-)
arch/powerpc/kernel/prom_parse.c +1 -7
index a11d689..a377abe 100644
@@ -232,11 +232,6 @@ int of_pci_address_to_resource(struct device_node *dev, int bar,
 }
 EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
 
-static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
-{
-	return (((pin - 1) + slot) % 4) + 1;
-}
-
 int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
 {
 	struct device_node *dn, *ppnode;
@@ -306,7 +301,7 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
 		/* We can only get here if we hit a P2P bridge with no node,
 		 * let's do standard swizzling and try again
 		 */
-		lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
+		lspec = pci_swizzle_interrupt_pin(pdev, lspec);
 		pdev = ppdev;
 	}
 
 
--

To unsubscribe from this list: send the line "unsubscribe linux-arch" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#20 lore raw

PATCH 11/12 PCI: sh: use generic pci_swizzle_interrupt_pin()

In reply to Bjorn Helgaas

Use the generic pci_swizzle_interrupt_pin() instead of arch-specific code.

---
 arch/sh/drivers/pci/ops-cayman.c |    9 ++-------
 arch/sh/drivers/pci/pci.c        |    7 +------
 2 files changed, 3 insertions(+), 13 deletions(-)
arch/sh/drivers/pci/ops-cayman.c +2 -7
index 5ccf9ea..38ef762 100644
@@ -5,11 +5,6 @@
 #include <cpu/irq.h>
 #include "pci-sh5.h"
 
-static inline u8 bridge_swizzle(u8 pin, u8 slot)
-{
-	return (((pin - 1) + slot) % 4) + 1;
-}
-
 int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int result = -1;
@@ -42,7 +37,7 @@ int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
 	while (dev->bus->number > 0) {
 
 		slot = path[i].slot = PCI_SLOT(dev->devfn);
-		pin = path[i].pin = bridge_swizzle(pin, slot);
+		pin = path[i].pin = pci_swizzle_interrupt_pin(dev, pin);
 		dev = dev->bus->self;
 		i++;
 		if (i > 3) panic("PCI path to root bus too long!\n");
@@ -56,7 +51,7 @@ int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
 	if ((slot < 3) || (i == 0)) {
 		/* Bus 0 (incl. PCI-PCI bridge itself) : perform the final
 		   swizzle now. */
-		result = IRQ_INTA + bridge_swizzle(pin, slot) - 1;
+		result = IRQ_INTA + pci_swizzle_interrupt_pin(dev, pin) - 1;
 	} else {
 		i--;
 		slot = path[i].slot;
arch/sh/drivers/pci/pci.c +1 -6
index d3839e6..aea3b6b 100644
@@ -21,17 +21,12 @@
 #include <linux/init.h>
 #include <asm/io.h>
 
-static inline u8 bridge_swizzle(u8 pin, u8 slot)
-{
-	return (((pin - 1) + slot) % 4) + 1;
-}
-
 static u8 __init simple_swizzle(struct pci_dev *dev, u8 *pinp)
 {
 	u8 pin = *pinp;
 
 	while (dev->bus->parent) {
-		pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+		pin = pci_swizzle_interrupt_pin(dev, pin);
 		/* Move up the chain of bridges. */
 		dev = dev->bus->self;
 	}
#22 lore raw

PATCH 12/12 PCI: x86: use generic pci_swizzle_interrupt_pin()

In reply to Bjorn Helgaas

Use the generic pci_swizzle_interrupt_pin() instead of arch-specific code.

---
 arch/x86/pci/irq.c   |    4 ++--
 arch/x86/pci/visws.c |    7 +------
 2 files changed, 3 insertions(+), 8 deletions(-)
arch/x86/pci/irq.c +2 -2
index 6547497..1d6469b 100644
@@ -1069,7 +1069,7 @@ static void __init pcibios_fixup_irqs(void)
 				struct pci_dev *bridge = dev->bus->self;
 				int bus;
 
-				pin = (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1;
+				pin = pci_swizzle_interrupt_pin(dev, pin);
 				bus = bridge->bus->number;
 				irq = IO_APIC_get_PCI_irq_vector(bus,
 						PCI_SLOT(bridge->devfn), pin - 1);
@@ -1233,7 +1233,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
 			while (irq < 0 && dev->bus->parent) { /* go back to the bridge */
 				struct pci_dev *bridge = dev->bus->self;
 
-				pin = (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1;
+				pin = pci_swizzle_interrupt_pin(dev, pin);
 				irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
 						PCI_SLOT(bridge->devfn), pin - 1);
 				if (irq >= 0)
arch/x86/pci/visws.c +1 -6
index 42f4cb1..6b5ed3d 100644
@@ -25,17 +25,12 @@ static void pci_visws_disable_irq(struct pci_dev *dev) { }
 
 unsigned int pci_bus0, pci_bus1;
 
-static inline u8 bridge_swizzle(u8 pin, u8 slot) 
-{
-	return (((pin - 1) + slot) % 4) + 1;
-}
-
 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 = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+		pin = pci_swizzle_interrupt_pin(dev, pin);
 		dev = dev->bus->self;
 	}
 	*pinp = pin;
Applied
#23 lore raw
In reply to Bjorn Helgaas
Quoted 7 lines · Bjorn Helgaas

This series adds a pci_swizzle_interrupt_pin() function in the PCI core. Most architectures currently implement this independently.

After this series, many of the callers of pci_swizzle_interrupt_pin() follow a similar pattern. I'd like to consolidate those callers, too, but I haven't started that yet.

Quoted 5 lines

One strange thing I'd like to understand eventually is why the swizzle in acpi_pci_irq_derive() does something special for CardBus bridges, while no other architecture does.

Comments welcome.

Applied the series to my linux-next branch, thanks a lot for unifying this.

Jesse