diff options
author | Yinghai Lu <yinghai@kernel.org> | 2009-05-06 13:10:06 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-05-11 04:35:10 -0400 |
commit | b9c61b70075c87a8612624736faf4a2de5b1ed30 (patch) | |
tree | 40f4ae74461d20be77b4b260e5384fe937bc5bec /arch/x86/pci | |
parent | 5ef2183768bb7d64b85eccbfa1537a61cbefa97c (diff) |
x86/pci: update pirq_enable_irq() to setup io apic routing
So we can set io apic routing only when enabling the device irq.
This is advantageous for IRQ descriptor allocation affinity: if we set up
the IO-APIC entry later, we have a chance to allocate the IRQ descriptor
later and know which device it is on and can set affinity accordingly.
[ Impact: standardize/enhance irq-enabling sequence for mptable irqs ]
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Len Brown <lenb@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
LKML-Reference: <4A01C46E.8000501@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/pci')
-rw-r--r-- | arch/x86/pci/irq.c | 84 |
1 files changed, 30 insertions, 54 deletions
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index a2f6bde9c4eb..2f3e192615c0 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,63 +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 | int ioapic = -1, ioapic_pin = -1; | ||
1055 | int triggering, polarity; | ||
1056 | |||
1057 | /* | ||
1058 | * interrupt pins are numbered starting from 1 | ||
1059 | */ | ||
1060 | irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, | ||
1061 | PCI_SLOT(dev->devfn), pin - 1, | ||
1062 | &ioapic, &ioapic_pin, | ||
1063 | &triggering, &polarity); | ||
1064 | /* | ||
1065 | * Busses behind bridges are typically not listed in the | ||
1066 | * MP-table. In this case we have to look up the IRQ | ||
1067 | * based on the parent bus, parent slot, and pin number. | ||
1068 | * The SMP code detects such bridged busses itself so we | ||
1069 | * should get into this branch reliably. | ||
1070 | */ | ||
1071 | if (irq < 0 && dev->bus->parent) { | ||
1072 | /* go back to the bridge */ | ||
1073 | struct pci_dev *bridge = dev->bus->self; | ||
1074 | int bus; | ||
1075 | |||
1076 | pin = pci_swizzle_interrupt_pin(dev, pin); | ||
1077 | bus = bridge->bus->number; | ||
1078 | irq = IO_APIC_get_PCI_irq_vector(bus, | ||
1079 | PCI_SLOT(bridge->devfn), | ||
1080 | pin - 1, | ||
1081 | &ioapic, &ioapic_pin, | ||
1082 | &triggering, &polarity); | ||
1083 | if (irq >= 0) | ||
1084 | dev_warn(&dev->dev, | ||
1085 | "using bridge %s INT %c to " | ||
1086 | "get IRQ %d\n", | ||
1087 | pci_name(bridge), | ||
1088 | 'A' + pin - 1, irq); | ||
1089 | } | ||
1090 | if (irq >= 0) { | ||
1091 | dev_info(&dev->dev, | ||
1092 | "PCI->APIC IRQ transform: INT %c " | ||
1093 | "-> IRQ %d\n", | ||
1094 | 'A' + pin - 1, irq); | ||
1095 | dev->irq = irq; | ||
1096 | } | ||
1097 | } | ||
1098 | #endif | ||
1099 | /* | 1054 | /* |
1100 | * Still no IRQ? Try to lookup one... | 1055 | * Still no IRQ? Try to lookup one... |
1101 | */ | 1056 | */ |
@@ -1190,6 +1145,19 @@ int __init pcibios_irq_init(void) | |||
1190 | pcibios_enable_irq = pirq_enable_irq; | 1145 | pcibios_enable_irq = pirq_enable_irq; |
1191 | 1146 | ||
1192 | 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 | |||
1193 | return 0; | 1161 | return 0; |
1194 | } | 1162 | } |
1195 | 1163 | ||
@@ -1220,13 +1188,17 @@ void pcibios_penalize_isa_irq(int irq, int active) | |||
1220 | static int pirq_enable_irq(struct pci_dev *dev) | 1188 | static int pirq_enable_irq(struct pci_dev *dev) |
1221 | { | 1189 | { |
1222 | u8 pin; | 1190 | u8 pin; |
1223 | struct pci_dev *temp_dev; | ||
1224 | 1191 | ||
1225 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); | 1192 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); |
1226 | if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) { | 1193 | if (pin && !pcibios_lookup_irq(dev, 1)) { |
1227 | char *msg = ""; | 1194 | char *msg = ""; |
1228 | 1195 | ||
1196 | if (!io_apic_assign_pci_irqs && dev->irq) | ||
1197 | return 0; | ||
1198 | |||
1229 | 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; | ||
1230 | int irq; | 1202 | int irq; |
1231 | int ioapic = -1, ioapic_pin = -1; | 1203 | int ioapic = -1, ioapic_pin = -1; |
1232 | int triggering, polarity; | 1204 | int triggering, polarity; |
@@ -1261,12 +1233,16 @@ static int pirq_enable_irq(struct pci_dev *dev) | |||
1261 | } | 1233 | } |
1262 | dev = temp_dev; | 1234 | dev = temp_dev; |
1263 | if (irq >= 0) { | 1235 | if (irq >= 0) { |
1236 | io_apic_set_pci_routing(&dev->dev, ioapic, | ||
1237 | ioapic_pin, irq, | ||
1238 | triggering, polarity); | ||
1239 | dev->irq = irq; | ||
1264 | dev_info(&dev->dev, "PCI->APIC IRQ transform: " | 1240 | dev_info(&dev->dev, "PCI->APIC IRQ transform: " |
1265 | "INT %c -> IRQ %d\n", 'A' + pin - 1, irq); | 1241 | "INT %c -> IRQ %d\n", 'A' + pin - 1, irq); |
1266 | dev->irq = irq; | ||
1267 | return 0; | 1242 | return 0; |
1268 | } else | 1243 | } else |
1269 | msg = "; probably buggy MP table"; | 1244 | msg = "; probably buggy MP table"; |
1245 | #endif | ||
1270 | } else if (pci_probe & PCI_BIOS_IRQ_SCAN) | 1246 | } else if (pci_probe & PCI_BIOS_IRQ_SCAN) |
1271 | msg = ""; | 1247 | msg = ""; |
1272 | else | 1248 | else |