Commit eb5ef7e6 authored by Andrew Morton's avatar Andrew Morton Committed by Dave Jones

[PATCH] Fix noirqbalance

Patch from Zwane Mwaikambo <zwane@linuxpower.ca>

This patch fixes what seems to have been a longstanding bug. Ever since we
moved cpu bringup later into the boot process, we end up programming the
ioapics before we have any of our possible cpus in the cpu_online_map.
Therefore leading to the following current situation;

For walmart-smp, bigsmp and summit we set the logical destination for cpu
to TARGET_CPUS which can depend on the cpu_online_map, so what you would
normally see with noirqbalance would be all interrupts handled on cpu0
since at that stage no other cpu apart from the BSP is online.

You can check for this by looking at the ioredtbls at boottime for a two
way system;

.... IRQ redirection table:
 NR Log Phy Mask Trig IRR Pol Stat Dest Deli Vect:
 00 000 00  1    0    0   0   0    0    0    00
 01 001 01  0    0    0   0   0    1    1    39
 02 001 01  0    0    0   0   0    1    1    31
 03 001 01  0    0    0   0   0    1    1    41
 04 001 01  0    0    0   0   0    1    1    49
 05 001 01  0    0    0   0   0    1    1    51
 06 001 01  0    0    0   0   0    1    1    59

Notice that 'Log' is set to 1 instead of 3.

This patch will simply reprogram all the ioredtbls to handle the other
online cpus.

Patch tested on my 2way P2-400 and a 16way NUMAQ both with noirqbalance.
It will not affect the irqbalance case because we are simply setting
TARGET_CPUS which is done anyway.

before:
  CPU0       CPU1
  0:    1495632          0    IO-APIC-edge  timer
  1:       4270          0    IO-APIC-edge  i8042
  2:          0          0          XT-PIC  cascade
  8:          1          0    IO-APIC-edge  rtc
 12:      83592          0    IO-APIC-edge  i8042
 14:      93791          0    IO-APIC-edge  ide0
 15:     103167          0    IO-APIC-edge  ide1
 17:    1396088          0   IO-APIC-level  EMU10K1, eth0
 18:      56125          0   IO-APIC-level  aic7xxx, aic7xxx
 19:       2258          0   IO-APIC-level  uhci-hcd, eth1, serial
NMI:          0          0
LOC:    1495566    1497133

after:
           CPU0       CPU1
  0:    1046157    1015670    IO-APIC-edge  timer
  1:       4923       4173    IO-APIC-edge  i8042
  2:          0          0          XT-PIC  cascade
  8:          1          0    IO-APIC-edge  rtc
 12:      48596      48968    IO-APIC-edge  i8042
 14:       4238       3416    IO-APIC-edge  ide0
 15:      25362      31525    IO-APIC-edge  ide1
 17:       3757       4014   IO-APIC-level  EMU10K1, eth0
 18:        335        366   IO-APIC-level  aic7xxx, aic7xxx
 19:       1052        908   IO-APIC-level  uhci-hcd, eth1
NMI:          0          0
LOC:    2061856    2061893
parent 7c08ac42
...@@ -742,6 +742,30 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) ...@@ -742,6 +742,30 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
return best_guess; return best_guess;
} }
/*
* This function currently is only a helper for the i386 smp boot process where
* we need to reprogram the ioredtbls to cater for the cpus which have come online
* so mask in all cases should simply be TARGET_CPUS
*/
void __init setup_ioapic_dest (unsigned long mask)
{
int pin, ioapic, irq, irq_entry;
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);
set_ioapic_affinity(irq, mask);
}
}
}
/* /*
* EISA Edge/Level control register, ELCR * EISA Edge/Level control register, ELCR
*/ */
......
...@@ -1155,6 +1155,7 @@ int __devinit __cpu_up(unsigned int cpu) ...@@ -1155,6 +1155,7 @@ int __devinit __cpu_up(unsigned int cpu)
void __init smp_cpus_done(unsigned int max_cpus) void __init smp_cpus_done(unsigned int max_cpus)
{ {
setup_ioapic_dest(TARGET_CPUS);
zap_low_mappings(); zap_low_mappings();
} }
......
...@@ -56,6 +56,7 @@ extern void disable_IO_APIC(void); ...@@ -56,6 +56,7 @@ extern void disable_IO_APIC(void);
extern void print_IO_APIC(void); extern void print_IO_APIC(void);
extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn); extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
extern void send_IPI(int dest, int vector); extern void send_IPI(int dest, int vector);
extern void setup_ioapic_dest(unsigned long mask);
extern unsigned long io_apic_irqs; extern unsigned long io_apic_irqs;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment