Commit f29bd1ba authored by Ingo Molnar's avatar Ingo Molnar Committed by Linus Torvalds

[PATCH] genirq: convert the x86_64 architecture to irq-chips

This patch converts all the x86_64 PIC controllers layers to the new and
simpler irq-chip interrupt handling layer.

[mingo@elte.hu: The patch also enables the fasteoi handler for x86_64]
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Roland Dreier <rolandd@cisco.com>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 0271eb94
...@@ -121,42 +121,15 @@ void (*interrupt[NR_IRQS])(void) = { ...@@ -121,42 +121,15 @@ void (*interrupt[NR_IRQS])(void) = {
* moves to arch independent land * moves to arch independent land
*/ */
DEFINE_SPINLOCK(i8259A_lock);
static int i8259A_auto_eoi; static int i8259A_auto_eoi;
DEFINE_SPINLOCK(i8259A_lock);
static void end_8259A_irq (unsigned int irq)
{
if (irq > 256) {
char var;
printk("return %p stack %p ti %p\n", __builtin_return_address(0), &var, task_thread_info(current));
BUG();
}
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) &&
irq_desc[irq].action)
enable_8259A_irq(irq);
}
#define shutdown_8259A_irq disable_8259A_irq
static void mask_and_ack_8259A(unsigned int); static void mask_and_ack_8259A(unsigned int);
static unsigned int startup_8259A_irq(unsigned int irq) static struct irq_chip i8259A_chip = {
{ .name = "XT-PIC",
enable_8259A_irq(irq); .mask = disable_8259A_irq,
return 0; /* never anything pending */ .unmask = enable_8259A_irq,
} .mask_ack = mask_and_ack_8259A,
static struct hw_interrupt_type i8259A_irq_type = {
.typename = "XT-PIC",
.startup = startup_8259A_irq,
.shutdown = shutdown_8259A_irq,
.enable = enable_8259A_irq,
.disable = disable_8259A_irq,
.ack = mask_and_ack_8259A,
.end = end_8259A_irq,
}; };
/* /*
...@@ -231,7 +204,7 @@ void make_8259A_irq(unsigned int irq) ...@@ -231,7 +204,7 @@ void make_8259A_irq(unsigned int irq)
{ {
disable_irq_nosync(irq); disable_irq_nosync(irq);
io_apic_irqs &= ~(1<<irq); io_apic_irqs &= ~(1<<irq);
irq_desc[irq].chip = &i8259A_irq_type; set_irq_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
enable_irq(irq); enable_irq(irq);
} }
...@@ -367,9 +340,9 @@ void init_8259A(int auto_eoi) ...@@ -367,9 +340,9 @@ void init_8259A(int auto_eoi)
* in AEOI mode we just have to mask the interrupt * in AEOI mode we just have to mask the interrupt
* when acking. * when acking.
*/ */
i8259A_irq_type.ack = disable_8259A_irq; i8259A_chip.mask_ack = disable_8259A_irq;
else else
i8259A_irq_type.ack = mask_and_ack_8259A; i8259A_chip.mask_ack = mask_and_ack_8259A;
udelay(100); /* wait for 8259A to initialize */ udelay(100); /* wait for 8259A to initialize */
...@@ -464,12 +437,13 @@ void __init init_ISA_irqs (void) ...@@ -464,12 +437,13 @@ void __init init_ISA_irqs (void)
/* /*
* 16 old-style INTA-cycle interrupts: * 16 old-style INTA-cycle interrupts:
*/ */
irq_desc[i].chip = &i8259A_irq_type; set_irq_chip_and_handler(i, &i8259A_chip,
handle_level_irq);
} else { } else {
/* /*
* 'high' PCI IRQs filled in on demand * 'high' PCI IRQs filled in on demand
*/ */
irq_desc[i].chip = &no_irq_type; irq_desc[i].chip = &no_irq_chip;
} }
} }
} }
......
...@@ -633,8 +633,8 @@ next: ...@@ -633,8 +633,8 @@ next:
} }
extern void (*interrupt[NR_IRQS])(void); extern void (*interrupt[NR_IRQS])(void);
static struct hw_interrupt_type ioapic_level_type;
static struct hw_interrupt_type ioapic_edge_type; static struct irq_chip ioapic_chip;
#define IOAPIC_AUTO -1 #define IOAPIC_AUTO -1
#define IOAPIC_EDGE 0 #define IOAPIC_EDGE 0
...@@ -648,9 +648,11 @@ static void ioapic_register_intr(int irq, int vector, unsigned long trigger) ...@@ -648,9 +648,11 @@ static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
trigger == IOAPIC_LEVEL) trigger == IOAPIC_LEVEL)
irq_desc[idx].chip = &ioapic_level_type; set_irq_chip_and_handler(idx, &ioapic_chip,
handle_fasteoi_irq);
else else
irq_desc[idx].chip = &ioapic_edge_type; set_irq_chip_and_handler(idx, &ioapic_chip,
handle_edge_irq);
set_intr_gate(vector, interrupt[idx]); set_intr_gate(vector, interrupt[idx]);
} }
...@@ -752,7 +754,7 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in ...@@ -752,7 +754,7 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in
* The timer IRQ doesn't have to know that behind the * The timer IRQ doesn't have to know that behind the
* scene we have a 8259A-master in AEOI mode ... * scene we have a 8259A-master in AEOI mode ...
*/ */
irq_desc[0].chip = &ioapic_edge_type; set_irq_chip_and_handler(0, &ioapic_chip, handle_edge_irq);
/* /*
* Add it to the IO-APIC irq-routing table: * Add it to the IO-APIC irq-routing table:
...@@ -1185,7 +1187,7 @@ static int __init timer_irq_works(void) ...@@ -1185,7 +1187,7 @@ static int __init timer_irq_works(void)
* an edge even if it isn't on the 8259A... * an edge even if it isn't on the 8259A...
*/ */
static unsigned int startup_edge_ioapic_irq(unsigned int irq) static unsigned int startup_ioapic_irq(unsigned int irq)
{ {
int was_pending = 0; int was_pending = 0;
unsigned long flags; unsigned long flags;
...@@ -1202,86 +1204,21 @@ static unsigned int startup_edge_ioapic_irq(unsigned int irq) ...@@ -1202,86 +1204,21 @@ static unsigned int startup_edge_ioapic_irq(unsigned int irq)
return was_pending; return was_pending;
} }
/* static unsigned int startup_ioapic_vector(unsigned int vector)
* Once we have recorded IRQ_PENDING already, we can mask the
* interrupt for real. This prevents IRQ storms from unhandled
* devices.
*/
static void ack_edge_ioapic_irq(unsigned int irq)
{
move_irq(irq);
if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
== (IRQ_PENDING | IRQ_DISABLED))
mask_IO_APIC_irq(irq);
ack_APIC_irq();
}
/*
* Level triggered interrupts can just be masked,
* and shutting down and starting up the interrupt
* is the same as enabling and disabling them -- except
* with a startup need to return a "was pending" value.
*
* Level triggered interrupts are special because we
* do not touch any IO-APIC register while handling
* them. We ack the APIC in the end-IRQ handler, not
* in the start-IRQ-handler. Protection against reentrance
* from the same interrupt is still provided, both by the
* generic IRQ layer and by the fact that an unacked local
* APIC does not accept IRQs.
*/
static unsigned int startup_level_ioapic_irq (unsigned int irq)
{
unmask_IO_APIC_irq(irq);
return 0; /* don't check for pending */
}
static void end_level_ioapic_irq (unsigned int irq)
{
move_irq(irq);
ack_APIC_irq();
}
#ifdef CONFIG_PCI_MSI
static unsigned int startup_edge_ioapic_vector(unsigned int vector)
{
int irq = vector_to_irq(vector);
return startup_edge_ioapic_irq(irq);
}
static void ack_edge_ioapic_vector(unsigned int vector)
{
int irq = vector_to_irq(vector);
move_native_irq(vector);
ack_edge_ioapic_irq(irq);
}
static unsigned int startup_level_ioapic_vector (unsigned int vector)
{
int irq = vector_to_irq(vector);
return startup_level_ioapic_irq (irq);
}
static void end_level_ioapic_vector (unsigned int vector)
{ {
int irq = vector_to_irq(vector); int irq = vector_to_irq(vector);
move_native_irq(vector); return startup_ioapic_irq(irq);
end_level_ioapic_irq(irq);
} }
static void mask_IO_APIC_vector (unsigned int vector) static void mask_ioapic_vector (unsigned int vector)
{ {
int irq = vector_to_irq(vector); int irq = vector_to_irq(vector);
mask_IO_APIC_irq(irq); mask_IO_APIC_irq(irq);
} }
static void unmask_IO_APIC_vector (unsigned int vector) static void unmask_ioapic_vector (unsigned int vector)
{ {
int irq = vector_to_irq(vector); int irq = vector_to_irq(vector);
...@@ -1298,10 +1235,11 @@ static void set_ioapic_affinity_vector (unsigned int vector, ...@@ -1298,10 +1235,11 @@ static void set_ioapic_affinity_vector (unsigned int vector,
set_ioapic_affinity_irq(irq, cpu_mask); set_ioapic_affinity_irq(irq, cpu_mask);
} }
#endif // CONFIG_SMP #endif // CONFIG_SMP
#endif // CONFIG_PCI_MSI
static int ioapic_retrigger(unsigned int irq) static int ioapic_retrigger_vector(unsigned int vector)
{ {
int irq = vector_to_irq(vector);
send_IPI_self(IO_APIC_VECTOR(irq)); send_IPI_self(IO_APIC_VECTOR(irq));
return 1; return 1;
...@@ -1316,32 +1254,22 @@ static int ioapic_retrigger(unsigned int irq) ...@@ -1316,32 +1254,22 @@ static int ioapic_retrigger(unsigned int irq)
* races. * races.
*/ */
static struct hw_interrupt_type ioapic_edge_type __read_mostly = { static void ack_apic(unsigned int vector)
.typename = "IO-APIC-edge", {
.startup = startup_edge_ioapic, ack_APIC_irq();
.shutdown = shutdown_edge_ioapic, }
.enable = enable_edge_ioapic,
.disable = disable_edge_ioapic,
.ack = ack_edge_ioapic,
.end = end_edge_ioapic,
#ifdef CONFIG_SMP
.set_affinity = set_ioapic_affinity,
#endif
.retrigger = ioapic_retrigger,
};
static struct hw_interrupt_type ioapic_level_type __read_mostly = { static struct irq_chip ioapic_chip __read_mostly = {
.typename = "IO-APIC-level", .name = "IO-APIC",
.startup = startup_level_ioapic, .startup = startup_ioapic_vector,
.shutdown = shutdown_level_ioapic, .mask = mask_ioapic_vector,
.enable = enable_level_ioapic, .unmask = unmask_ioapic_vector,
.disable = disable_level_ioapic, .ack = ack_apic,
.ack = mask_and_ack_level_ioapic, .eoi = ack_apic,
.end = end_level_ioapic,
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
.set_affinity = set_ioapic_affinity, .set_affinity = set_ioapic_affinity_vector,
#endif #endif
.retrigger = ioapic_retrigger, .retrigger = ioapic_retrigger_vector,
}; };
static inline void init_IO_APIC_traps(void) static inline void init_IO_APIC_traps(void)
...@@ -1376,7 +1304,7 @@ static inline void init_IO_APIC_traps(void) ...@@ -1376,7 +1304,7 @@ static inline void init_IO_APIC_traps(void)
make_8259A_irq(irq); make_8259A_irq(irq);
else else
/* Strange. Oh, well.. */ /* Strange. Oh, well.. */
irq_desc[irq].chip = &no_irq_type; irq_desc[irq].chip = &no_irq_chip;
} }
} }
} }
......
...@@ -74,7 +74,8 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -74,7 +74,8 @@ int show_interrupts(struct seq_file *p, void *v)
for_each_online_cpu(j) for_each_online_cpu(j)
seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
#endif #endif
seq_printf(p, " %14s", irq_desc[i].chip->typename); seq_printf(p, " %8s", irq_desc[i].chip->name);
seq_printf(p, "-%s", handle_irq_name(irq_desc[i].handle_irq));
seq_printf(p, " %s", action->name); seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next) for (action=action->next; action; action = action->next)
...@@ -117,7 +118,7 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs) ...@@ -117,7 +118,7 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
#ifdef CONFIG_DEBUG_STACKOVERFLOW #ifdef CONFIG_DEBUG_STACKOVERFLOW
stack_overflow_check(regs); stack_overflow_check(regs);
#endif #endif
__do_IRQ(irq, regs); generic_handle_irq(irq, regs);
irq_exit(); irq_exit();
return 1; return 1;
......
...@@ -19,8 +19,6 @@ ...@@ -19,8 +19,6 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <linux/profile.h> #include <linux/profile.h>
#include <linux/smp.h> #include <linux/smp.h>
struct hw_interrupt_type;
#endif #endif
#define NMI_VECTOR 0x02 #define NMI_VECTOR 0x02
......
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