patch-2.2.18 linux/arch/ppc/kernel/open_pic.c
Next file: linux/arch/ppc/kernel/open_pic.h
Previous file: linux/arch/ppc/kernel/misc.S
Back to the patch index
Back to the overall index
- Lines: 150
- Date:
Wed Nov 8 23:00:34 2000
- Orig file:
v2.2.17/arch/ppc/kernel/open_pic.c
- Orig date:
Fri Apr 21 12:45:47 2000
diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.17/arch/ppc/kernel/open_pic.c linux/arch/ppc/kernel/open_pic.c
@@ -1,48 +1,126 @@
+/*
+ * open_pic.c
+ *
+ * Common support routines for platforms with an OpenPIC interrupt controller
+ *
+ */
+
#include <linux/stddef.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/openpic.h>
#include <asm/irq.h>
+#include <asm/processor.h>
#include "open_pic.h"
#include "i8259.h"
-#ifdef __SMP__
-void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
-{
- smp_message_recv(cpl-OPENPIC_VEC_IPI);
-}
-#endif /* __SMP__ */
+extern volatile unsigned char *chrp_int_ack_special;
-void chrp_mask_and_ack_irq(unsigned int irq_nr)
+void open_pic_do_IRQ(struct pt_regs *regs, int cpu, int isfake)
{
- if ((_machine != _MACH_gemini) && is_8259_irq(irq_nr))
- i8259_pic.mask_and_ack(irq_nr);
-}
+ int irq;
+ int openpic_eoi_done = 0;
-static void chrp_mask_irq(unsigned int irq_nr)
-{
- if ((_machine != _MACH_gemini) && is_8259_irq(irq_nr))
- i8259_pic.disable(irq_nr);
+#ifdef __SMP__
+ {
+ unsigned int loops = 1000000;
+ while (test_bit(0, &global_irq_lock)) {
+ if (smp_processor_id() == global_irq_holder) {
+ printk("uh oh, interrupt while we hold global irq lock!\n");
+#ifdef CONFIG_XMON
+ xmon(0);
+#endif
+ break;
+ }
+ if (loops-- == 0) {
+ printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
+#ifdef CONFIG_XMON
+ xmon(0);
+#endif
+ }
+ }
+ }
+#endif /* __SMP__ */
+
+ irq = openpic_irq(smp_processor_id());
+ /* make sure open_pic.irq_offset is set to something!
+ * do we really need the _MACH_Pmac test??
+ */
+ if (!(_machine == _MACH_Pmac) && (irq == open_pic.irq_offset))
+ {
+ /*
+ * This magic address generates a PCI IACK cycle.
+ *
+ * This should go in the above mask/ack code soon. -- Cort
+ */
+ if ( chrp_int_ack_special )
+ irq = *chrp_int_ack_special;
+#ifndef CONFIG_PMAC
+ else
+ irq = i8259_irq(0);
+#endif
+ /*
+ * Acknowledge as soon as possible to allow i8259
+ * interrupt nesting */
+ openpic_eoi(smp_processor_id());
+ openpic_eoi_done = 1;
+ }
+ if (irq == OPENPIC_VEC_SPURIOUS)
+ {
+ /*
+ * Spurious interrupts should never be
+ * acknowledged
+ */
+ ppc_spurious_interrupts++;
+ openpic_eoi_done = 1;
+ goto out;
+ }
+
+ if (irq < 0)
+ {
+ printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
+ irq, regs->nip);
+ ppc_spurious_interrupts++;
+ }
else
- openpic_disable_irq(irq_nr-open_pic.irq_offset);
+ {
+ ppc_irq_dispatch_handler( regs, irq );
+ }
+out:
+ if (!openpic_eoi_done)
+ openpic_eoi(smp_processor_id());
}
-static void chrp_unmask_irq(unsigned int irq_nr)
+#ifdef __SMP__
+void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
{
- if ((_machine != _MACH_gemini) && is_8259_irq(irq_nr))
- i8259_pic.enable(irq_nr);
- else
- openpic_enable_irq(irq_nr-open_pic.irq_offset);
+ smp_message_recv(cpl-OPENPIC_VEC_IPI);
}
+#endif /* __SMP__ */
+
struct hw_interrupt_type open_pic = {
" OpenPIC ",
NULL,
NULL,
NULL,
- chrp_unmask_irq,
- chrp_mask_irq,
- chrp_mask_and_ack_irq,
+ openpic_enable_irq,
+ openpic_disable_irq,
+ /* Theorically, the mask&ack should be NULL for OpenPIC. However, doing
+ * so shows tons of bogus interrupts coming in.
+ * This problem is apparently due to the common code always calling
+ * unmask(). I apparently (need more test) fixed it in the 2.4 new IRQ
+ * management by cleanly implementing the handler's end() function, so
+ * neither mask nor unmask are needed. In the meantime, the fix below will
+ * work for 2.2 -Benh
+ *
+ * Hopefully this will fix my bogus interrups on MTX
+ * I merged everthing together so we don't have the same code in three
+ * places. This might cause stability problems, but I'd rather
+ * get it right once than three different times because someone forgot
+ * to make the same change to PReP or something --Troy
+ */
+ openpic_disable_irq,
0
};
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)