patch-2.2.2 linux/arch/i386/kernel/irq.c
Next file: linux/arch/i386/kernel/irq.h
Previous file: linux/arch/i386/kernel/io_apic.c
Back to the patch index
Back to the overall index
- Lines: 276
- Date:
Tue Feb 16 14:20:05 1999
- Orig file:
v2.2.1/linux/arch/i386/kernel/irq.c
- Orig date:
Wed Jan 20 23:14:04 1999
diff -u --recursive --new-file v2.2.1/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
@@ -70,11 +70,34 @@
*/
spinlock_t irq_controller_lock;
-
/*
* Dummy controller type for unused interrupts
*/
-static void do_none(unsigned int irq, struct pt_regs * regs) { }
+static void do_none(unsigned int irq, struct pt_regs * regs)
+{
+ /*
+ * we are careful. While for ISA irqs it's common to happen
+ * outside of any driver (think autodetection), this is not
+ * at all nice for PCI interrupts. So we are stricter and
+ * print a warning when such spurious interrupts happen.
+ * Spurious interrupts can confuse other drivers if the PCI
+ * IRQ line is shared.
+ *
+ * Such spurious interrupts are either driver bugs, or
+ * sometimes hw (chipset) bugs.
+ */
+ printk("unexpected IRQ vector %d on CPU#%d!\n",irq, smp_processor_id());
+
+#ifdef __SMP__
+ /*
+ * [currently unexpected vectors happen only on SMP and APIC.
+ * if we want to have non-APIC and non-8259A controllers
+ * in the future with unexpected vectors, this ack should
+ * probably be made controller-specific.]
+ */
+ ack_APIC_irq();
+#endif
+}
static void enable_none(unsigned int irq) { }
static void disable_none(unsigned int irq) { }
@@ -82,7 +105,7 @@
#define startup_none enable_none
#define shutdown_none disable_none
-static struct hw_interrupt_type no_irq_type = {
+struct hw_interrupt_type no_irq_type = {
"none",
startup_none,
shutdown_none,
@@ -141,10 +164,10 @@
* fed to the CPU IRQ line directly.
*
* Any '1' bit in this mask means the IRQ is routed through the IO-APIC.
- * this 'mixed mode' IRQ handling costs us one more branch in do_IRQ,
- * but we have _much_ higher compatibility and robustness this way.
+ * this 'mixed mode' IRQ handling costs nothing because it's only used
+ * at IRQ setup time.
*/
-unsigned long long io_apic_irqs = 0;
+unsigned long io_apic_irqs = 0;
/*
* These have to be protected by the irq controller spinlock
@@ -254,32 +277,43 @@
BUILD_COMMON_IRQ()
+
+#define BI(x,y) \
+ BUILD_IRQ(##x##y)
+
+#define BUILD_16_IRQS(x) \
+ BI(x,0) BI(x,1) BI(x,2) BI(x,3) \
+ BI(x,4) BI(x,5) BI(x,6) BI(x,7) \
+ BI(x,8) BI(x,9) BI(x,a) BI(x,b) \
+ BI(x,c) BI(x,d) BI(x,e) BI(x,f)
+
/*
* ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
+ * (these are usually mapped to vectors 0x20-0x30)
*/
-BUILD_IRQ(0) BUILD_IRQ(1) BUILD_IRQ(2) BUILD_IRQ(3)
-BUILD_IRQ(4) BUILD_IRQ(5) BUILD_IRQ(6) BUILD_IRQ(7)
-BUILD_IRQ(8) BUILD_IRQ(9) BUILD_IRQ(10) BUILD_IRQ(11)
-BUILD_IRQ(12) BUILD_IRQ(13) BUILD_IRQ(14) BUILD_IRQ(15)
+BUILD_16_IRQS(0x0)
#ifdef CONFIG_X86_IO_APIC
/*
- * The IO-APIC gives us many more interrupt sources..
+ * The IO-APIC gives us many more interrupt sources. Most of these
+ * are unused but an SMP system is supposed to have enough memory ...
+ * sometimes (mostly wrt. hw bugs) we get corrupted vectors all
+ * across the spectrum, so we really want to be prepared to get all
+ * of these. Plus, more powerful systems might have more than 64
+ * IO-APIC registers.
+ *
+ * (these are usually mapped into the 0x30-0xff vector range)
*/
-BUILD_IRQ(16) BUILD_IRQ(17) BUILD_IRQ(18) BUILD_IRQ(19)
-BUILD_IRQ(20) BUILD_IRQ(21) BUILD_IRQ(22) BUILD_IRQ(23)
-BUILD_IRQ(24) BUILD_IRQ(25) BUILD_IRQ(26) BUILD_IRQ(27)
-BUILD_IRQ(28) BUILD_IRQ(29) BUILD_IRQ(30) BUILD_IRQ(31)
-BUILD_IRQ(32) BUILD_IRQ(33) BUILD_IRQ(34) BUILD_IRQ(35)
-BUILD_IRQ(36) BUILD_IRQ(37) BUILD_IRQ(38) BUILD_IRQ(39)
-BUILD_IRQ(40) BUILD_IRQ(41) BUILD_IRQ(42) BUILD_IRQ(43)
-BUILD_IRQ(44) BUILD_IRQ(45) BUILD_IRQ(46) BUILD_IRQ(47)
-BUILD_IRQ(48) BUILD_IRQ(49) BUILD_IRQ(50) BUILD_IRQ(51)
-BUILD_IRQ(52) BUILD_IRQ(53) BUILD_IRQ(54) BUILD_IRQ(55)
-BUILD_IRQ(56) BUILD_IRQ(57) BUILD_IRQ(58) BUILD_IRQ(59)
-BUILD_IRQ(60) BUILD_IRQ(61) BUILD_IRQ(62) BUILD_IRQ(63)
+ BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3)
+BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7)
+BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BUILD_16_IRQS(0xa) BUILD_16_IRQS(0xb)
+BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd)
#endif
+#undef BUILD_16_IRQS
+#undef BI
+
+
#ifdef __SMP__
/*
* The following vectors are part of the Linux architecture, there
@@ -303,37 +337,35 @@
#endif
+#define IRQ(x,y) \
+ IRQ##x##y##_interrupt
+
+#define IRQLIST_16(x) \
+ IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), \
+ IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), \
+ IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
+ IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
+
static void (*interrupt[NR_IRQS])(void) = {
- IRQ0_interrupt, IRQ1_interrupt, IRQ2_interrupt, IRQ3_interrupt,
- IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt,
- IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt,
- IRQ12_interrupt, IRQ13_interrupt, IRQ14_interrupt, IRQ15_interrupt
+ IRQLIST_16(0x0),
+
#ifdef CONFIG_X86_IO_APIC
- ,IRQ16_interrupt, IRQ17_interrupt, IRQ18_interrupt, IRQ19_interrupt,
- IRQ20_interrupt, IRQ21_interrupt, IRQ22_interrupt, IRQ23_interrupt,
- IRQ24_interrupt, IRQ25_interrupt, IRQ26_interrupt, IRQ27_interrupt,
- IRQ28_interrupt, IRQ29_interrupt,
- IRQ30_interrupt, IRQ31_interrupt, IRQ32_interrupt, IRQ33_interrupt,
- IRQ34_interrupt, IRQ35_interrupt, IRQ36_interrupt, IRQ37_interrupt,
- IRQ38_interrupt, IRQ39_interrupt,
- IRQ40_interrupt, IRQ41_interrupt, IRQ42_interrupt, IRQ43_interrupt,
- IRQ44_interrupt, IRQ45_interrupt, IRQ46_interrupt, IRQ47_interrupt,
- IRQ48_interrupt, IRQ49_interrupt,
- IRQ50_interrupt, IRQ51_interrupt, IRQ52_interrupt, IRQ53_interrupt,
- IRQ54_interrupt, IRQ55_interrupt, IRQ56_interrupt, IRQ57_interrupt,
- IRQ58_interrupt, IRQ59_interrupt,
- IRQ60_interrupt, IRQ61_interrupt, IRQ62_interrupt, IRQ63_interrupt
+ IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3),
+ IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),
+ IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),
+ IRQLIST_16(0xc), IRQLIST_16(0xd)
#endif
};
+#undef IRQ
+#undef IRQLIST_16
+
/*
- * Initial irq handlers.
+ * Special irq handlers.
*/
-void no_action(int cpl, void *dev_id, struct pt_regs *regs)
-{
-}
+void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
#ifndef CONFIG_VISWS
/*
@@ -770,7 +802,7 @@
* 0 return value means that this irq is already being
* handled by some other CPU. (or is disabled)
*/
- unsigned int irq = regs.orig_eax & 0xff;
+ int irq = regs.orig_eax & 0xff; /* subtle, see irq.h */
int cpu = smp_processor_id();
kstat.irqs[cpu][irq]++;
@@ -986,42 +1018,6 @@
return irq_found;
}
-/*
- * Silly, horrible hack
- */
-static char uglybuffer[10*256];
-
-__asm__("\n" __ALIGN_STR"\n"
- "common_unexpected:\n\t"
- SAVE_ALL
- "pushl $ret_from_intr\n\t"
- "jmp strange_interrupt");
-
-void strange_interrupt(int irqnum)
-{
- printk("Unexpected interrupt %d\n", irqnum & 255);
- for (;;);
-}
-
-extern int common_unexpected;
-__initfunc(void init_unexpected_irq(void))
-{
- int i;
- for (i = 0; i < 256; i++) {
- char *code = uglybuffer + 10*i;
- unsigned long jumpto = (unsigned long) &common_unexpected;
-
- jumpto -= (unsigned long)(code+10);
- code[0] = 0x68; /* pushl */
- *(int *)(code+1) = i - 512;
- code[5] = 0xe9; /* jmp */
- *(int *)(code+6) = jumpto;
-
- set_intr_gate(i,code);
- }
-}
-
-
void init_ISA_irqs (void)
{
int i;
@@ -1033,7 +1029,7 @@
if (i < 16) {
/*
- * 16 old-style INTA-cycle interrupt gates:
+ * 16 old-style INTA-cycle interrupts:
*/
irq_desc[i].handler = &i8259A_irq_type;
} else {
@@ -1054,9 +1050,16 @@
#else
init_VISWS_APIC_irqs();
#endif
-
- for (i = 0; i < 16; i++)
- set_intr_gate(0x20+i,interrupt[i]);
+ /*
+ * Cover the whole vector space, no vector can escape
+ * us. (some of these will be overridden and become
+ * 'special' SMP interrupts)
+ */
+ for (i = 0; i < NR_IRQS; i++) {
+ int vector = FIRST_EXTERNAL_VECTOR + i;
+ if (vector != SYSCALL_VECTOR)
+ set_intr_gate(vector, interrupt[i]);
+ }
#ifdef __SMP__
@@ -1067,13 +1070,9 @@
set_intr_gate(IRQ0_TRAP_VECTOR, interrupt[0]);
/*
- * The reschedule interrupt slowly changes it's functionality,
- * while so far it was a kind of broadcasted timer interrupt,
- * in the future it should become a CPU-to-CPU rescheduling IPI,
- * driven by schedule() ?
+ * The reschedule interrupt is a CPU-to-CPU reschedule-helper
+ * IPI, driven by wakeup.
*/
-
- /* IPI for rescheduling */
set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
/* IPI for invalidation */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)