[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: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas 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: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
0271eb947d
commit
f29bd1ba68
@ -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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
* 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)
|
|||||||
/*
|
/*
|
||||||
* 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:
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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
|
|||||||
* 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)
|
|||||||
* 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)
|
|||||||
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);
|
int irq = vector_to_irq(vector);
|
||||||
|
|
||||||
return startup_edge_ioapic_irq(irq);
|
return startup_ioapic_irq(irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ack_edge_ioapic_vector(unsigned int vector)
|
static void mask_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);
|
|
||||||
|
|
||||||
move_native_irq(vector);
|
|
||||||
end_level_ioapic_irq(irq);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mask_IO_APIC_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,
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
#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 @@
|
|||||||
#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
|
||||||
|
Loading…
Reference in New Issue
Block a user