Ralf, The two copies of irq_cpu.c should both in theory and in practice be the same, but for some reason they are not. Here's a patch for 2.4 to bring them to sync. The next step would be a trivial update for 2.6 to make that version the same as these two as well. OK to apply? Maciej -- + Maciej W. Rozycki, Technical University of Gdansk, Poland + +--------------------------------------------------------------+ + e-mail: macro@ds2.pg.gda.pl, PGP key available + patch-mips-2.4.24-pre2-20040116-irq_cpu-0 diff -up --recursive --new-file linux-mips-2.4.24-pre2-20040116.macro/arch/mips/kernel/irq_cpu.c linux-mips-2.4.24-pre2-20040116/arch/mips/kernel/irq_cpu.c --- linux-mips-2.4.24-pre2-20040116.macro/arch/mips/kernel/irq_cpu.c 2003-02-05 03:56:38.000000000 +0000 +++ linux-mips-2.4.24-pre2-20040116/arch/mips/kernel/irq_cpu.c 2004-02-09 22:33:17.000000000 +0000 @@ -2,6 +2,8 @@ * Copyright 2001 MontaVista Software Inc. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * + * Copyright (C) 2001 Ralf Baechle + * * This file define the irq handler for MIPS CPU interrupts. * * This program is free software; you can redistribute it and/or modify it @@ -13,9 +15,12 @@ /* * Almost all MIPS CPUs define 8 interrupt sources. They are typically * level triggered (i.e., cannot be cleared from CPU; must be cleared from - * device). The first two are software interrupts. The last one is - * usually the CPU timer interrupt if counter register is present or, for - * CPUs with an external FPU, by convention it's the FPU exception interrupt. + * device). The first two are software interrupts which we don't really + * use or support. The last one is usually the CPU timer interrupt if + * counter register is present or, for CPUs with an external FPU, by + * convention it's the FPU exception interrupt. + * + * Don't even think about using this on SMP. You have been warned. * * This file exports one global function: * void mips_cpu_irq_init(int irq_base); @@ -26,18 +31,37 @@ #include <asm/irq_cpu.h> #include <asm/mipsregs.h> +#include <asm/system.h> + +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)); +} -static int mips_cpu_irq_base = -1; +static inline void mask_mips_irq(unsigned int irq) +{ + clear_c0_status(0x100 << (irq - mips_cpu_irq_base)); +} -static void mips_cpu_irq_enable(unsigned int irq) +static inline void mips_cpu_irq_enable(unsigned int irq) { - clear_c0_cause( 1 << (irq - mips_cpu_irq_base + 8)); - set_c0_status(1 << (irq - mips_cpu_irq_base + 8)); + unsigned long flags; + + local_irq_save(flags); + unmask_mips_irq(irq); + local_irq_restore(flags); } static void mips_cpu_irq_disable(unsigned int irq) { - clear_c0_status(1 << (irq - mips_cpu_irq_base + 8)); + unsigned long flags; + + local_irq_save(flags); + mask_mips_irq(irq); + local_irq_restore(flags); } static unsigned int mips_cpu_irq_startup(unsigned int irq) @@ -49,21 +73,22 @@ static unsigned int mips_cpu_irq_startup #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) { - /* although we attempt to clear the IP bit in cause register, I think - * usually it is cleared by device (irq source) - */ - clear_c0_cause(1 << (irq - mips_cpu_irq_base + 8)); + /* Only necessary for soft interrupts */ + clear_c0_cause(0x100 << (irq - mips_cpu_irq_base)); - /* disable this interrupt - so that we safe proceed to the handler */ - mips_cpu_irq_disable(irq); + mask_mips_irq(irq); } static void mips_cpu_irq_end(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - mips_cpu_irq_enable(irq); + unmask_mips_irq(irq); } static hw_irq_controller mips_cpu_irq_controller = { diff -up --recursive --new-file linux-mips-2.4.24-pre2-20040116.macro/arch/mips64/kernel/irq_cpu.c linux-mips-2.4.24-pre2-20040116/arch/mips64/kernel/irq_cpu.c --- linux-mips-2.4.24-pre2-20040116.macro/arch/mips64/kernel/irq_cpu.c 2002-12-04 03:56:39.000000000 +0000 +++ linux-mips-2.4.24-pre2-20040116/arch/mips64/kernel/irq_cpu.c 2004-02-09 22:33:36.000000000 +0000 @@ -16,18 +16,20 @@ * Almost all MIPS CPUs define 8 interrupt sources. They are typically * level triggered (i.e., cannot be cleared from CPU; must be cleared from * device). The first two are software interrupts which we don't really - * use or support. The last one is usually cpu timer interrupt if a counter - * register is present. + * use or support. The last one is usually the CPU timer interrupt if + * counter register is present or, for CPUs with an external FPU, by + * convention it's the FPU exception interrupt. * * Don't even think about using this on SMP. You have been warned. * * This file exports one global function: - * mips_cpu_irq_init(u32 irq_base); + * void mips_cpu_irq_init(int irq_base); */ +#include <linux/init.h> #include <linux/interrupt.h> -#include <linux/types.h> #include <linux/kernel.h> +#include <asm/irq_cpu.h> #include <asm/mipsregs.h> #include <asm/system.h> @@ -78,7 +80,7 @@ static unsigned int mips_cpu_irq_startup static void mips_cpu_irq_ack(unsigned int irq) { /* Only necessary for soft interrupts */ - clear_c0_cause(1 << (irq - mips_cpu_irq_base + 8)); + clear_c0_cause(0x100 << (irq - mips_cpu_irq_base)); mask_mips_irq(irq); } @@ -90,7 +92,7 @@ static void mips_cpu_irq_end(unsigned in } static hw_irq_controller mips_cpu_irq_controller = { - "CPU_irq", + "MIPS", mips_cpu_irq_startup, mips_cpu_irq_shutdown, mips_cpu_irq_enable, @@ -101,9 +103,9 @@ static hw_irq_controller mips_cpu_irq_co }; -void mips_cpu_irq_init(u32 irq_base) +void __init mips_cpu_irq_init(int irq_base) { - u32 i; + int i; for (i = irq_base; i < irq_base + 8; i++) { irq_desc[i].status = IRQ_DISABLED;