diff options
Diffstat (limited to 'arch/ppc/kernel/irq.c')
-rw-r--r-- | arch/ppc/kernel/irq.c | 75 |
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]; |