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
- Lines: 111
- Date:
Mon Jan 22 15:41:15 2001
- Orig file:
v2.4.0/linux/arch/ppc/kernel/i8259.c
- Orig date:
Mon Jun 19 17:59:36 2000
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)