patch-2.4.18 linux/include/asm-cris/irq.h
Next file: linux/include/asm-cris/pgtable.h
Previous file: linux/include/asm-cris/ethernet.h
Back to the patch index
Back to the overall index
- Lines: 52
- Date:
Tue Jan 8 16:00:08 2002
- Orig file:
linux.orig/include/asm-cris/irq.h
- Orig date:
Mon Feb 18 20:18:40 2002
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/include/asm-cris/irq.h linux/include/asm-cris/irq.h
@@ -126,6 +126,9 @@
/* the asm IRQ handler makes sure the causing IRQ is blocked, then it calls
* do_IRQ (with irq disabled still). after that it unblocks and jumps to
* ret_from_intr (entry.S)
+ *
+ * The reason the IRQ is blocked is to allow an sti() before the handler which
+ * will acknowledge the interrupt is run.
*/
#define BUILD_IRQ(nr,mask) \
@@ -151,6 +154,41 @@
"reti\n\t" \
"nop\n");
+/* This is subtle. The timer interrupt is crucial and it should not be disabled for
+ * too long. However, if it had been a normal interrupt as per BUILD_IRQ, it would
+ * have been BLOCK'ed, and then softirq's are run before we return here to UNBLOCK.
+ * If the softirq's take too much time to run, the timer irq won't run and the
+ * watchdog will kill us.
+ *
+ * Furthermore, if a lot of other irq's occur before we return here, the multiple_irq
+ * handler is run and it prioritizes the timer interrupt. However if we had BLOCK'ed
+ * it here, we would not get the multiple_irq at all.
+ *
+ * The non-blocking here is based on the knowledge that the timer interrupt is
+ * registred as a fast interrupt (SA_INTERRUPT) so that we _know_ there will not
+ * be an sti() before the timer irq handler is run to acknowledge the interrupt.
+ */
+
+#define BUILD_TIMER_IRQ(nr,mask) \
+void IRQ_NAME(nr); \
+void sIRQ_NAME(nr); \
+void BAD_IRQ_NAME(nr); \
+__asm__ ( \
+ ".text\n\t" \
+ "IRQ" #nr "_interrupt:\n\t" \
+ SAVE_ALL \
+ "sIRQ" #nr "_interrupt:\n\t" /* shortcut for the multiple irq handler */ \
+ "moveq "#nr",$r10\n\t" \
+ "move.d $sp,$r11\n\t" \
+ "jsr do_IRQ\n\t" /* irq.c, r10 and r11 are arguments */ \
+ "moveq 0,$r9\n\t" /* make ret_from_intr realise we came from an irq */ \
+ "jump ret_from_intr\n\t" \
+ "bad_IRQ" #nr "_interrupt:\n\t" \
+ "push $r0\n\t" \
+ BLOCK_IRQ(mask,nr) \
+ "pop $r0\n\t" \
+ "reti\n\t" \
+ "nop\n");
#endif /* _ASM_IRQ_H */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)