patch-2.4.1 linux/arch/ppc/kernel/i8259.c

Next file: linux/arch/ppc/kernel/idle.c
Previous file: linux/arch/ppc/kernel/head.S
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/i8259.c linux/arch/ppc/kernel/i8259.c
@@ -10,12 +10,15 @@
 #define cached_A1 (cached_8259[0])
 #define cached_21 (cached_8259[1])
 
+spinlock_t i8259_lock = SPIN_LOCK_UNLOCKED;
+
 int i8259_pic_irq_offset;
 
 int i8259_irq(int cpu)
 {
 	int irq;
 	
+	spin_lock/*_irqsave*/(&i8259_lock/*, flags*/);
         /*
          * Perform an interrupt acknowledge cycle on controller 1
          */                                                             
@@ -40,14 +43,20 @@
 		 * interrupt
 		 */
 		outb(0x0b, 0x20);
-		if(~inb(0x20)&0x80)
+		if(~inb(0x20)&0x80) {
+			spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/);
 			return -1;
+		}
 	}
+	spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/);
 	return irq;
 }
 
 static void i8259_mask_and_ack_irq(unsigned int irq_nr)
 {
+	unsigned long flags;
+	
+	spin_lock_irqsave(&i8259_lock, flags);
         if ( irq_nr >= i8259_pic_irq_offset )
                 irq_nr -= i8259_pic_irq_offset;
 
@@ -63,6 +72,7 @@
                 outb(cached_21,0x21);
                 outb(0x20,0x20);        /* Non-specific EOI */                 
         }                                                                
+	spin_unlock_irqrestore(&i8259_lock, flags);
 }
 
 static void i8259_set_irq_mask(int irq_nr)
@@ -73,6 +83,9 @@
 
 static void i8259_mask_irq(unsigned int irq_nr)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&i8259_lock, flags);
         if ( irq_nr >= i8259_pic_irq_offset )
                 irq_nr -= i8259_pic_irq_offset;
         if ( irq_nr < 8 )
@@ -80,11 +93,14 @@
         else
                 cached_A1 |= 1 << (irq_nr-8);
         i8259_set_irq_mask(irq_nr);
+	spin_unlock_irqrestore(&i8259_lock, flags);
 }
 
 static void i8259_unmask_irq(unsigned int irq_nr)
 {
+	unsigned long flags;
 
+	spin_lock_irqsave(&i8259_lock, flags);
         if ( irq_nr >= i8259_pic_irq_offset )
                 irq_nr -= i8259_pic_irq_offset;
         if ( irq_nr < 8 )
@@ -92,6 +108,13 @@
         else
                 cached_A1 &= ~(1 << (irq_nr-8));
         i8259_set_irq_mask(irq_nr);
+	spin_unlock_irqrestore(&i8259_lock, flags);
+}
+
+static void i8259_end_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		i8259_unmask_irq(irq);
 }
 
 struct hw_interrupt_type i8259_pic = {
@@ -101,11 +124,15 @@
         i8259_unmask_irq,
         i8259_mask_irq,
         i8259_mask_and_ack_irq,
-        0
+        i8259_end_irq,
+        NULL
 };
 
 void __init i8259_init(void)
 {
+	unsigned long flags;
+	
+	spin_lock_irqsave(&i8259_lock, flags);
         /* init master interrupt controller */
         outb(0x11, 0x20); /* Start init sequence */
         outb(0x00, 0x21); /* Vector base */
@@ -120,7 +147,7 @@
         outb(0xFF, 0xA1); /* Mask all */
         outb(cached_A1, 0xA1);
         outb(cached_21, 0x21);
+	spin_unlock_irqrestore(&i8259_lock, flags);
         request_irq( i8259_pic_irq_offset + 2, no_action, SA_INTERRUPT,
                      "82c59 secondary cascade", NULL );
-        enable_irq(i8259_pic_irq_offset + 2);  /* Enable cascade interrupt */
 }

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