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>
This commit is contained in:
Yinghai Lu
2009-05-06 10:10:06 -07:00
committed by Ingo Molnar
parent 5ef2183768
commit b9c61b7007
2 changed files with 110 additions and 136 deletions

View File

@@ -1480,9 +1480,13 @@ static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq
ioapic_write_entry(apic_id, pin, entry);
}
static struct {
DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
} mp_ioapic_routing[MAX_IO_APICS];
static void __init setup_IO_APIC_irqs(void)
{
int apic_id, pin, idx, irq;
int apic_id = 0, pin, idx, irq;
int notcon = 0;
struct irq_desc *desc;
struct irq_cfg *cfg;
@@ -1490,48 +1494,53 @@ static void __init setup_IO_APIC_irqs(void)
apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
for (apic_id = 0; apic_id < nr_ioapics; apic_id++) {
for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
#ifdef CONFIG_ACPI
if (!acpi_disabled && acpi_ioapic) {
apic_id = mp_find_ioapic(0);
if (apic_id < 0)
apic_id = 0;
}
#endif
idx = find_irq_entry(apic_id, pin, mp_INT);
if (idx == -1) {
if (!notcon) {
notcon = 1;
apic_printk(APIC_VERBOSE,
KERN_DEBUG " %d-%d",
mp_ioapics[apic_id].apicid, pin);
} else
apic_printk(APIC_VERBOSE, " %d-%d",
mp_ioapics[apic_id].apicid, pin);
continue;
}
if (notcon) {
for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
idx = find_irq_entry(apic_id, pin, mp_INT);
if (idx == -1) {
if (!notcon) {
notcon = 1;
apic_printk(APIC_VERBOSE,
" (apicid-pin) not connected\n");
notcon = 0;
}
irq = pin_2_irq(idx, apic_id, pin);
/*
* Skip the timer IRQ if there's a quirk handler
* installed and if it returns 1:
*/
if (apic->multi_timer_check &&
apic->multi_timer_check(apic_id, irq))
continue;
desc = irq_to_desc_alloc_node(irq, node);
if (!desc) {
printk(KERN_INFO "can not get irq_desc for %d\n", irq);
continue;
}
cfg = desc->chip_data;
add_pin_to_irq_node(cfg, node, apic_id, pin);
setup_IO_APIC_irq(apic_id, pin, irq, desc,
irq_trigger(idx), irq_polarity(idx));
KERN_DEBUG " %d-%d",
mp_ioapics[apic_id].apicid, pin);
} else
apic_printk(APIC_VERBOSE, " %d-%d",
mp_ioapics[apic_id].apicid, pin);
continue;
}
if (notcon) {
apic_printk(APIC_VERBOSE,
" (apicid-pin) not connected\n");
notcon = 0;
}
irq = pin_2_irq(idx, apic_id, pin);
/*
* Skip the timer IRQ if there's a quirk handler
* installed and if it returns 1:
*/
if (apic->multi_timer_check &&
apic->multi_timer_check(apic_id, irq))
continue;
desc = irq_to_desc_alloc_node(irq, node);
if (!desc) {
printk(KERN_INFO "can not get irq_desc for %d\n", irq);
continue;
}
cfg = desc->chip_data;
add_pin_to_irq_node(cfg, node, apic_id, pin);
set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed);
setup_IO_APIC_irq(apic_id, pin, irq, desc,
irq_trigger(idx), irq_polarity(idx));
}
if (notcon)
@@ -3876,10 +3885,6 @@ static int __io_apic_set_pci_routing(struct device *dev, int ioapic, int pin, in
return 0;
}
static struct {
DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
} mp_ioapic_routing[MAX_IO_APICS];
int io_apic_set_pci_routing(struct device *dev, int ioapic, int pin, int irq,
int triggering, int polarity)
{
@@ -4023,51 +4028,44 @@ int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
#ifdef CONFIG_SMP
void __init setup_ioapic_dest(void)
{
int pin, ioapic, irq, irq_entry;
int pin, ioapic = 0, irq, irq_entry;
struct irq_desc *desc;
struct irq_cfg *cfg;
const struct cpumask *mask;
if (skip_ioapic_setup == 1)
return;
for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
irq_entry = find_irq_entry(ioapic, pin, mp_INT);
if (irq_entry == -1)
continue;
irq = pin_2_irq(irq_entry, ioapic, pin);
/* setup_IO_APIC_irqs could fail to get vector for some device
* when you have too many devices, because at that time only boot
* cpu is online.
*/
desc = irq_to_desc(irq);
cfg = desc->chip_data;
if (!cfg->vector) {
setup_IO_APIC_irq(ioapic, pin, irq, desc,
irq_trigger(irq_entry),
irq_polarity(irq_entry));
continue;
}
/*
* Honour affinities which have been set in early boot
*/
if (desc->status &
(IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
mask = desc->affinity;
else
mask = apic->target_cpus();
if (intr_remapping_enabled)
set_ir_ioapic_affinity_irq_desc(desc, mask);
else
set_ioapic_affinity_irq_desc(desc, mask);
}
#ifdef CONFIG_ACPI
if (!acpi_disabled && acpi_ioapic) {
ioapic = mp_find_ioapic(0);
if (ioapic < 0)
ioapic = 0;
}
#endif
for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
irq_entry = find_irq_entry(ioapic, pin, mp_INT);
if (irq_entry == -1)
continue;
irq = pin_2_irq(irq_entry, ioapic, pin);
desc = irq_to_desc(irq);
/*
* Honour affinities which have been set in early boot
*/
if (desc->status &
(IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
mask = desc->affinity;
else
mask = apic->target_cpus();
if (intr_remapping_enabled)
set_ir_ioapic_affinity_irq_desc(desc, mask);
else
set_ioapic_affinity_irq_desc(desc, mask);
}
}
#endif