Commit f672c392 authored by Bjorn Helgaas's avatar Bjorn Helgaas Committed by Jesse Barnes

x86/PCI: use config space encoding for interrupt pins

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.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: hpa@zytor.com
Signed-off-by: default avatarBjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 878f2e50
...@@ -887,7 +887,6 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) ...@@ -887,7 +887,6 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
dev_dbg(&dev->dev, "no interrupt pin\n"); dev_dbg(&dev->dev, "no interrupt pin\n");
return 0; return 0;
} }
pin = pin - 1;
/* Find IRQ routing entry */ /* Find IRQ routing entry */
...@@ -897,17 +896,17 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) ...@@ -897,17 +896,17 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
info = pirq_get_info(dev); info = pirq_get_info(dev);
if (!info) { if (!info) {
dev_dbg(&dev->dev, "PCI INT %c not found in routing table\n", dev_dbg(&dev->dev, "PCI INT %c not found in routing table\n",
'A' + pin); 'A' + pin - 1);
return 0; return 0;
} }
pirq = info->irq[pin].link; pirq = info->irq[pin - 1].link;
mask = info->irq[pin].bitmap; mask = info->irq[pin - 1].bitmap;
if (!pirq) { 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; return 0;
} }
dev_dbg(&dev->dev, "PCI INT %c -> PIRQ %02x, mask %04x, excl %04x", 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; mask &= pcibios_irq_mask;
/* Work around broken HP Pavilion Notebooks which assign USB to /* Work around broken HP Pavilion Notebooks which assign USB to
...@@ -949,7 +948,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) ...@@ -949,7 +948,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
newirq = i; 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 */ /* Check if it is hardcoded */
if ((pirq & 0xf0) == 0xf0) { if ((pirq & 0xf0) == 0xf0) {
...@@ -977,18 +976,18 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) ...@@ -977,18 +976,18 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
return 0; 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 */ /* Update IRQ for all devices with the same pirq value */
while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) { while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) {
pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin); pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin);
if (!pin) if (!pin)
continue; continue;
pin--;
info = pirq_get_info(dev2); info = pirq_get_info(dev2);
if (!info) if (!info)
continue; continue;
if (info->irq[pin].link == pirq) { if (info->irq[pin - 1].link == pirq) {
/* /*
* We refuse to override the dev->irq * We refuse to override the dev->irq
* information. Give a warning! * information. Give a warning!
...@@ -1055,9 +1054,8 @@ static void __init pcibios_fixup_irqs(void) ...@@ -1055,9 +1054,8 @@ static void __init pcibios_fixup_irqs(void)
/* /*
* interrupt pins are numbered starting from 1 * interrupt pins are numbered starting from 1
*/ */
pin--;
irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, 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 * Busses behind bridges are typically not listed in the
* MP-table. In this case we have to look up the IRQ * MP-table. In this case we have to look up the IRQ
...@@ -1070,22 +1068,22 @@ static void __init pcibios_fixup_irqs(void) ...@@ -1070,22 +1068,22 @@ static void __init pcibios_fixup_irqs(void)
struct pci_dev *bridge = dev->bus->self; struct pci_dev *bridge = dev->bus->self;
int bus; int bus;
pin = (pin + PCI_SLOT(dev->devfn)) % 4; pin = (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1;
bus = bridge->bus->number; bus = bridge->bus->number;
irq = IO_APIC_get_PCI_irq_vector(bus, irq = IO_APIC_get_PCI_irq_vector(bus,
PCI_SLOT(bridge->devfn), pin); PCI_SLOT(bridge->devfn), pin - 1);
if (irq >= 0) if (irq >= 0)
dev_warn(&dev->dev, dev_warn(&dev->dev,
"using bridge %s INT %c to " "using bridge %s INT %c to "
"get IRQ %d\n", "get IRQ %d\n",
pci_name(bridge), pci_name(bridge),
'A' + pin, irq); 'A' + pin - 1, irq);
} }
if (irq >= 0) { if (irq >= 0) {
dev_info(&dev->dev, dev_info(&dev->dev,
"PCI->APIC IRQ transform: INT %c " "PCI->APIC IRQ transform: INT %c "
"-> IRQ %d\n", "-> IRQ %d\n",
'A' + pin, irq); 'A' + pin - 1, irq);
dev->irq = irq; dev->irq = irq;
} }
} }
...@@ -1220,12 +1218,10 @@ static int pirq_enable_irq(struct pci_dev *dev) ...@@ -1220,12 +1218,10 @@ static int pirq_enable_irq(struct pci_dev *dev)
if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) { if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
char *msg = ""; char *msg = "";
pin--; /* interrupt pins are numbered starting from 1 */
if (io_apic_assign_pci_irqs) { if (io_apic_assign_pci_irqs) {
int irq; 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. * 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, * In this case we have to look up the IRQ based on the parent bus,
...@@ -1236,20 +1232,20 @@ static int pirq_enable_irq(struct pci_dev *dev) ...@@ -1236,20 +1232,20 @@ static int pirq_enable_irq(struct pci_dev *dev)
while (irq < 0 && dev->bus->parent) { /* go back to the bridge */ while (irq < 0 && dev->bus->parent) { /* go back to the bridge */
struct pci_dev *bridge = dev->bus->self; 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, irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
PCI_SLOT(bridge->devfn), pin); PCI_SLOT(bridge->devfn), pin - 1);
if (irq >= 0) if (irq >= 0)
dev_warn(&dev->dev, "using bridge %s " dev_warn(&dev->dev, "using bridge %s "
"INT %c to get IRQ %d\n", "INT %c to get IRQ %d\n",
pci_name(bridge), 'A' + pin, pci_name(bridge), 'A' + pin - 1,
irq); irq);
dev = bridge; dev = bridge;
} }
dev = temp_dev; dev = temp_dev;
if (irq >= 0) { if (irq >= 0) {
dev_info(&dev->dev, "PCI->APIC IRQ transform: " 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; dev->irq = irq;
return 0; return 0;
} else } else
...@@ -1268,7 +1264,7 @@ static int pirq_enable_irq(struct pci_dev *dev) ...@@ -1268,7 +1264,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
return 0; return 0;
dev_warn(&dev->dev, "can't find IRQ for PCI INT %c%s\n", dev_warn(&dev->dev, "can't find IRQ for PCI INT %c%s\n",
'A' + pin, msg); 'A' + pin - 1, msg);
} }
return 0; return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment