patch-2.1.121 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: 263
- Date:
Wed Sep 9 08:56:58 1998
- Orig file:
v2.1.120/linux/arch/i386/kernel/irq.c
- Orig date:
Sat Sep 5 16:46:40 1998
diff -u --recursive --new-file v2.1.120/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
@@ -39,6 +39,7 @@
#include <asm/delay.h>
#include "irq.h"
+#include "desc.h"
unsigned int local_bh_count[NR_CPUS];
unsigned int local_irq_count[NR_CPUS];
@@ -79,14 +80,14 @@
*/
unsigned long long io_apic_irqs = 0;
-static void do_8259A_IRQ (unsigned int irq, int cpu, struct pt_regs * regs);
+static void do_8259A_IRQ(unsigned int irq, struct pt_regs * regs);
static void enable_8259A_irq(unsigned int irq);
void disable_8259A_irq(unsigned int irq);
/*
* Dummy controller type for unused interrupts
*/
-static void do_none(unsigned int irq, int cpu, struct pt_regs * regs) { }
+static void do_none(unsigned int irq, struct pt_regs * regs) { }
static void enable_none(unsigned int irq) { }
static void disable_none(unsigned int irq) { }
@@ -105,12 +106,10 @@
};
irq_desc_t irq_desc[NR_IRQS] = {
- [0 ... 15] = { 0, &i8259A_irq_type, }, /* default to standard ISA IRQs */
- [16 ... 63] = { 0, &no_irq_type, }, /* 'high' PCI IRQs filled in on demand */
+ [0 ... 15] = { 0, &i8259A_irq_type, }, /* default to standard ISA IRQs */
+ [16 ... NR_IRQS-1] = { 0, &no_irq_type, }, /* 'high' PCI IRQs filled in on demand */
};
-int irq_vector[NR_IRQS] = { IRQ0_TRAP_VECTOR , 0 };
-
/*
* These have to be protected by the irq controller spinlock
@@ -150,52 +149,29 @@
BUILD_COMMON_IRQ()
/*
- * ISA PIC or IO-APIC triggered (INTA-cycle or APIC) interrupts:
+ * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
*/
-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(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)
#ifdef __SMP__
/*
- * The IO-APIC (present only in SMP boards) has 8 more hardware
- * interrupt pins, for all of them we define an IRQ vector:
- *
- * raw PCI interrupts 0-3, basically these are the ones used
- * heavily:
+ * The IO-APIC gives us many more interrupt sources..
*/
BUILD_IRQ(16) BUILD_IRQ(17) BUILD_IRQ(18) BUILD_IRQ(19)
-
-/*
- * [FIXME: anyone with 2 separate PCI buses and 2 IO-APICs, please
- * speak up if problems and request experimental patches.
- * --mingo ]
- */
-
-/*
- * MIRQ (motherboard IRQ) interrupts 0-1:
- */
-BUILD_IRQ(20) BUILD_IRQ(21)
-
-/*
- * 'nondefined general purpose interrupt'.
- */
-BUILD_IRQ(22)
-/*
- * optionally rerouted SMI interrupt:
- */
-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(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)
/*
@@ -586,29 +562,35 @@
#endif
-int handle_IRQ_event(unsigned int irq, struct pt_regs * regs)
+/*
+ * This should really return information about whether
+ * we should do bottom half handling etc. Right now we
+ * end up _always_ checking the bottom half, which is a
+ * waste of time and is not what some drivers would
+ * prefer.
+ */
+int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
{
- struct irqaction * action;
int status;
+ int cpu = smp_processor_id();
- status = 0;
- action = irq_desc[irq].action;
+ irq_enter(cpu, irq);
- if (action) {
- status |= 1;
+ status = 1; /* Force the "do bottom halves" bit */
- if (!(action->flags & SA_INTERRUPT))
- __sti();
+ if (!(action->flags & SA_INTERRUPT))
+ __sti();
- do {
- status |= action->flags;
- action->handler(irq, action->dev_id, regs);
- action = action->next;
- } while (action);
- if (status & SA_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);
- __cli();
- }
+ do {
+ status |= action->flags;
+ action->handler(irq, action->dev_id, regs);
+ action = action->next;
+ } while (action);
+ if (status & SA_SAMPLE_RANDOM)
+ add_interrupt_randomness(irq);
+ __cli();
+
+ irq_exit(cpu, irq);
return status;
}
@@ -625,9 +607,9 @@
void make_8259A_irq(unsigned int irq)
{
+ disable_irq(irq);
__long(0,io_apic_irqs) &= ~(1<<irq);
irq_desc[irq].handler = &i8259A_irq_type;
- disable_irq(irq);
enable_irq(irq);
}
@@ -639,8 +621,6 @@
*/
static inline void mask_and_ack_8259A(unsigned int irq)
{
- spin_lock(&irq_controller_lock);
- irq_desc[irq].status |= IRQ_INPROGRESS;
cached_irq_mask |= 1 << irq;
if (irq & 8) {
inb(0xA1); /* DUMMY */
@@ -652,24 +632,39 @@
outb(cached_21,0x21);
outb(0x20,0x20);
}
- spin_unlock(&irq_controller_lock);
}
-static void do_8259A_IRQ(unsigned int irq, int cpu, struct pt_regs * regs)
+static void do_8259A_IRQ(unsigned int irq, struct pt_regs * regs)
{
- mask_and_ack_8259A(irq);
+ struct irqaction * action;
+ irq_desc_t *desc = irq_desc + irq;
- irq_enter(cpu, irq);
+ spin_lock(&irq_controller_lock);
+ {
+ unsigned int status;
+ mask_and_ack_8259A(irq);
+ status = desc->status & ~IRQ_REPLAY;
+ action = NULL;
+ if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ action = desc->action;
+ desc->status = status | IRQ_INPROGRESS;
+ }
+ spin_unlock(&irq_controller_lock);
- if (handle_IRQ_event(irq, regs)) {
- spin_lock(&irq_controller_lock);
- irq_desc[irq].status &= ~IRQ_INPROGRESS;
- if (!(irq_desc[irq].status & IRQ_DISABLED))
+ /* Exit early if we had no action or it was disabled */
+ if (!action)
+ return;
+
+ handle_IRQ_event(irq, regs, action);
+
+ spin_lock(&irq_controller_lock);
+ {
+ unsigned int status = desc->status & ~IRQ_INPROGRESS;
+ desc->status = status;
+ if (!(status & IRQ_DISABLED))
enable_8259A_irq(irq);
- spin_unlock(&irq_controller_lock);
}
-
- irq_exit(cpu, irq);
+ spin_unlock(&irq_controller_lock);
}
@@ -730,7 +725,7 @@
int cpu = smp_processor_id();
kstat.irqs[cpu][irq]++;
- irq_desc[irq].handler->handle(irq, cpu, ®s);
+ irq_desc[irq].handler->handle(irq, ®s);
/*
* This should be conditional: we should really get
@@ -986,9 +981,6 @@
* 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() ?
- *
- * [ It has to be here .. it doesn't work if you put
- * it down the bottom - assembler explodes 8) ]
*/
/* IPI for rescheduling */
@@ -1013,9 +1005,9 @@
request_region(0xa0,0x20,"pic2");
setup_x86_irq(2, &irq2);
setup_x86_irq(13, &irq13);
-}
+}
-#ifdef __SMP__
+#ifdef __SMP__
__initfunc(void init_IRQ_SMP(void))
{
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov