patch-2.2.8 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.2.7/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
@@ -203,7 +203,7 @@
 
 void make_8259A_irq(unsigned int irq)
 {
-	disable_irq(irq);
+	disable_irq_nosync(irq);
 	io_apic_irqs &= ~(1<<irq);
 	irq_desc[irq].handler = &i8259A_irq_type;
 	enable_irq(irq);
@@ -239,11 +239,13 @@
 	{
 		unsigned int status;
 		mask_and_ack_8259A(irq);
-		status = desc->status & ~IRQ_REPLAY;
+		status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
 		action = NULL;
-		if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
 			action = desc->action;
-		desc->status = status | IRQ_INPROGRESS;
+			status |= IRQ_INPROGRESS;
+		}
+		desc->status = status;
 	}
 	spin_unlock(&irq_controller_lock);
 
@@ -320,7 +322,7 @@
 BUILD_SMP_INTERRUPT(reschedule_interrupt)
 BUILD_SMP_INTERRUPT(invalidate_interrupt)
 BUILD_SMP_INTERRUPT(stop_cpu_interrupt)
-BUILD_SMP_INTERRUPT(mtrr_interrupt)
+BUILD_SMP_INTERRUPT(call_function_interrupt)
 BUILD_SMP_INTERRUPT(spurious_interrupt)
 
 /*
@@ -747,7 +749,7 @@
  * hardware disable after having gotten the irq
  * controller lock. 
  */
-void disable_irq(unsigned int irq)
+void disable_irq_nosync(unsigned int irq)
 {
 	unsigned long flags;
 
@@ -757,9 +759,21 @@
 		irq_desc[irq].handler->disable(irq);
 	}
 	spin_unlock_irqrestore(&irq_controller_lock, flags);
+}
+
+/*
+ * Synchronous version of the above, making sure the IRQ is
+ * no longer running on any other IRQ..
+ */
+void disable_irq(unsigned int irq)
+{
+	disable_irq_nosync(irq);
 
-	if (irq_desc[irq].status & IRQ_INPROGRESS)
-		synchronize_irq();
+	if (!local_irq_count[smp_processor_id()]) {
+		do {
+			barrier();
+		} while (irq_desc[irq].status & IRQ_INPROGRESS);
+	}
 }
 
 void enable_irq(unsigned int irq)
@@ -769,7 +783,7 @@
 	spin_lock_irqsave(&irq_controller_lock, flags);
 	switch (irq_desc[irq].depth) {
 	case 1:
-		irq_desc[irq].status &= ~(IRQ_DISABLED | IRQ_INPROGRESS);
+		irq_desc[irq].status &= ~IRQ_DISABLED;
 		irq_desc[irq].handler->enable(irq);
 		/* fall throught */
 	default:
@@ -864,7 +878,7 @@
 
 	if (!shared) {
 		irq_desc[irq].depth = 0;
-		irq_desc[irq].status &= ~(IRQ_DISABLED | IRQ_INPROGRESS);
+		irq_desc[irq].status &= ~IRQ_DISABLED;
 		irq_desc[irq].handler->startup(irq);
 	}
 	spin_unlock_irqrestore(&irq_controller_lock,flags);
@@ -936,7 +950,7 @@
  *
  * This depends on the fact that any interrupt that
  * comes in on to an unassigned handler will get stuck
- * with "IRQ_INPROGRESS" asserted and the interrupt
+ * with "IRQ_WAITING" cleared and the interrupt
  * disabled.
  */
 unsigned long probe_irq_on(void)
@@ -950,8 +964,7 @@
 	spin_lock_irq(&irq_controller_lock);
 	for (i = NR_IRQS-1; i > 0; i--) {
 		if (!irq_desc[i].action) {
-			unsigned int status = irq_desc[i].status | IRQ_AUTODETECT;
-			irq_desc[i].status = status & ~IRQ_INPROGRESS;
+			irq_desc[i].status |= IRQ_AUTODETECT | IRQ_WAITING;
 			irq_desc[i].handler->startup(i);
 		}
 	}
@@ -974,7 +987,7 @@
 			continue;
 		
 		/* It triggered already - consider it spurious. */
-		if (status & IRQ_INPROGRESS) {
+		if (!(status & IRQ_WAITING)) {
 			irq_desc[i].status = status & ~IRQ_AUTODETECT;
 			irq_desc[i].handler->shutdown(i);
 		}
@@ -1000,7 +1013,7 @@
 		if (!(status & IRQ_AUTODETECT))
 			continue;
 
-		if (status & IRQ_INPROGRESS) {
+		if (!(status & IRQ_WAITING)) {
 			if (!nr_irqs)
 				irq_found = i;
 			nr_irqs++;
@@ -1081,8 +1094,8 @@
 	/* self generated IPI for local APIC timer */
 	set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
 
-	/* IPI for MTRR control */
-	set_intr_gate(MTRR_CHANGE_VECTOR, mtrr_interrupt);
+	/* IPI for generic function call */
+	set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
 
 	/* IPI vector for APIC spurious interrupts */
 	set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)