--- linux-2.6.31.10/arch/mips/metarouter/irq.c 1970-01-01 03:00:00.000000000 +0300 +++ linux-2.6.31.10.new/arch/mips/metarouter/irq.c 2010-04-12 15:54:46.000000000 +0300 @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +asmlinkage void plat_irq_dispatch(void) { + unsigned pending = read_c0_status() & read_c0_cause() & 0xfe00; + + if (pending) + do_IRQ(fls(pending) - 9); +} + +volatile unsigned long virqs; +EXPORT_SYMBOL(virqs); + +static void ack_virq(unsigned int irq) +{ + clear_bit(irq - VIRQ_BASE, &virqs); +} + +static inline void unmask_virq(unsigned int irq) +{ +} + +static inline void mask_virq(unsigned int irq) +{ +} + +static struct irq_chip virq_controller = { + .name = "virq", + .ack = ack_virq, + .unmask = unmask_virq, + .mask = mask_virq, +}; + +static irqreturn_t virq_cascade_irq(int irq, void *dev_id) +{ + unsigned i; + unsigned irqs = virqs; + + for (i = 0; irqs; ++i) { + if (irqs & (1 << i)) { + do_IRQ(i + VIRQ_BASE); + irqs ^= (1 << i); + } + } + return IRQ_HANDLED; +} + +static struct irqaction virq_cascade = { + .handler = virq_cascade_irq, + .name = "virq-cascade", +}; + +static void soft_irq_ack(unsigned int irq) +{ + clear_c0_cause(0x100 << (irq - MIPS_CPU_IRQ_BASE)); +} + +static inline void unmask_soft_irq(unsigned int irq) + { + set_c0_status(0x100 << (irq - MIPS_CPU_IRQ_BASE)); + irq_enable_hazard(); + } + +static inline void mask_soft_irq(unsigned int irq) +{ + clear_c0_status(0x100 << (irq - MIPS_CPU_IRQ_BASE)); + irq_disable_hazard(); +} + +static struct irq_chip soft_irq_controller = { + .name = "SoftIRQ", + .ack = soft_irq_ack, + .unmask = unmask_soft_irq, + .mask = mask_soft_irq, +}; + +void __init arch_init_irq(void) +{ + unsigned i; + + mips_cpu_irq_init(); + + set_irq_chip_and_handler(1, &soft_irq_controller, handle_percpu_irq); + setup_irq(1, &virq_cascade); + + for (i = VIRQ_BASE; i < VIRQ_BASE + 32; ++i) + set_irq_chip_and_handler(i, &virq_controller, handle_edge_irq); +}