X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fmips%2Fkernel%2Firq_cpu.c;h=fcc86b96ccf6097d5490dca91002b806936a9b89;hb=refs%2Fheads%2Fvserver;hp=2b936cf1ef70fe6f655cd235260912044a7e6368;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c index 2b936cf1e..fcc86b96c 100644 --- a/arch/mips/kernel/irq_cpu.c +++ b/arch/mips/kernel/irq_cpu.c @@ -3,6 +3,8 @@ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * * Copyright (C) 2001 Ralf Baechle + * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. + * Author: Maciej W. Rozycki * * This file define the irq handler for MIPS CPU interrupts. * @@ -31,88 +33,91 @@ #include #include +#include #include static int mips_cpu_irq_base; static inline void unmask_mips_irq(unsigned int irq) { - clear_c0_cause(0x100 << (irq - mips_cpu_irq_base)); set_c0_status(0x100 << (irq - mips_cpu_irq_base)); + irq_enable_hazard(); } static inline void mask_mips_irq(unsigned int irq) { clear_c0_status(0x100 << (irq - mips_cpu_irq_base)); + irq_disable_hazard(); } -static inline void mips_cpu_irq_enable(unsigned int irq) -{ - unsigned long flags; - - local_irq_save(flags); - unmask_mips_irq(irq); - local_irq_restore(flags); -} +static struct irq_chip mips_cpu_irq_controller = { + .typename = "MIPS", + .ack = mask_mips_irq, + .mask = mask_mips_irq, + .mask_ack = mask_mips_irq, + .unmask = unmask_mips_irq, + .eoi = unmask_mips_irq, +}; -static void mips_cpu_irq_disable(unsigned int irq) -{ - unsigned long flags; +/* + * Basically the same as above but taking care of all the MT stuff + */ - local_irq_save(flags); - mask_mips_irq(irq); - local_irq_restore(flags); -} +#define unmask_mips_mt_irq unmask_mips_irq +#define mask_mips_mt_irq mask_mips_irq -static unsigned int mips_cpu_irq_startup(unsigned int irq) +static unsigned int mips_mt_cpu_irq_startup(unsigned int irq) { - mips_cpu_irq_enable(irq); + unsigned int vpflags = dvpe(); + + clear_c0_cause(0x100 << (irq - mips_cpu_irq_base)); + evpe(vpflags); + unmask_mips_mt_irq(irq); return 0; } -#define mips_cpu_irq_shutdown mips_cpu_irq_disable - /* * While we ack the interrupt interrupts are disabled and thus we don't need * to deal with concurrency issues. Same for mips_cpu_irq_end. */ -static void mips_cpu_irq_ack(unsigned int irq) +static void mips_mt_cpu_irq_ack(unsigned int irq) { - /* Only necessary for soft interrupts */ + unsigned int vpflags = dvpe(); clear_c0_cause(0x100 << (irq - mips_cpu_irq_base)); - - mask_mips_irq(irq); + evpe(vpflags); + mask_mips_mt_irq(irq); } -static void mips_cpu_irq_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - unmask_mips_irq(irq); -} - -static hw_irq_controller mips_cpu_irq_controller = { - "MIPS", - mips_cpu_irq_startup, - mips_cpu_irq_shutdown, - mips_cpu_irq_enable, - mips_cpu_irq_disable, - mips_cpu_irq_ack, - mips_cpu_irq_end, - NULL /* no affinity stuff for UP */ +static struct irq_chip mips_mt_cpu_irq_controller = { + .typename = "MIPS", + .startup = mips_mt_cpu_irq_startup, + .ack = mips_mt_cpu_irq_ack, + .mask = mask_mips_mt_irq, + .mask_ack = mips_mt_cpu_irq_ack, + .unmask = unmask_mips_mt_irq, + .eoi = unmask_mips_mt_irq, }; - void __init mips_cpu_irq_init(int irq_base) { int i; - for (i = irq_base; i < irq_base + 8; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - irq_desc[i].handler = &mips_cpu_irq_controller; - } + /* Mask interrupts. */ + clear_c0_status(ST0_IM); + clear_c0_cause(CAUSEF_IP); + + /* + * Only MT is using the software interrupts currently, so we just + * leave them uninitialized for other processors. + */ + if (cpu_has_mipsmt) + for (i = irq_base; i < irq_base + 2; i++) + set_irq_chip(i, &mips_mt_cpu_irq_controller); + + for (i = irq_base + 2; i < irq_base + 8; i++) + set_irq_chip_and_handler(i, &mips_cpu_irq_controller, + handle_level_irq); mips_cpu_irq_base = irq_base; }