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/kernel/apic/io_apic.c | |
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/kernel/apic/io_apic.c')
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 150 |
1 files changed, 74 insertions, 76 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 | ||