diff options
| author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2008-12-09 18:11:51 -0500 |
|---|---|---|
| committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-01-07 14:12:49 -0500 |
| commit | f672c392b9c61bcdfb1247561d404b2c3ed4b0b3 (patch) | |
| tree | e0fbbbbed7d0d444ea7e23d41f8236100b99d1f2 | |
| parent | 878f2e50fd1cfea575cdca5bf019c2175dc64131 (diff) | |
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: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
| -rw-r--r-- | arch/x86/pci/irq.c | 44 |
1 files changed, 20 insertions, 24 deletions
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index 399a172f047d..cc9d5e254060 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c | |||
| @@ -887,7 +887,6 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) | |||
| 887 | dev_dbg(&dev->dev, "no interrupt pin\n"); | 887 | dev_dbg(&dev->dev, "no interrupt pin\n"); |
| 888 | return 0; | 888 | return 0; |
| 889 | } | 889 | } |
| 890 | pin = pin - 1; | ||
| 891 | 890 | ||
| 892 | /* Find IRQ routing entry */ | 891 | /* Find IRQ routing entry */ |
| 893 | 892 | ||
| @@ -897,17 +896,17 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) | |||
| 897 | info = pirq_get_info(dev); | 896 | info = pirq_get_info(dev); |
| 898 | if (!info) { | 897 | if (!info) { |
| 899 | dev_dbg(&dev->dev, "PCI INT %c not found in routing table\n", | 898 | dev_dbg(&dev->dev, "PCI INT %c not found in routing table\n", |
| 900 | 'A' + pin); | 899 | 'A' + pin - 1); |
| 901 | return 0; | 900 | return 0; |
| 902 | } | 901 | } |
| 903 | pirq = info->irq[pin].link; | 902 | pirq = info->irq[pin - 1].link; |
| 904 | mask = info->irq[pin].bitmap; | 903 | mask = info->irq[pin - 1].bitmap; |
| 905 | if (!pirq) { | 904 | if (!pirq) { |
| 906 | dev_dbg(&dev->dev, "PCI INT %c not routed\n", 'A' + pin); | 905 | dev_dbg(&dev->dev, "PCI INT %c not routed\n", 'A' + pin - 1); |
| 907 | return 0; | 906 | return 0; |
| 908 | } | 907 | } |
| 909 | dev_dbg(&dev->dev, "PCI INT %c -> PIRQ %02x, mask %04x, excl %04x", | 908 | dev_dbg(&dev->dev, "PCI INT %c -> PIRQ %02x, mask %04x, excl %04x", |
| 910 | 'A' + pin, pirq, mask, pirq_table->exclusive_irqs); | 909 | 'A' + pin - 1, pirq, mask, pirq_table->exclusive_irqs); |
| 911 | mask &= pcibios_irq_mask; | 910 | mask &= pcibios_irq_mask; |
| 912 | 911 | ||
| 913 | /* Work around broken HP Pavilion Notebooks which assign USB to | 912 | /* 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 | newirq = i; | 948 | newirq = i; |
| 950 | } | 949 | } |
| 951 | } | 950 | } |
| 952 | dev_dbg(&dev->dev, "PCI INT %c -> newirq %d", 'A' + pin, newirq); | 951 | dev_dbg(&dev->dev, "PCI INT %c -> newirq %d", 'A' + pin - 1, newirq); |
| 953 | 952 | ||
| 954 | /* Check if it is hardcoded */ | 953 | /* Check if it is hardcoded */ |
| 955 | if ((pirq & 0xf0) == 0xf0) { | 954 | if ((pirq & 0xf0) == 0xf0) { |
| @@ -977,18 +976,18 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) | |||
| 977 | return 0; | 976 | return 0; |
| 978 | } | 977 | } |
| 979 | } | 978 | } |
| 980 | dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", msg, 'A' + pin, irq); | 979 | dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", msg, 'A' + pin - 1, irq); |
| 981 | 980 | ||
| 982 | /* Update IRQ for all devices with the same pirq value */ | 981 | /* Update IRQ for all devices with the same pirq value */ |
| 983 | while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) { | 982 | while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) { |
| 984 | pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin); | 983 | pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin); |
| 985 | if (!pin) | 984 | if (!pin) |
| 986 | continue; | 985 | continue; |
| 987 | pin--; | 986 | |
| 988 | info = pirq_get_info(dev2); | 987 | info = pirq_get_info(dev2); |
| 989 | if (!info) | 988 | if (!info) |
| 990 | continue; | 989 | continue; |
| 991 | if (info->irq[pin].link == pirq) { | 990 | if (info->irq[pin - 1].link == pirq) { |
| 992 | /* | 991 | /* |
| 993 | * We refuse to override the dev->irq | 992 | * We refuse to override the dev->irq |
| 994 | * information. Give a warning! | 993 | * information. Give a warning! |
| @@ -1055,9 +1054,8 @@ static void __init pcibios_fixup_irqs(void) | |||
| 1055 | /* | 1054 | /* |
| 1056 | * interrupt pins are numbered starting from 1 | 1055 | * interrupt pins are numbered starting from 1 |
| 1057 | */ | 1056 | */ |
| 1058 | pin--; | ||
| 1059 | irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, | 1057 | irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, |
| 1060 | PCI_SLOT(dev->devfn), pin); | 1058 | PCI_SLOT(dev->devfn), pin - 1); |
| 1061 | /* | 1059 | /* |
| 1062 | * Busses behind bridges are typically not listed in the | 1060 | * Busses behind bridges are typically not listed in the |
| 1063 | * MP-table. In this case we have to look up the IRQ | 1061 | * MP-table. In this case we have to look up the IRQ |
| @@ -1070,22 +1068,22 @@ static void __init pcibios_fixup_irqs(void) | |||
| 1070 | struct pci_dev *bridge = dev->bus->self; | 1068 | struct pci_dev *bridge = dev->bus->self; |
| 1071 | int bus; | 1069 | int bus; |
| 1072 | 1070 | ||
| 1073 | pin = (pin + PCI_SLOT(dev->devfn)) % 4; | 1071 | pin = (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1; |
| 1074 | bus = bridge->bus->number; | 1072 | bus = bridge->bus->number; |
| 1075 | irq = IO_APIC_get_PCI_irq_vector(bus, | 1073 | irq = IO_APIC_get_PCI_irq_vector(bus, |
| 1076 | PCI_SLOT(bridge->devfn), pin); | 1074 | PCI_SLOT(bridge->devfn), pin - 1); |
| 1077 | if (irq >= 0) | 1075 | if (irq >= 0) |
| 1078 | dev_warn(&dev->dev, | 1076 | dev_warn(&dev->dev, |
| 1079 | "using bridge %s INT %c to " | 1077 | "using bridge %s INT %c to " |
| 1080 | "get IRQ %d\n", | 1078 | "get IRQ %d\n", |
| 1081 | pci_name(bridge), | 1079 | pci_name(bridge), |
| 1082 | 'A' + pin, irq); | 1080 | 'A' + pin - 1, irq); |
| 1083 | } | 1081 | } |
| 1084 | if (irq >= 0) { | 1082 | if (irq >= 0) { |
| 1085 | dev_info(&dev->dev, | 1083 | dev_info(&dev->dev, |
| 1086 | "PCI->APIC IRQ transform: INT %c " | 1084 | "PCI->APIC IRQ transform: INT %c " |
| 1087 | "-> IRQ %d\n", | 1085 | "-> IRQ %d\n", |
| 1088 | 'A' + pin, irq); | 1086 | 'A' + pin - 1, irq); |
| 1089 | dev->irq = irq; | 1087 | dev->irq = irq; |
| 1090 | } | 1088 | } |
| 1091 | } | 1089 | } |
| @@ -1220,12 +1218,10 @@ static int pirq_enable_irq(struct pci_dev *dev) | |||
| 1220 | if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) { | 1218 | if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) { |
| 1221 | char *msg = ""; | 1219 | char *msg = ""; |
| 1222 | 1220 | ||
| 1223 | pin--; /* interrupt pins are numbered starting from 1 */ | ||
| 1224 | |||
| 1225 | if (io_apic_assign_pci_irqs) { | 1221 | if (io_apic_assign_pci_irqs) { |
| 1226 | int irq; | 1222 | int irq; |
| 1227 | 1223 | ||
| 1228 | irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin); | 1224 | irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin - 1); |
| 1229 | /* | 1225 | /* |
| 1230 | * Busses behind bridges are typically not listed in the MP-table. | 1226 | * Busses behind bridges are typically not listed in the MP-table. |
| 1231 | * In this case we have to look up the IRQ based on the parent bus, | 1227 | * 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 | while (irq < 0 && dev->bus->parent) { /* go back to the bridge */ | 1232 | while (irq < 0 && dev->bus->parent) { /* go back to the bridge */ |
| 1237 | struct pci_dev *bridge = dev->bus->self; | 1233 | struct pci_dev *bridge = dev->bus->self; |
| 1238 | 1234 | ||
| 1239 | pin = (pin + PCI_SLOT(dev->devfn)) % 4; | 1235 | pin = (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1; |
| 1240 | irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, | 1236 | irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, |
| 1241 | PCI_SLOT(bridge->devfn), pin); | 1237 | PCI_SLOT(bridge->devfn), pin - 1); |
| 1242 | if (irq >= 0) | 1238 | if (irq >= 0) |
| 1243 | dev_warn(&dev->dev, "using bridge %s " | 1239 | dev_warn(&dev->dev, "using bridge %s " |
| 1244 | "INT %c to get IRQ %d\n", | 1240 | "INT %c to get IRQ %d\n", |
| 1245 | pci_name(bridge), 'A' + pin, | 1241 | pci_name(bridge), 'A' + pin - 1, |
| 1246 | irq); | 1242 | irq); |
| 1247 | dev = bridge; | 1243 | dev = bridge; |
| 1248 | } | 1244 | } |
| 1249 | dev = temp_dev; | 1245 | dev = temp_dev; |
| 1250 | if (irq >= 0) { | 1246 | if (irq >= 0) { |
| 1251 | dev_info(&dev->dev, "PCI->APIC IRQ transform: " | 1247 | dev_info(&dev->dev, "PCI->APIC IRQ transform: " |
| 1252 | "INT %c -> IRQ %d\n", 'A' + pin, irq); | 1248 | "INT %c -> IRQ %d\n", 'A' + pin - 1, irq); |
| 1253 | dev->irq = irq; | 1249 | dev->irq = irq; |
| 1254 | return 0; | 1250 | return 0; |
| 1255 | } else | 1251 | } else |
| @@ -1268,7 +1264,7 @@ static int pirq_enable_irq(struct pci_dev *dev) | |||
| 1268 | return 0; | 1264 | return 0; |
| 1269 | 1265 | ||
| 1270 | dev_warn(&dev->dev, "can't find IRQ for PCI INT %c%s\n", | 1266 | dev_warn(&dev->dev, "can't find IRQ for PCI INT %c%s\n", |
| 1271 | 'A' + pin, msg); | 1267 | 'A' + pin - 1, msg); |
| 1272 | } | 1268 | } |
| 1273 | return 0; | ||
