patch-2.1.120 linux/arch/i386/kernel/io_apic.c

Next file: linux/arch/i386/kernel/irq.c
Previous file: linux/arch/i386/kernel/entry.S
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.119/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
@@ -921,9 +921,10 @@
 static inline void self_IPI(unsigned int irq)
 {
 	irq_desc_t *desc = irq_desc + irq;
+	unsigned int status = desc->status;
 
-	if (desc->events && !desc->ipi) {
-		desc->ipi = 1;
+	if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
+		desc->status = status | IRQ_REPLAY;
 		send_IPI(APIC_DEST_SELF, IO_APIC_VECTOR(irq));
 	}
 }
@@ -960,6 +961,7 @@
 {
 	irq_desc_t *desc = irq_desc + irq;
 	struct irqaction * action;
+	unsigned int status;
 
 	spin_lock(&irq_controller_lock);
 
@@ -968,19 +970,19 @@
 	 * and do not need to be masked.
 	 */
 	ack_APIC_irq();
-	desc->ipi = 0;
-	desc->events = 1;
+	status = desc->status & ~IRQ_REPLAY;
+	status |= IRQ_PENDING;
 
 	/*
 	 * If the IRQ is disabled for whatever reason, we cannot
 	 * use the action we have.
 	 */
 	action = NULL;
-	if (!(desc->status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
 		action = desc->action;
-		desc->status = IRQ_INPROGRESS;
-		desc->events = 0;
+		status &= ~IRQ_PENDING;
 	}
+	desc->status = status | IRQ_INPROGRESS;
 	spin_unlock(&irq_controller_lock);
 
 	/*
@@ -996,18 +998,15 @@
 	 * pending events.
 	 */
 	for (;;) {
-		int pending;
-
 		handle_IRQ_event(irq, regs);
 
 		spin_lock(&irq_controller_lock);
-		pending = desc->events;
-		desc->events = 0;
-		if (!pending)
+		if (!(desc->status & IRQ_PENDING))
 			break;
+		desc->status &= ~IRQ_PENDING;
 		spin_unlock(&irq_controller_lock);
 	}
-	desc->status &= IRQ_DISABLED;
+	desc->status &= ~IRQ_INPROGRESS;
 	spin_unlock(&irq_controller_lock);
 
 	irq_exit(cpu, irq);
@@ -1018,6 +1017,7 @@
 {
 	irq_desc_t *desc = irq_desc + irq;
 	struct irqaction * action;
+	unsigned int status;
 
 	spin_lock(&irq_controller_lock);
 	/*
@@ -1029,18 +1029,17 @@
 	 * So this all has to be within the spinlock.
 	 */
 	mask_IO_APIC_irq(irq);
-
-	desc->ipi = 0;
+	status = desc->status & ~IRQ_REPLAY;
 
 	/*
 	 * If the IRQ is disabled for whatever reason, we must
 	 * not enter the IRQ action.
 	 */
 	action = NULL;
-	if (!(desc->status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
 		action = desc->action;
-		desc->status = IRQ_INPROGRESS;
 	}
+	desc->status = status | IRQ_INPROGRESS;
 
 	ack_APIC_irq();
 	spin_unlock(&irq_controller_lock);
@@ -1055,7 +1054,7 @@
 
 	spin_lock(&irq_controller_lock);
 	desc->status &= ~IRQ_INPROGRESS;
-	if (!desc->status)
+	if (!(desc->status & IRQ_DISABLED))
 		unmask_IO_APIC_irq(irq);
 	spin_unlock(&irq_controller_lock);
 
@@ -1160,6 +1159,31 @@
 	}
 }
 
+/*
+ *
+ * IRQ's that are handled by the old PIC in all cases:
+ * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
+ *   Linux doesn't really care, as it's not actually used
+ *   for any interrupt handling anyway.
+ * - IRQ13 is the FPU error IRQ, and may be connected
+ *   directly from the FPU to the old PIC. Linux doesn't
+ *   really care, because Linux doesn't want to use IRQ13
+ *   anyway (exception 16 is the proper FPU error signal)
+ * - IRQ9 is broken on PIIX4 motherboards:
+ *
+ *		"IRQ9 cannot be re-assigned"
+ *
+ *		IRQ9 is not available to assign to
+ *		ISA add-in cards because it is
+ *		dedicated to the power
+ *		management function of the PIIX4
+ *		controller on the motherboard.
+ *		This is true for other motherboards
+ *		which use the 82371AB PIIX4
+ *		component.
+ */
+#define PIC_IRQS	((1<<2)|(1<<9)|(1<<13))
+
 void __init setup_IO_APIC(void)
 {
 	init_sym_mode();
@@ -1177,7 +1201,7 @@
 		pirqs_enabled)
 	{
 		printk("ENABLING IO-APIC IRQs\n");
-		io_apic_irqs = ~((1<<2)|(1<<9)|(1<<13));
+		io_apic_irqs = ~PIC_IRQS;
 	} else {
 		if (ioapic_blacklisted())
 			printk(" blacklisted board, DISABLING IO-APIC IRQs\n");

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