Skip to content

Commit

Permalink
[PATCH] x86-64: check vector in setup_ioapic_dest to verify if need s…
Browse files Browse the repository at this point in the history
…etup_IO_APIC_irq

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.  So check vector
for irq in setup_ioapic_dest and call setup_IO_APIC_irq to make sure IO-APIC
irq-routing table is initialized.

Also seperate setup_IO_APIC_irq from setup_IO_APIC_irqs.

Signed-off-by: Yinghai Lu <yinghai.lu@amd.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Cc: Andi Kleen <ak@suse.de>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
  • Loading branch information
Yinghai Lu authored and Andi Kleen committed Dec 7, 2006
1 parent f6ca808 commit ad892f5
Showing 1 changed file with 61 additions and 43 deletions.
104 changes: 61 additions & 43 deletions arch/x86_64/kernel/io_apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -789,27 +789,65 @@ static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
handle_edge_irq, "edge");
}
}

static void __init setup_IO_APIC_irqs(void)
static void __init setup_IO_APIC_irq(int apic, int pin, int idx, int irq)
{
struct IO_APIC_route_entry entry;
int apic, pin, idx, irq, first_notcon = 1, vector;
int vector;
unsigned long flags;

apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");

for (apic = 0; apic < nr_ioapics; apic++) {
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
/*
* add it to the IO-APIC irq-routing table:
*/
memset(&entry,0,sizeof(entry));

/*
* add it to the IO-APIC irq-routing table:
*/
memset(&entry,0,sizeof(entry));
entry.delivery_mode = INT_DELIVERY_MODE;
entry.dest_mode = INT_DEST_MODE;
entry.mask = 0; /* enable IRQ */
entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);

entry.trigger = irq_trigger(idx);
entry.polarity = irq_polarity(idx);

entry.delivery_mode = INT_DELIVERY_MODE;
entry.dest_mode = INT_DEST_MODE;
entry.mask = 0; /* enable IRQ */
if (irq_trigger(idx)) {
entry.trigger = 1;
entry.mask = 1;
entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
}

if (!apic && !IO_APIC_IRQ(irq))
return;

if (IO_APIC_IRQ(irq)) {
cpumask_t mask;
vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
if (vector < 0)
return;

entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
entry.vector = vector;

ioapic_register_intr(irq, vector, IOAPIC_AUTO);
if (!apic && (irq < 16))
disable_8259A_irq(irq);
}

ioapic_write_entry(apic, pin, entry);

spin_lock_irqsave(&ioapic_lock, flags);
set_native_irq_info(irq, TARGET_CPUS);
spin_unlock_irqrestore(&ioapic_lock, flags);

}

static void __init setup_IO_APIC_irqs(void)
{
int apic, pin, idx, irq, first_notcon = 1;

apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");

for (apic = 0; apic < nr_ioapics; apic++) {
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {

idx = find_irq_entry(apic,pin,mp_INT);
if (idx == -1) {
Expand All @@ -821,39 +859,11 @@ static void __init setup_IO_APIC_irqs(void)
continue;
}

entry.trigger = irq_trigger(idx);
entry.polarity = irq_polarity(idx);

if (irq_trigger(idx)) {
entry.trigger = 1;
entry.mask = 1;
entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
}

irq = pin_2_irq(idx, apic, pin);
add_pin_to_irq(irq, apic, pin);

if (!apic && !IO_APIC_IRQ(irq))
continue;
setup_IO_APIC_irq(apic, pin, idx, irq);

if (IO_APIC_IRQ(irq)) {
cpumask_t mask;
vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
if (vector < 0)
continue;

entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
entry.vector = vector;

ioapic_register_intr(irq, vector, IOAPIC_AUTO);
if (!apic && (irq < 16))
disable_8259A_irq(irq);
}
ioapic_write_entry(apic, pin, entry);

spin_lock_irqsave(&ioapic_lock, flags);
set_native_irq_info(irq, TARGET_CPUS);
spin_unlock_irqrestore(&ioapic_lock, flags);
}
}

Expand Down Expand Up @@ -2139,7 +2149,15 @@ void __init setup_ioapic_dest(void)
if (irq_entry == -1)
continue;
irq = pin_2_irq(irq_entry, ioapic, pin);
set_ioapic_affinity_irq(irq, TARGET_CPUS);

/* 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.
*/
if(!irq_vector[irq])
setup_IO_APIC_irq(ioapic, pin, irq_entry, irq);
else
set_ioapic_affinity_irq(irq, TARGET_CPUS);
}

}
Expand Down

0 comments on commit ad892f5

Please sign in to comment.