patch-2.4.26 linux-2.4.26/drivers/acpi/pci_irq.c

Next file: linux-2.4.26/drivers/acpi/pci_link.c
Previous file: linux-2.4.26/drivers/acpi/parser/psscope.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.25/drivers/acpi/pci_irq.c linux-2.4.26/drivers/acpi/pci_irq.c
@@ -277,7 +277,6 @@
 	return_VALUE(entry->irq);
 }
 
-
 static int
 acpi_pci_irq_derive (
 	struct pci_dev		*dev,
@@ -285,6 +284,7 @@
 {
 	struct pci_dev		*bridge = dev;
 	int			irq = 0;
+	u8			bridge_pin = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_derive");
 
@@ -293,12 +293,28 @@
 
 	/* 
 	 * Attempt to derive an IRQ for this device from a parent bridge's
-	 * PCI interrupt routing entry (a.k.a. the "bridge swizzle").
+	 * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge)
 	 */
 	while (!irq && bridge->bus->self) {
 		pin = (pin + PCI_SLOT(bridge->devfn)) % 4;
 		bridge = bridge->bus->self;
-		irq = acpi_pci_irq_lookup(0, bridge->bus->number, PCI_SLOT(bridge->devfn), pin);
+
+		if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) {
+			/* PC card has the same IRQ as its cardbridge */
+			pci_read_config_byte(bridge, PCI_INTERRUPT_PIN, &bridge_pin);
+			if (!bridge_pin) {
+				ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+					"No interrupt pin configured for device %s\n",
+					pci_name(bridge)));
+				return_VALUE(0);
+			}
+			/* Pin is from 0 to 3 */
+			bridge_pin --;
+			pin = bridge_pin;
+		}
+
+		irq = acpi_pci_irq_lookup(0, bridge->bus->number,
+				PCI_SLOT(bridge->devfn), pin);
 	}
 
 	if (!irq) {
@@ -306,7 +322,8 @@
 		return_VALUE(0);
 	}
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derived IRQ %d\n", irq));
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derive IRQ %d for device %s from %s\n",
+		irq, pci_name(dev), pci_name(bridge)));
 
 	return_VALUE(irq);
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)