Skip to content

Commit

Permalink
x86: Distangle ioapic and i8259
Browse files Browse the repository at this point in the history
The proposed Moorestown support patches use an extra feature flag
mechanism to make the ioapic work w/o an i8259. There is a much
simpler solution.

Most i8259 specific functions are already called dependend on the irq
number less than NR_IRQS_LEGACY. Replacing that constant by a
read_mostly variable which can be set to 0 by the platform setup code
allows us to achieve the same without any special feature flags.

That trivial change allows us to proceed with MRST w/o doing a full
blown overhaul of the ioapic code which would delay MRST unduly.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
  • Loading branch information
Thomas Gleixner committed Aug 31, 2009
1 parent 3f4110a commit bc07844
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 12 deletions.
2 changes: 2 additions & 0 deletions arch/x86/include/asm/io_apic.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ extern int noioapicreroute;
/* 1 if the timer IRQ uses the '8259A Virtual Wire' mode */
extern int timer_through_8259;

extern void io_apic_disable_legacy(void);

/*
* If we use the IO-APIC for IRQ routing, disable automatic
* assignment of PCI IRQ's.
Expand Down
41 changes: 29 additions & 12 deletions arch/x86/kernel/apic/io_apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
/* # of MP IRQ source entries */
int mp_irq_entries;

/* Number of legacy interrupts */
static int nr_legacy_irqs __read_mostly = NR_IRQS_LEGACY;
/* GSI interrupts */
static int nr_irqs_gsi = NR_IRQS_LEGACY;

#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
int mp_bus_id_to_type[MAX_MP_BUSSES];
#endif
Expand Down Expand Up @@ -172,6 +177,12 @@ static struct irq_cfg irq_cfgx[NR_IRQS] = {
[15] = { .vector = IRQ15_VECTOR, },
};

void __init io_apic_disable_legacy(void)
{
nr_legacy_irqs = 0;
nr_irqs_gsi = 0;
}

int __init arch_early_irq_init(void)
{
struct irq_cfg *cfg;
Expand All @@ -189,7 +200,7 @@ int __init arch_early_irq_init(void)
desc->chip_data = &cfg[i];
zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node);
zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_NOWAIT, node);
if (i < NR_IRQS_LEGACY)
if (i < nr_legacy_irqs)
cpumask_setall(cfg[i].domain);
}

Expand Down Expand Up @@ -883,7 +894,7 @@ static int __init find_isa_irq_apic(int irq, int type)
*/
static int EISA_ELCR(unsigned int irq)
{
if (irq < NR_IRQS_LEGACY) {
if (irq < nr_legacy_irqs) {
unsigned int port = 0x4d0 + (irq >> 3);
return (inb(port) >> (irq & 7)) & 1;
}
Expand Down Expand Up @@ -1480,7 +1491,7 @@ static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq
}

ioapic_register_intr(irq, desc, trigger);
if (irq < NR_IRQS_LEGACY)
if (irq < nr_legacy_irqs)
disable_8259A_irq(irq);

ioapic_write_entry(apic_id, pin, entry);
Expand Down Expand Up @@ -1851,7 +1862,7 @@ __apicdebuginit(void) print_PIC(void)
unsigned int v;
unsigned long flags;

if (apic_verbosity == APIC_QUIET)
if (apic_verbosity == APIC_QUIET || !nr_legacy_irqs)
return;

printk(KERN_DEBUG "\nprinting PIC contents\n");
Expand Down Expand Up @@ -1914,6 +1925,10 @@ void __init enable_IO_APIC(void)
spin_unlock_irqrestore(&ioapic_lock, flags);
nr_ioapic_registers[apic] = reg_01.bits.entries+1;
}

if (!nr_legacy_irqs)
return;

for(apic = 0; apic < nr_ioapics; apic++) {
int pin;
/* See if any of the pins is in ExtINT mode */
Expand Down Expand Up @@ -1968,6 +1983,9 @@ void disable_IO_APIC(void)
*/
clear_IO_APIC();

if (!nr_legacy_irqs)
return;

/*
* If the i8259 is routed through an IOAPIC
* Put that IOAPIC in virtual wire mode
Expand Down Expand Up @@ -2198,7 +2216,7 @@ static unsigned int startup_ioapic_irq(unsigned int irq)
struct irq_cfg *cfg;

spin_lock_irqsave(&ioapic_lock, flags);
if (irq < NR_IRQS_LEGACY) {
if (irq < nr_legacy_irqs) {
disable_8259A_irq(irq);
if (i8259A_irq_pending(irq))
was_pending = 1;
Expand Down Expand Up @@ -2709,7 +2727,7 @@ static inline void init_IO_APIC_traps(void)
* so default to an old-fashioned 8259
* interrupt if we can..
*/
if (irq < NR_IRQS_LEGACY)
if (irq < nr_legacy_irqs)
make_8259A_irq(irq);
else
/* Strange. Oh, well.. */
Expand Down Expand Up @@ -3045,16 +3063,15 @@ static inline void __init check_timer(void)
* the I/O APIC in all cases now. No actual device should request
* it anyway. --macro
*/
#define PIC_IRQS (1 << PIC_CASCADE_IR)
#define PIC_IRQS (1UL << PIC_CASCADE_IR)

void __init setup_IO_APIC(void)
{

/*
* calling enable_IO_APIC() is moved to setup_local_APIC for BP
*/

io_apic_irqs = ~PIC_IRQS;
io_apic_irqs = nr_legacy_irqs ? ~PIC_IRQS : ~0UL;

apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
/*
Expand All @@ -3065,7 +3082,8 @@ void __init setup_IO_APIC(void)
sync_Arb_IDs();
setup_IO_APIC_irqs();
init_IO_APIC_traps();
check_timer();
if (nr_legacy_irqs)
check_timer();
}

/*
Expand Down Expand Up @@ -3166,7 +3184,6 @@ static int __init ioapic_init_sysfs(void)

device_initcall(ioapic_init_sysfs);

static int nr_irqs_gsi = NR_IRQS_LEGACY;
/*
* Dynamic irq allocate and deallocation
*/
Expand Down Expand Up @@ -3907,7 +3924,7 @@ static int __io_apic_set_pci_routing(struct device *dev, int irq,
/*
* IRQs < 16 are already in the irq_2_pin[] map
*/
if (irq >= NR_IRQS_LEGACY) {
if (irq >= nr_legacy_irqs) {
cfg = desc->chip_data;
add_pin_to_irq_node(cfg, node, ioapic, pin);
}
Expand Down

0 comments on commit bc07844

Please sign in to comment.