summaryrefslogtreecommitdiffstats
path: root/arch/ppc/kernel/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc/kernel/irq.c')
-rw-r--r--arch/ppc/kernel/irq.c75
1 files changed, 50 insertions, 25 deletions
diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
index a180e5f0a..f4a7c7143 100644
--- a/arch/ppc/kernel/irq.c
+++ b/arch/ppc/kernel/irq.c
@@ -1,4 +1,6 @@
/*
+ * $Id: irq.c,v 1.91 1998/12/28 10:28:47 paulus Exp $
+ *
* arch/ppc/kernel/irq.c
*
* Derived from arch/i386/kernel/irq.c
@@ -6,6 +8,7 @@
* Adapted from arch/i386 by Gary Thomas
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
* Updated and modified by Cort Dougan (cort@cs.nmt.edu)
+ * Copyright (C) 1996 Cort Dougan
* Adapted for Power Macintosh by Paul Mackerras
* Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
* Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
@@ -309,14 +312,14 @@ static void __openfirmware chrp_unmask_irq(unsigned int irq_nr)
static void mbx_mask_irq(unsigned int irq_nr)
{
cached_irq_mask[0] &= ~(1 << (31-irq_nr));
- ((immap_t *)MBX_IMAP_ADDR)->im_siu_conf.sc_simask =
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
cached_irq_mask[0];
}
static void mbx_unmask_irq(unsigned int irq_nr)
{
cached_irq_mask[0] |= (1 << (31-irq_nr));
- ((immap_t *)MBX_IMAP_ADDR)->im_siu_conf.sc_simask =
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
cached_irq_mask[0];
}
#endif /* CONFIG_8xx */
@@ -454,7 +457,6 @@ static inline void wait_on_bh(void)
}
-#define MAXCOUNT 100000000
static inline void wait_on_irq(int cpu)
{
int count = MAXCOUNT;
@@ -507,7 +509,7 @@ static inline void wait_on_irq(int cpu)
void synchronize_bh(void)
{
if (atomic_read(&global_bh_count) && !in_interrupt())
- wait_on_bh();
+ wait_on_bh();
}
@@ -529,6 +531,8 @@ void synchronize_irq(void)
static inline void get_irqlock(int cpu)
{
+ unsigned int loops = MAXCOUNT;
+
if (test_and_set_bit(0,&global_irq_lock)) {
/* do we already hold the lock? */
if ((unsigned char) cpu == global_irq_holder)
@@ -536,12 +540,17 @@ static inline void get_irqlock(int cpu)
/* Uhhuh.. Somebody else got it. Wait.. */
do {
do {
-
+ if (loops-- == 0) {
+ printk("get_irqlock(%d) waiting, global_irq_holder=%d\n", cpu, global_irq_holder);
+#ifdef CONFIG_XMON
+ xmon(0);
+#endif
+ }
} while (test_bit(0,&global_irq_lock));
} while (test_and_set_bit(0,&global_irq_lock));
}
/*
- * We also to make sure that nobody else is running
+ * We also need to make sure that nobody else is running
* in an interrupt context.
*/
wait_on_irq(cpu);
@@ -637,7 +646,7 @@ void __global_restore_flags(unsigned long flags)
#endif /* __SMP__ */
-asmlinkage void do_IRQ(struct pt_regs *regs)
+asmlinkage void do_IRQ(struct pt_regs *regs, int isfake)
{
int irq;
unsigned long bits;
@@ -656,9 +665,14 @@ asmlinkage void do_IRQ(struct pt_regs *regs)
#ifdef __SMP__
if ( cpu != 0 )
{
- if (!atomic_read(&n_lost_interrupts))
+ if (!isfake)
{
extern void smp_message_recv(void);
+#ifdef CONFIG_XMON
+ static int xmon_2nd;
+ if (xmon_2nd)
+ xmon(regs);
+#endif
smp_message_recv();
goto out;
}
@@ -666,6 +680,25 @@ asmlinkage void do_IRQ(struct pt_regs *regs)
mess with the controller from the second cpu -- Cort */
goto out;
}
+
+ {
+ unsigned int loops = MAXCOUNT;
+ while (test_bit(0, &global_irq_lock)) {
+ if (smp_processor_id() == global_irq_holder) {
+ printk("uh oh, interrupt while we hold global irq lock!\n");
+#ifdef CONFIG_XMON
+ xmon(0);
+#endif
+ break;
+ }
+ if (loops-- == 0) {
+ printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
+#ifdef CONFIG_XMON
+ xmon(0);
+#endif
+ }
+ }
+ }
#endif /* __SMP__ */
switch ( _machine )
@@ -799,9 +832,13 @@ apus_out:
}
if (irq < 0) {
- printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
- irq, regs->nip);
- spurious_interrupts++;
+ /* we get here with Gatwick but the 'bogus' isn't correct in that case -- Cort */
+ if ( irq != second_irq )
+ {
+ printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
+ irq, regs->nip);
+ spurious_interrupts++;
+ }
goto out;
}
@@ -809,7 +846,7 @@ apus_out:
/* For MPC8xx, read the SIVEC register and shift the bits down
* to get the irq number.
*/
- bits = ((immap_t *)MBX_IMAP_ADDR)->im_siu_conf.sc_sivec;
+ bits = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec;
irq = bits >> 26;
#endif /* CONFIG_8xx */
mask_and_ack_irq(irq);
@@ -1089,17 +1126,6 @@ __initfunc(void init_IRQ(void))
*/
if ( _prep_type == _PREP_IBM )
irq_mode2 |= 0xa0;
- /*
- * Sound on the Powerstack reportedly needs to be edge triggered
- */
- if ( _prep_type == _PREP_Motorola )
- {
- irq_mode2 &= ~0x04L;
- irq_mode2 = 0xca;
- outb( irq_mode1 , 0x4d0 );
- outb( irq_mode2 , 0x4d1 );
- }
-
}
break;
#ifdef CONFIG_APUS
@@ -1116,8 +1142,7 @@ __initfunc(void init_IRQ(void))
/* This routine will fix some missing interrupt values in the device tree
* on the gatwick mac-io controller used by some PowerBooks
*/
-__pmac
-static void pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
+static void __init pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
{
struct device_node *node;
static struct interrupt_info int_pool[4];