patch-2.1.120 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

diff -u --recursive --new-file v2.1.119/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
@@ -105,8 +105,8 @@
 };
 
 irq_desc_t irq_desc[NR_IRQS] = {
-	[0 ... 15] = { 0, 0, 0, &i8259A_irq_type, },	/* default to standard ISA IRQs */
-	[16 ... 63] = { 0, 0, 0, &no_irq_type, },	/* 'high' PCI IRQs filled in on demand */
+	[0 ... 15] = { 0, &i8259A_irq_type, },	/* default to standard ISA IRQs */
+	[16 ... 63] = { 0, &no_irq_type, },	/* 'high' PCI IRQs filled in on demand */
 };
 
 int irq_vector[NR_IRQS] = { IRQ0_TRAP_VECTOR , 0 };
@@ -663,7 +663,8 @@
 
 	if (handle_IRQ_event(irq, regs)) {
 		spin_lock(&irq_controller_lock);
-		if (!(irq_desc[irq].status &= IRQ_DISABLED))
+		irq_desc[irq].status &= ~IRQ_INPROGRESS;
+		if (!(irq_desc[irq].status & IRQ_DISABLED))
 			enable_8259A_irq(irq);
 		spin_unlock(&irq_controller_lock);
 	}
@@ -683,10 +684,6 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&irq_controller_lock, flags);
-	/*
-	 * At this point we may actually have a pending interrupt being active
-	 * on another CPU. So don't touch the IRQ_INPROGRESS bit..
-	 */
 	irq_desc[irq].status |= IRQ_DISABLED;
 	irq_desc[irq].handler->disable(irq);
 	spin_unlock_irqrestore(&irq_controller_lock, flags);
@@ -793,6 +790,7 @@
 	*p = new;
 
 	if (!shared) {
+		irq_desc[irq].status = 0;
 #ifdef __SMP__
 		if (IO_APIC_IRQ(irq)) {
 			/*
@@ -803,11 +801,10 @@
 			if (irq < 16) {
 				disable_8259A_irq(irq);
 				if (i8259A_irq_pending(irq))
-					irq_desc[irq].events = 1;
+					irq_desc[irq].status = IRQ_PENDING;
 			}
 		}
 #endif
-		irq_desc[irq].status = 0;
 		irq_desc[irq].handler->enable(irq);
 	}
 	spin_unlock_irqrestore(&irq_controller_lock,flags);
@@ -863,8 +860,10 @@
 		/* Found it - now free it */
 		*p = action->next;
 		kfree(action);
-		if (!irq_desc[irq].action)
+		if (!irq_desc[irq].action) {
+			irq_desc[irq].status |= IRQ_DISABLED;
 			irq_desc[irq].handler->disable(irq);
+		}
 		goto out;
 	}
 	printk("Trying to free free IRQ%d\n",irq);
@@ -880,9 +879,9 @@
  * with "IRQ_INPROGRESS" asserted and the interrupt
  * disabled.
  */
-unsigned long probe_irq_on (void)
+unsigned long probe_irq_on(void)
 {
-	unsigned int i, irqs = 0;
+	unsigned int i;
 	unsigned long delay;
 
 	/*
@@ -891,51 +890,68 @@
 	spin_lock_irq(&irq_controller_lock);
 	for (i = NR_IRQS-1; i > 0; i--) {
 		if (!irq_desc[i].action) {
-			irq_desc[i].status = 0;
+			unsigned int status = irq_desc[i].status | IRQ_AUTODETECT;
+			irq_desc[i].status = status & ~(IRQ_INPROGRESS | IRQ_PENDING);
 			irq_desc[i].handler->enable(i);
-			irqs |= (1 << i);
 		}
 	}
 	spin_unlock_irq(&irq_controller_lock);
 
 	/*
-	 * wait for spurious interrupts to increase counters
+	 * Wait for spurious interrupts to trigger
 	 */
 	for (delay = jiffies + HZ/10; delay > jiffies; )
 		/* about 100ms delay */ synchronize_irq();
 
 	/*
-	 * now filter out any obviously spurious interrupts
+	 * Now filter out any obviously spurious interrupts
 	 */
 	spin_lock_irq(&irq_controller_lock);
 	for (i=0; i<NR_IRQS; i++) {
-		if (irq_desc[i].status & IRQ_INPROGRESS)
-			irqs &= ~(1UL << i);
+		unsigned int status = irq_desc[i].status;
+
+		if (!(status & IRQ_AUTODETECT))
+			continue;
+		
+		/* It triggered already - consider it spurious. */
+		if (status & IRQ_INPROGRESS) {
+			irq_desc[i].status = status & ~IRQ_AUTODETECT;
+			irq_desc[i].handler->disable(i);
+		}
 	}
 	spin_unlock_irq(&irq_controller_lock);
 
-	return irqs;
+	return 0x12345678;
 }
 
-int probe_irq_off (unsigned long irqs)
+int probe_irq_off(unsigned long unused)
 {
-	int i, irq_found = -1;
+	int i, irq_found, nr_irqs;
+
+	if (unused != 0x12345678)
+		printk("Bad IRQ probe from %lx\n", (&unused)[-1]);
 
+	nr_irqs = 0;
+	irq_found = 0;
 	spin_lock_irq(&irq_controller_lock);
 	for (i=0; i<NR_IRQS; i++) {
-		if ((irqs & 1) && (irq_desc[i].status & IRQ_INPROGRESS)) {
-			if (irq_found != -1) {
-				irq_found = -irq_found;
-				goto out;
-			}
-			irq_found = i;
+		unsigned int status = irq_desc[i].status;
+
+		if (!(status & IRQ_AUTODETECT))
+			continue;
+
+		if (status & IRQ_INPROGRESS) {
+			if (!nr_irqs)
+				irq_found = i;
+			nr_irqs++;
 		}
-		irqs >>= 1;
+		irq_desc[i].status = status & ~IRQ_AUTODETECT;
+		irq_desc[i].handler->disable(i);
 	}
-	if (irq_found == -1)
-		irq_found = 0;
-out:
 	spin_unlock_irq(&irq_controller_lock);
+
+	if (nr_irqs > 1)
+		irq_found = -irq_found;
 	return irq_found;
 }
 
@@ -948,10 +964,9 @@
 	outb_p(LATCH & 0xff , 0x40);	/* LSB */
 	outb(LATCH >> 8 , 0x40);	/* MSB */
 
-	for (i=0; i<NR_IRQS; i++) {
-		irq_desc[i].events = 0;
-		irq_desc[i].status = 0;
-	}
+	for (i=0; i<NR_IRQS; i++)
+		irq_desc[i].status = IRQ_DISABLED;
+
 	/*
 	 * 16 old-style INTA-cycle interrupt gates:
 	 */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov