diff -Nur linux-2.6.15/arch/mips/aruba/irq.c linux-2.6.15-openwrt/arch/mips/aruba/irq.c
--- linux-2.6.15/arch/mips/aruba/irq.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.15-openwrt/arch/mips/aruba/irq.c 2006-01-10 00:32:32.000000000 +0100
-@@ -0,0 +1,393 @@
+@@ -0,0 +1,429 @@
+/**************************************************************************
+ *
+ * BRIEF MODULE DESCRIPTION
-+ * Interrupt routines for IDT EB434 boards
++ * Interrupt routines for IDT EB434 boards / Atheros boards
++ * Modified by Aruba Networks
+ *
+ * Copyright 2004 IDT Inc. (rischelp@idt.com)
+ *
+};
+
+#define READ_PEND_MERLOT(base) (*((volatile unsigned long *)(0xbc003010)))
-+#define READ_MASK_MERLOT(base) (*((volatile unsigned long *)(0xbc003010 + 4)))
-+#define WRITE_MASK_MERLOT(base, val) ((*((volatile unsigned long *)((0xbc003010) + 4))) = (val))
++#define READ_MASK_MERLOT(base) (*((volatile unsigned long *)(0xbc003014)))
++#define WRITE_MASK_MERLOT(base, val) ((*((volatile unsigned long *)(0xbc003014))) = (val), READ_MASK_MERLOT())
+
+static const intr_group_t intr_group_muscat[NUM_INTR_GROUPS] = {
+ {0x0000efff, (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 0 * IC_GROUP_OFFSET)},
+
+static inline void enable_local_irq(unsigned int ip)
+{
-+ int ipnum = 0x100 << ip;
-+ clear_c0_cause(ipnum);
-+ set_c0_status(ipnum);
++ set_c0_status(0x100 << ip);
++ irq_enable_hazard();
+}
+
+static inline void disable_local_irq(unsigned int ip)
+{
-+ int ipnum = 0x100 << ip;
-+ clear_c0_status(ipnum);
-+}
-+
-+static inline void ack_local_irq(unsigned int ip)
-+{
-+ int ipnum = 0x100 << ip;
-+ clear_c0_cause(ipnum);
++ clear_c0_status(0x100 << ip);
++ irq_disable_hazard();
+}
+
+static void aruba_enable_irq(unsigned int irq_nr)
+{
++ unsigned long flags;
+ int ip = irq_nr - GROUP0_IRQ_BASE;
+ unsigned int group, intr_bit;
+ volatile unsigned int *addr;
++
++
++ local_irq_save(flags);
++
+ if (ip < 0) {
+ enable_local_irq(irq_nr);
+ } else {
+ ip -= (group << 5);
+ intr_bit = 1 << ip;
+
-+ // first enable the IP mapped to this IRQ
-+ enable_local_irq(group_to_ip(group));
-+
+ switch (mips_machtype) {
+ case MACH_ARUBA_AP70:
+ addr = intr_group_muscat[group].base_addr;
-+ // unmask intr within group
+ WRITE_MASK_MUSCAT(addr, READ_MASK_MUSCAT(addr) & ~intr_bit);
+ break;
+ case MACH_ARUBA_AP65:
+ WRITE_MASK_MERLOT(addr, READ_MASK_MERLOT(addr) | intr_bit);
+ break;
+ }
++ enable_local_irq(group_to_ip(group));
+ }
++
++ back_to_back_c0_hazard();
++ local_irq_restore(flags);
++
+}
+
+static void aruba_disable_irq(unsigned int irq_nr)
+{
++ unsigned long flags;
+ int ip = irq_nr - GROUP0_IRQ_BASE;
+ unsigned int group, intr_bit, mask;
+ volatile unsigned int *addr;
+
-+ // calculate group
-+ switch (mips_machtype) {
-+ case MACH_ARUBA_AP70:
-+ group = ip >> 5;
-+ break;
-+ case MACH_ARUBA_AP65:
-+ case MACH_ARUBA_AP60:
-+ default:
-+ group = 0;
-+ break;
-+ }
++ local_irq_save(flags);
+
-+ // calc interrupt bit within group
-+ ip -= group << 5;
-+ intr_bit = 1 << ip;
++ if (ip < 0) {
++ disable_local_irq(irq_nr);
++ } else {
++ // calculate group
++ switch (mips_machtype) {
++ case MACH_ARUBA_AP70:
++ group = ip >> 5;
++ break;
++ case MACH_ARUBA_AP65:
++ case MACH_ARUBA_AP60:
++ default:
++ group = 0;
++ break;
++ }
+
-+ switch (mips_machtype) {
-+ case MACH_ARUBA_AP70:
-+ addr = intr_group_muscat[group].base_addr;
-+ // mask intr within group
-+ mask = READ_MASK_MUSCAT(addr);
-+ mask |= intr_bit;
-+ WRITE_MASK_MUSCAT(addr, mask);
++ // calc interrupt bit within group
++ ip -= group << 5;
++ intr_bit = 1 << ip;
++
++ switch (mips_machtype) {
++ case MACH_ARUBA_AP70:
++ addr = intr_group_muscat[group].base_addr;
++ // mask intr within group
++ mask = READ_MASK_MUSCAT(addr);
++ mask |= intr_bit;
++ WRITE_MASK_MUSCAT(addr, mask);
+
-+ /*
-+ if there are no more interrupts enabled in this
-+ group, disable corresponding IP
-+ */
-+ if (mask == intr_group_muscat[group].mask)
-+ disable_local_irq(group_to_ip(group));
-+ break;
-+ case MACH_ARUBA_AP65:
-+ case MACH_ARUBA_AP60:
-+ default:
-+ addr = intr_group_merlot[group].base_addr;
-+ // mask intr within group
-+ mask = READ_MASK_MERLOT(addr);
-+ mask &= ~intr_bit;
-+ WRITE_MASK_MERLOT(addr, mask);
-+ if (!mask)
-+ disable_local_irq(group_to_ip(group));
-+ break;
++ /*
++ if there are no more interrupts enabled in this
++ group, disable corresponding IP
++ */
++ if (mask == intr_group_muscat[group].mask)
++ disable_local_irq(group_to_ip(group));
++ break;
++ case MACH_ARUBA_AP65:
++ case MACH_ARUBA_AP60:
++ default:
++ addr = intr_group_merlot[group].base_addr;
++ // mask intr within group
++ mask = READ_MASK_MERLOT(addr);
++ mask &= ~intr_bit;
++ if (!mask)
++ disable_local_irq(group_to_ip(group));
++ WRITE_MASK_MERLOT(addr, mask);
++ break;
++ }
+ }
++
++ back_to_back_c0_hazard();
++ local_irq_restore(flags);
+}
+
+static unsigned int startup_irq(unsigned int irq_nr)
+static void shutdown_irq(unsigned int irq_nr)
+{
+ aruba_disable_irq(irq_nr);
-+ return;
+}
+
+static void mask_and_ack_irq(unsigned int irq_nr)
+{
+ aruba_disable_irq(irq_nr);
-+ ack_local_irq(group_to_ip(irq_to_group(irq_nr)));
+}
+
+static void end_irq(unsigned int irq_nr)
+ unsigned int intr_bit, group;
+ volatile unsigned int *addr;
+
++
+ if (irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS)) {
+ printk("warning: end_irq %d did not enable (%x)\n",
+ irq_nr, irq_desc[irq_nr].status);
-+ }
++ /* fall through; enable the interrupt
++ * -- It'll get stuck otherwise
++ */
+
-+ switch (mips_machtype) {
-+ case MACH_ARUBA_AP70:
-+ if (irq_nr == GROUP4_IRQ_BASE + 9) idt_gpio->gpioistat &= 0xfffffdff;
-+ else if (irq_nr == GROUP4_IRQ_BASE + 10) idt_gpio->gpioistat &= 0xfffffbff;
-+ else if (irq_nr == GROUP4_IRQ_BASE + 11) idt_gpio->gpioistat &= 0xfffff7ff;
-+ else if (irq_nr == GROUP4_IRQ_BASE + 12) idt_gpio->gpioistat &= 0xffffefff;
-+
-+ group = ip >> 5;
-+
-+ // calc interrupt bit within group
-+ ip -= (group << 5);
-+ intr_bit = 1 << ip;
-+
-+ // first enable the IP mapped to this IRQ
-+ enable_local_irq(group_to_ip(group));
-+
-+ addr = intr_group_muscat[group].base_addr;
-+ // unmask intr within group
-+ WRITE_MASK_MUSCAT(addr, READ_MASK_MUSCAT(addr) & ~intr_bit);
-+ break;
-+ case MACH_ARUBA_AP65:
-+ case MACH_ARUBA_AP60:
-+ group = 0;
++ }
+
-+ // calc interrupt bit within group
-+ intr_bit = 1 << ip;
++ if (ip<0) {
++ enable_local_irq(irq_nr);
++ } else {
+
-+ // first enable the IP mapped to this IRQ
-+ enable_local_irq(group_to_ip(group));
++ switch (mips_machtype) {
++ case MACH_ARUBA_AP70:
++ if (irq_nr == GROUP4_IRQ_BASE + 9) idt_gpio->gpioistat &= 0xfffffdff;
++ else if (irq_nr == GROUP4_IRQ_BASE + 10) idt_gpio->gpioistat &= 0xfffffbff;
++ else if (irq_nr == GROUP4_IRQ_BASE + 11) idt_gpio->gpioistat &= 0xfffff7ff;
++ else if (irq_nr == GROUP4_IRQ_BASE + 12) idt_gpio->gpioistat &= 0xffffefff;
++
++ group = ip >> 5;
++
++ // calc interrupt bit within group
++ ip -= (group << 5);
++ intr_bit = 1 << ip;
++
++ // first enable the IP mapped to this IRQ
++ enable_local_irq(group_to_ip(group));
++
++ addr = intr_group_muscat[group].base_addr;
++ // unmask intr within group
++ WRITE_MASK_MUSCAT(addr, READ_MASK_MUSCAT(addr) & ~intr_bit);
++ break;
+
-+ addr = intr_group_merlot[group].base_addr;
-+ // unmask intr within group
-+ WRITE_MASK_MERLOT(addr, READ_MASK_MERLOT(addr) | intr_bit);
-+ break;
++ case MACH_ARUBA_AP65:
++ case MACH_ARUBA_AP60:
++ default:
++ group = 0;
++
++ // calc interrupt bit within group
++ intr_bit = 1 << ip;
++
++ // first enable the IP mapped to this IRQ
++ enable_local_irq(group_to_ip(group));
++
++ addr = intr_group_merlot[group].base_addr;
++ // unmask intr within group
++ WRITE_MASK_MERLOT(addr, READ_MASK_MERLOT(addr) | intr_bit);
++ break;
++ }
+ }
+}
+
+static struct hw_interrupt_type aruba_irq_type = {
-+ .typename = "IDT434",
++ .typename = "ARUBA",
+ .startup = startup_irq,
+ .shutdown = shutdown_irq,
+ .enable = aruba_enable_irq,
+ memset(irq_desc, 0, sizeof(irq_desc));
+ set_except_vector(0, idtIRQ);
+
++ set_c0_status(0xFF00);
++
+ for (i = 0; i < RC32434_NR_IRQS; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = NULL;
+ irq_desc[i].handler = &aruba_irq_type;
+ spin_lock_init(&irq_desc[i].lock);
+ }
-+
-+ switch (mips_machtype) {
-+ case MACH_ARUBA_AP70:
-+ break;
-+ case MACH_ARUBA_AP65:
-+ case MACH_ARUBA_AP60:
-+ default:
-+ WRITE_MASK_MERLOT(intr_group_merlot[0].base_addr, 0);
-+ *((volatile unsigned long *)0xbc003014) = 0x10;
-+ break;
-+ }
+}
+
+/* Main Interrupt dispatcher */
+{
+ unsigned int pend, group, ip;
+ volatile unsigned int *addr;
++
++ if(cp0_cause == 0) {
++ printk("INTERRUPT(S) FIRED WHILE MASKED\n");
++#ifdef ARUBA_DEBUG
++ // debuging use -- figure out which interrupt(s) fired
++ cp0_cause = read_c0_cause() & CAUSEF_IP;
++ while (cp0_cause) {
++ unsigned long intr_bit;
++ unsigned int irq_nr;
++ intr_bit = (31 - rc32434_clz(cp0_cause));
++ irq_nr = intr_bit - GROUP0_IRQ_BASE;
++ printk(" ---> MASKED IRQ %d\n",irq_nr);
++ cp0_cause &= ~(1 << intr_bit);
++ }
++#endif
++ return;
++ }
++
+ switch (mips_machtype) {
+ case MACH_ARUBA_AP70:
+ if ((ip = (cp0_cause & 0x7c00))) {
+ case MACH_ARUBA_AP65:
+ case MACH_ARUBA_AP60:
+ default:
-+ if (cp0_cause & 0x4000) {
++ if (cp0_cause & 0x4000) { // 1 << (8 +6) == irq 6
+ // Misc Interrupt
+ group = 0;
+ addr = intr_group_merlot[group].base_addr;
+ pend = READ_PEND_MERLOT(addr);
+ pend &= READ_MASK_MERLOT(addr); // only unmasked interrupts
+ /* handle one misc interrupt at a time */
-+ while (pend) {
-+ unsigned int intr_bit, irq_nr;
-+ intr_bit = pend ^ (pend - 1);
-+ irq_nr = ((31 - rc32434_clz(pend)) + GROUP0_IRQ_BASE);
++ while (pend)
++ {
++ unsigned long intr_bit;
++ unsigned int irq_nr;
++
++ intr_bit = (31 - rc32434_clz(pend));
++ irq_nr = intr_bit + GROUP0_IRQ_BASE;
++
+ do_IRQ(irq_nr, regs);
-+ pend &= ~intr_bit;
++ pend &= ~(1 << intr_bit);
+ }
-+ }
-+ if (cp0_cause & 0x3c00) {
-+ while (cp0_cause) {
-+ unsigned int intr_bit, irq_nr;
-+ intr_bit = cp0_cause ^ (cp0_cause - 1);
-+ irq_nr = ((31 - rc32434_clz(cp0_cause)) - GROUP0_IRQ_BASE);
++ } else if (cp0_cause & 0x3c00) { // irq 2-5
++ while (cp0_cause)
++ {
++ unsigned long intr_bit;
++ unsigned int irq_nr;
++
++ intr_bit = (31 - rc32434_clz(cp0_cause));
++ irq_nr = intr_bit - GROUP0_IRQ_BASE;
++
+ do_IRQ(irq_nr, regs);
-+ cp0_cause &= ~intr_bit;
++ cp0_cause &= ~(1 << intr_bit);
+ }
+ }
+ break;