Skip to content

Commit

Permalink
x86/PCI: use config space encoding for interrupt pins
Browse files Browse the repository at this point in the history
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: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
  • Loading branch information
Bjorn Helgaas authored and Jesse Barnes committed Jan 7, 2009
1 parent 878f2e5 commit f672c39
Showing 1 changed file with 20 additions and 24 deletions.
44 changes: 20 additions & 24 deletions arch/x86/pci/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -887,7 +887,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 */

Expand All @@ -897,17 +896,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
Expand Down Expand Up @@ -949,7 +948,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) {
Expand Down Expand Up @@ -977,18 +976,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!
Expand Down Expand Up @@ -1055,9 +1054,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
Expand All @@ -1070,22 +1068,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;
}
}
Expand Down Expand Up @@ -1220,12 +1218,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,
Expand All @@ -1236,20 +1232,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
Expand All @@ -1268,7 +1264,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;
}

0 comments on commit f672c39

Please sign in to comment.