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 | |
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>
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 150 | ||||
-rw-r--r-- | arch/x86/pci/irq.c | 84 |
2 files changed, 104 insertions, 130 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 3a68daee0d99..5d5f4120c743 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -1480,9 +1480,13 @@ static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq | |||
1480 | ioapic_write_entry(apic_id, pin, entry); | 1480 | ioapic_write_entry(apic_id, pin, entry); |
1481 | } | 1481 | } |
1482 | 1482 | ||
1483 | static struct { | ||
1484 | DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1); | ||
1485 | } mp_ioapic_routing[MAX_IO_APICS]; | ||
1486 | |||
1483 | static void __init setup_IO_APIC_irqs(void) | 1487 | static void __init setup_IO_APIC_irqs(void) |
1484 | { | 1488 | { |
1485 | int apic_id, pin, idx, irq; | 1489 | int apic_id = 0, pin, idx, irq; |
1486 | int notcon = 0; | 1490 | int notcon = 0; |
1487 | struct irq_desc *desc; | 1491 | struct irq_desc *desc; |
1488 | struct irq_cfg *cfg; | 1492 | struct irq_cfg *cfg; |
@@ -1490,48 +1494,53 @@ static void __init setup_IO_APIC_irqs(void) | |||
1490 | 1494 | ||
1491 | apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); | 1495 | apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); |
1492 | 1496 | ||
1493 | for (apic_id = 0; apic_id < nr_ioapics; apic_id++) { | 1497 | #ifdef CONFIG_ACPI |
1494 | for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) { | 1498 | if (!acpi_disabled && acpi_ioapic) { |
1495 | 1499 | apic_id = mp_find_ioapic(0); | |
1496 | idx = find_irq_entry(apic_id, pin, mp_INT); | 1500 | if (apic_id < 0) |
1497 | if (idx == -1) { | 1501 | apic_id = 0; |
1498 | if (!notcon) { | 1502 | } |
1499 | notcon = 1; | 1503 | #endif |
1500 | apic_printk(APIC_VERBOSE, | ||
1501 | KERN_DEBUG " %d-%d", | ||
1502 | mp_ioapics[apic_id].apicid, pin); | ||
1503 | } else | ||
1504 | apic_printk(APIC_VERBOSE, " %d-%d", | ||
1505 | mp_ioapics[apic_id].apicid, pin); | ||
1506 | continue; | ||
1507 | } | ||
1508 | if (notcon) { | ||
1509 | apic_printk(APIC_VERBOSE, | ||
1510 | " (apicid-pin) not connected\n"); | ||
1511 | notcon = 0; | ||
1512 | } | ||
1513 | 1504 | ||
1514 | irq = pin_2_irq(idx, apic_id, pin); | 1505 | for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) { |
1506 | idx = find_irq_entry(apic_id, pin, mp_INT); | ||
1507 | if (idx == -1) { | ||
1508 | if (!notcon) { | ||
1509 | notcon = 1; | ||
1510 | apic_printk(APIC_VERBOSE, | ||
1511 | KERN_DEBUG " %d-%d", | ||
1512 | mp_ioapics[apic_id].apicid, pin); | ||
1513 | } else | ||
1514 | apic_printk(APIC_VERBOSE, " %d-%d", | ||
1515 | mp_ioapics[apic_id].apicid, pin); | ||
1516 | continue; | ||
1517 | } | ||
1518 | if (notcon) { | ||
1519 | apic_printk(APIC_VERBOSE, | ||
1520 | " (apicid-pin) not connected\n"); | ||
1521 | notcon = 0; | ||
1522 | } | ||
1515 | 1523 | ||
1516 | /* | 1524 | irq = pin_2_irq(idx, apic_id, pin); |
1517 | * Skip the timer IRQ if there's a quirk handler | ||
1518 | * installed and if it returns 1: | ||
1519 | */ | ||
1520 | if (apic->multi_timer_check && | ||
1521 | apic->multi_timer_check(apic_id, irq)) | ||
1522 | continue; | ||
1523 | 1525 | ||
1524 | desc = irq_to_desc_alloc_node(irq, node); | 1526 | /* |
1525 | if (!desc) { | 1527 | * Skip the timer IRQ if there's a quirk handler |
1526 | printk(KERN_INFO "can not get irq_desc for %d\n", irq); | 1528 | * installed and if it returns 1: |
1527 | continue; | 1529 | */ |
1528 | } | 1530 | if (apic->multi_timer_check && |
1529 | cfg = desc->chip_data; | 1531 | apic->multi_timer_check(apic_id, irq)) |
1530 | add_pin_to_irq_node(cfg, node, apic_id, pin); | 1532 | continue; |
1531 | 1533 | ||
1532 | setup_IO_APIC_irq(apic_id, pin, irq, desc, | 1534 | desc = irq_to_desc_alloc_node(irq, node); |
1533 | irq_trigger(idx), irq_polarity(idx)); | 1535 | if (!desc) { |
1536 | printk(KERN_INFO "can not get irq_desc for %d\n", irq); | ||
1537 | continue; | ||
1534 | } | 1538 | } |
1539 | cfg = desc->chip_data; | ||
1540 | add_pin_to_irq_node(cfg, node, apic_id, pin); | ||
1541 | set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed); | ||
1542 | setup_IO_APIC_irq(apic_id, pin, irq, desc, | ||
1543 | irq_trigger(idx), irq_polarity(idx)); | ||
1535 | } | 1544 | } |
1536 | 1545 | ||
1537 | if (notcon) | 1546 | if (notcon) |
@@ -3876,10 +3885,6 @@ static int __io_apic_set_pci_routing(struct device *dev, int ioapic, int pin, in | |||
3876 | return 0; | 3885 | return 0; |
3877 | } | 3886 | } |
3878 | 3887 | ||
3879 | static struct { | ||
3880 | DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1); | ||
3881 | } mp_ioapic_routing[MAX_IO_APICS]; | ||
3882 | |||
3883 | int io_apic_set_pci_routing(struct device *dev, int ioapic, int pin, int irq, | 3888 | int io_apic_set_pci_routing(struct device *dev, int ioapic, int pin, int irq, |
3884 | int triggering, int polarity) | 3889 | int triggering, int polarity) |
3885 | { | 3890 | { |
@@ -4023,51 +4028,44 @@ int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity) | |||
4023 | #ifdef CONFIG_SMP | 4028 | #ifdef CONFIG_SMP |
4024 | void __init setup_ioapic_dest(void) | 4029 | void __init setup_ioapic_dest(void) |
4025 | { | 4030 | { |
4026 | int pin, ioapic, irq, irq_entry; | 4031 | int pin, ioapic = 0, irq, irq_entry; |
4027 | struct irq_desc *desc; | 4032 | struct irq_desc *desc; |
4028 | struct irq_cfg *cfg; | ||
4029 | const struct cpumask *mask; | 4033 | const struct cpumask *mask; |
4030 | 4034 | ||
4031 | if (skip_ioapic_setup == 1) | 4035 | if (skip_ioapic_setup == 1) |
4032 | return; | 4036 | return; |
4033 | 4037 | ||
4034 | for (ioapic = 0; ioapic < nr_ioapics; ioapic++) { | 4038 | #ifdef CONFIG_ACPI |
4035 | for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) { | 4039 | if (!acpi_disabled && acpi_ioapic) { |
4036 | irq_entry = find_irq_entry(ioapic, pin, mp_INT); | 4040 | ioapic = mp_find_ioapic(0); |
4037 | if (irq_entry == -1) | 4041 | if (ioapic < 0) |
4038 | continue; | 4042 | ioapic = 0; |
4039 | irq = pin_2_irq(irq_entry, ioapic, pin); | 4043 | } |
4040 | 4044 | #endif | |
4041 | /* setup_IO_APIC_irqs could fail to get vector for some device | ||
4042 | * when you have too many devices, because at that time only boot | ||
4043 | * cpu is online. | ||
4044 | */ | ||
4045 | desc = irq_to_desc(irq); | ||
4046 | cfg = desc->chip_data; | ||
4047 | if (!cfg->vector) { | ||
4048 | setup_IO_APIC_irq(ioapic, pin, irq, desc, | ||
4049 | irq_trigger(irq_entry), | ||
4050 | irq_polarity(irq_entry)); | ||
4051 | continue; | ||
4052 | 4045 | ||
4053 | } | 4046 | for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) { |
4047 | irq_entry = find_irq_entry(ioapic, pin, mp_INT); | ||
4048 | if (irq_entry == -1) | ||
4049 | continue; | ||
4050 | irq = pin_2_irq(irq_entry, ioapic, pin); | ||
4054 | 4051 | ||
4055 | /* | 4052 | desc = irq_to_desc(irq); |
4056 | * Honour affinities which have been set in early boot | ||
4057 | */ | ||
4058 | if (desc->status & | ||
4059 | (IRQ_NO_BALANCING | IRQ_AFFINITY_SET)) | ||
4060 | mask = desc->affinity; | ||
4061 | else | ||
4062 | mask = apic->target_cpus(); | ||
4063 | 4053 | ||
4064 | if (intr_remapping_enabled) | 4054 | /* |
4065 | set_ir_ioapic_affinity_irq_desc(desc, mask); | 4055 | * Honour affinities which have been set in early boot |
4066 | else | 4056 | */ |
4067 | set_ioapic_affinity_irq_desc(desc, mask); | 4057 | if (desc->status & |
4068 | } | 4058 | (IRQ_NO_BALANCING | IRQ_AFFINITY_SET)) |
4059 | mask = desc->affinity; | ||
4060 | else | ||
4061 | mask = apic->target_cpus(); | ||
4069 | 4062 | ||
4063 | if (intr_remapping_enabled) | ||
4064 | set_ir_ioapic_affinity_irq_desc(desc, mask); | ||
4065 | else | ||
4066 | set_ioapic_affinity_irq_desc(desc, mask); | ||
4070 | } | 4067 | } |
4068 | |||
4071 | } | 4069 | } |
4072 | #endif | 4070 | #endif |
4073 | 4071 | ||
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 |