diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-10 18:25:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-10 18:25:41 -0400 |
commit | f0d5e12bd42b7173ebbbf59279c867605f859814 (patch) | |
tree | f4018a726ecd2cf520afdf27210bfec1f3181718 /arch/x86/pci | |
parent | 0fea615e526b4b7eff0363ee02d5753e5f924089 (diff) | |
parent | 103428e57be323c3c5545db8ad12667099bc6005 (diff) |
Merge branch 'irq-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'irq-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (76 commits)
x86, apic: Fix dummy apic read operation together with broken MP handling
x86, apic: Restore irqs on fail paths
x86: Print real IOAPIC version for x86-64
x86: enable_update_mptable should be a macro
sparseirq: Allow early irq_desc allocation
x86, io-apic: Don't mark pin_programmed early
x86, irq: don't call mp_config_acpi_gsi() if update_mptable is not enabled
x86, irq: update_mptable needs pci_routeirq
x86: don't call read_apic_id if !cpu_has_apic
x86, apic: introduce io_apic_irq_attr
x86/pci: add 4 more return parameters to IO_APIC_get_PCI_irq_vector(), fix
x86: read apic ID in the !acpi_lapic case
x86: apic: Fixmap apic address even if apic disabled
x86: display extended apic registers with print_local_APIC and cpu_debug code
x86: read apic ID in the !acpi_lapic case
x86: clean up and fix setup_clear/force_cpu_cap handling
x86: apic: Check rev 3 fadt correctly for physical_apic bit
x86/pci: update pirq_enable_irq() to setup io apic routing
x86/acpi: move setup io apic routing out of CONFIG_ACPI scope
x86/pci: add 4 more return parameters to IO_APIC_get_PCI_irq_vector()
...
Diffstat (limited to 'arch/x86/pci')
-rw-r--r-- | arch/x86/pci/irq.c | 84 |
1 files changed, 35 insertions, 49 deletions
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index fecbce6e7d7c..0696d506c4ad 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c | |||
@@ -889,6 +889,9 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) | |||
889 | return 0; | 889 | return 0; |
890 | } | 890 | } |
891 | 891 | ||
892 | if (io_apic_assign_pci_irqs) | ||
893 | return 0; | ||
894 | |||
892 | /* Find IRQ routing entry */ | 895 | /* Find IRQ routing entry */ |
893 | 896 | ||
894 | if (!pirq_table) | 897 | if (!pirq_table) |
@@ -1039,56 +1042,15 @@ static void __init pcibios_fixup_irqs(void) | |||
1039 | pirq_penalty[dev->irq]++; | 1042 | pirq_penalty[dev->irq]++; |
1040 | } | 1043 | } |
1041 | 1044 | ||
1045 | if (io_apic_assign_pci_irqs) | ||
1046 | return; | ||
1047 | |||
1042 | dev = NULL; | 1048 | dev = NULL; |
1043 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | 1049 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { |
1044 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); | 1050 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); |
1045 | if (!pin) | 1051 | if (!pin) |
1046 | continue; | 1052 | continue; |
1047 | 1053 | ||
1048 | #ifdef CONFIG_X86_IO_APIC | ||
1049 | /* | ||
1050 | * Recalculate IRQ numbers if we use the I/O APIC. | ||
1051 | */ | ||
1052 | if (io_apic_assign_pci_irqs) { | ||
1053 | int irq; | ||
1054 | |||
1055 | /* | ||
1056 | * interrupt pins are numbered starting from 1 | ||
1057 | */ | ||
1058 | irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, | ||
1059 | PCI_SLOT(dev->devfn), pin - 1); | ||
1060 | /* | ||
1061 | * Busses behind bridges are typically not listed in the | ||
1062 | * MP-table. In this case we have to look up the IRQ | ||
1063 | * based on the parent bus, parent slot, and pin number. | ||
1064 | * The SMP code detects such bridged busses itself so we | ||
1065 | * should get into this branch reliably. | ||
1066 | */ | ||
1067 | if (irq < 0 && dev->bus->parent) { | ||
1068 | /* go back to the bridge */ | ||
1069 | struct pci_dev *bridge = dev->bus->self; | ||
1070 | int bus; | ||
1071 | |||
1072 | pin = pci_swizzle_interrupt_pin(dev, pin); | ||
1073 | bus = bridge->bus->number; | ||
1074 | irq = IO_APIC_get_PCI_irq_vector(bus, | ||
1075 | PCI_SLOT(bridge->devfn), pin - 1); | ||
1076 | if (irq >= 0) | ||
1077 | dev_warn(&dev->dev, | ||
1078 | "using bridge %s INT %c to " | ||
1079 | "get IRQ %d\n", | ||
1080 | pci_name(bridge), | ||
1081 | 'A' + pin - 1, irq); | ||
1082 | } | ||
1083 | if (irq >= 0) { | ||
1084 | dev_info(&dev->dev, | ||
1085 | "PCI->APIC IRQ transform: INT %c " | ||
1086 | "-> IRQ %d\n", | ||
1087 | 'A' + pin - 1, irq); | ||
1088 | dev->irq = irq; | ||
1089 | } | ||
1090 | } | ||
1091 | #endif | ||
1092 | /* | 1054 | /* |
1093 | * Still no IRQ? Try to lookup one... | 1055 | * Still no IRQ? Try to lookup one... |
1094 | */ | 1056 | */ |
@@ -1183,6 +1145,19 @@ int __init pcibios_irq_init(void) | |||
1183 | pcibios_enable_irq = pirq_enable_irq; | 1145 | pcibios_enable_irq = pirq_enable_irq; |
1184 | 1146 | ||
1185 | pcibios_fixup_irqs(); | 1147 | pcibios_fixup_irqs(); |
1148 | |||
1149 | if (io_apic_assign_pci_irqs && pci_routeirq) { | ||
1150 | struct pci_dev *dev = NULL; | ||
1151 | /* | ||
1152 | * PCI IRQ routing is set up by pci_enable_device(), but we | ||
1153 | * also do it here in case there are still broken drivers that | ||
1154 | * don't use pci_enable_device(). | ||
1155 | */ | ||
1156 | printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n"); | ||
1157 | for_each_pci_dev(dev) | ||
1158 | pirq_enable_irq(dev); | ||
1159 | } | ||
1160 | |||
1186 | return 0; | 1161 | return 0; |
1187 | } | 1162 | } |
1188 | 1163 | ||
@@ -1213,16 +1188,23 @@ void pcibios_penalize_isa_irq(int irq, int active) | |||
1213 | static int pirq_enable_irq(struct pci_dev *dev) | 1188 | static int pirq_enable_irq(struct pci_dev *dev) |
1214 | { | 1189 | { |
1215 | u8 pin; | 1190 | u8 pin; |
1216 | struct pci_dev *temp_dev; | ||
1217 | 1191 | ||
1218 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); | 1192 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); |
1219 | if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) { | 1193 | if (pin && !pcibios_lookup_irq(dev, 1)) { |
1220 | char *msg = ""; | 1194 | char *msg = ""; |
1221 | 1195 | ||
1196 | if (!io_apic_assign_pci_irqs && dev->irq) | ||
1197 | return 0; | ||
1198 | |||
1222 | if (io_apic_assign_pci_irqs) { | 1199 | if (io_apic_assign_pci_irqs) { |
1200 | #ifdef CONFIG_X86_IO_APIC | ||
1201 | struct pci_dev *temp_dev; | ||
1223 | int irq; | 1202 | int irq; |
1203 | struct io_apic_irq_attr irq_attr; | ||
1224 | 1204 | ||
1225 | irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin - 1); | 1205 | irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, |
1206 | PCI_SLOT(dev->devfn), | ||
1207 | pin - 1, &irq_attr); | ||
1226 | /* | 1208 | /* |
1227 | * Busses behind bridges are typically not listed in the MP-table. | 1209 | * Busses behind bridges are typically not listed in the MP-table. |
1228 | * In this case we have to look up the IRQ based on the parent bus, | 1210 | * In this case we have to look up the IRQ based on the parent bus, |
@@ -1235,7 +1217,8 @@ static int pirq_enable_irq(struct pci_dev *dev) | |||
1235 | 1217 | ||
1236 | pin = pci_swizzle_interrupt_pin(dev, pin); | 1218 | pin = pci_swizzle_interrupt_pin(dev, pin); |
1237 | irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, | 1219 | irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, |
1238 | PCI_SLOT(bridge->devfn), pin - 1); | 1220 | PCI_SLOT(bridge->devfn), |
1221 | pin - 1, &irq_attr); | ||
1239 | if (irq >= 0) | 1222 | if (irq >= 0) |
1240 | dev_warn(&dev->dev, "using bridge %s " | 1223 | dev_warn(&dev->dev, "using bridge %s " |
1241 | "INT %c to get IRQ %d\n", | 1224 | "INT %c to get IRQ %d\n", |
@@ -1245,12 +1228,15 @@ static int pirq_enable_irq(struct pci_dev *dev) | |||
1245 | } | 1228 | } |
1246 | dev = temp_dev; | 1229 | dev = temp_dev; |
1247 | if (irq >= 0) { | 1230 | if (irq >= 0) { |
1231 | io_apic_set_pci_routing(&dev->dev, irq, | ||
1232 | &irq_attr); | ||
1233 | dev->irq = irq; | ||
1248 | dev_info(&dev->dev, "PCI->APIC IRQ transform: " | 1234 | dev_info(&dev->dev, "PCI->APIC IRQ transform: " |
1249 | "INT %c -> IRQ %d\n", 'A' + pin - 1, irq); | 1235 | "INT %c -> IRQ %d\n", 'A' + pin - 1, irq); |
1250 | dev->irq = irq; | ||
1251 | return 0; | 1236 | return 0; |
1252 | } else | 1237 | } else |
1253 | msg = "; probably buggy MP table"; | 1238 | msg = "; probably buggy MP table"; |
1239 | #endif | ||
1254 | } else if (pci_probe & PCI_BIOS_IRQ_SCAN) | 1240 | } else if (pci_probe & PCI_BIOS_IRQ_SCAN) |
1255 | msg = ""; | 1241 | msg = ""; |
1256 | else | 1242 | else |