* MIPS, i8259 and spurious interrupts.
@ 2002-02-25 19:50 Scott A McConnell
2002-02-26 10:49 ` Dominic Sweetman
0 siblings, 1 reply; 5+ messages in thread
From: Scott A McConnell @ 2002-02-25 19:50 UTC (permalink / raw)
To: linux-mips
I have been trying to track down and resolve a spurious interrupt
problem. I have attached some output and the code used to generate it in
i8259.c.
enable_8259A_irq is called but disable_8259A_irq is never called.
My i8259 is mapped to MIPS IRQ 6. As you will see below all my spurious
interrupts happen to be on 8259 irq 6. (Which is my ethernet card)
It appears that a new interrput is occuring before the last one is
finished. What should be done with MIPS irq 6? Should I clear the
status?
clear_cp0_status(STATUSF_IP6);
Instead of implementing i8259_do_irq is it ok to use do_irq in
arch/mips/kernel/irq.c?
Can anyone explain the following behavior:
Sometimes this code get caught in an endless loop.
Sometimes I see the:
printk("spurious 8259A interrupt: IRQ%d.\n", irq);
Sometimes I see:
*** SP 1 irq: 6***
*** SP 1.1 ***
*** SP 1.2 ***
*** SP 1 irq: 6***
*** SP 1.1 ***
*** SP 1.2 ***
*** SP 1 irq: 6***
*** SP 1.1 ***
*** SP 1.2 ***
*** SP 1 irq: 6***
*** SP 1.1 ***
*** SP 1.2 ***
*** SP 1 irq: 6***
*** SP 1.1 ***
*** SP 1.2 ***
*** SP 1 irq: 6***
*** SP 1.1 ***
*** SP 1.2 ***
*** SP 1 irq: 6***
*** SP 1.1 ***
*** SP 1.2 ***
---- Modified code ----
static inline int i8259A_irq_real(unsigned int irq)
{
int value;
int irqmask = 1 << irq;
if (irq < 8) {
printk("*** SP 1.1 ***\n");
outb(0x0B,0x20); /* ISR register */
value = inb(0x20) & irqmask;
outb(0x0A,0x20); /* back to the IRR register */
printk("*** SP 1.2 ***\n");
return value;
}
if (irq<14)
printk("*** SP 1.3 ***\n");
outb(0x0B,0xA0); /* ISR register */
value = inb(0xA0) & (irqmask >> 8);
outb(0x0A,0xA0); /* back to the IRR register */
return value;
}
/*
* Careful! The 8259A is a fragile beast, it pretty
* much _has_ to be done exactly like this (mask it
* first, _then_ send the EOI, and the order of EOI
* to the two 8259s is important!
*/
void mask_and_ack_8259A(unsigned int irq)
{
unsigned int irqmask = 1 << irq;
unsigned long flags;
spin_lock_irqsave(&i8259A_lock, flags);
/*
* Lightweight spurious IRQ detection. We do not want to overdo
* spurious IRQ handling - it's usually a sign of hardware problems, so
* we only do the checks we can do without slowing down good hardware
* nnecesserily.
*
* Note that IRQ7 and IRQ15 (the two spurious IRQs usually resulting
* rom the 8259A-1|2 PICs) occur even if the IRQ is masked in the
8259A.
* Thus we can check spurious 8259A IRQs without doing the quite slow
* i8259A_irq_real() call for every IRQ. This does not cover 100% of
* spurious interrupts, but should be enough to warn the user that
* there is something bad going on ...
*/
if (cached_irq_mask & irqmask)
goto spurious_8259A_irq;
cached_irq_mask |= irqmask;
handle_real_irq:
if (irq & 8) {
inb(0xA1); /* DUMMY - (do we need this?) */
outb(cached_A1,0xA1);
outb(0x60+(irq&7),0xA0);/* 'Specific EOI' to slave */
outb(0x62,0x20); /* 'Specific EOI' to master-IRQ2 */
} else {
inb(0x21); /* DUMMY - (do we need this?) */
outb(cached_21,0x21);
outb(0x60+irq,0x20); /* 'Specific EOI' to master */
}
spin_unlock_irqrestore(&i8259A_lock, flags);
return;
spurious_8259A_irq:
/*
* this is the slow path - should happen rarely.
*/
/************************************************************************************/
/* Why am I not returning from the following
call? */
/************************************************************************************/
printk("*** SP 1 irq: %d***\n", irq);
if (i8259A_irq_real(irq))
/*
* oops, the IRQ _is_ in service according to the
* 8259A - not spurious, go handle it.
*/
printk("*** SP 2 ***\n");
goto handle_real_irq;
{
static int spurious_irq_mask = 0;
printk("*** SP 3 ***\n");
/*
* At this point we can be sure the IRQ is spurious,
* lets ACK and report it. [once per IRQ]
*/
printk("*** SP 4 ***\n");
if (!(spurious_irq_mask & irqmask)) {
printk("spurious 8259A interrupt: IRQ%d.\n", irq);
spurious_irq_mask |= irqmask;
}
printk("*** SP 5 ***\n");
irq_err_count++;
/*
* Theoretically we do not have to handle this IRQ,
* but in Linux this does not cause problems and is
* simpler for us.
*/
printk("*** SP 6 ***\n");
goto handle_real_irq;
}
}
Thanks in advance for any advice...
--
Scott A. McConnell
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: MIPS, i8259 and spurious interrupts.
2002-02-25 19:50 MIPS, i8259 and spurious interrupts Scott A McConnell
@ 2002-02-26 10:49 ` Dominic Sweetman
2002-02-26 11:10 ` Alan Cox
0 siblings, 1 reply; 5+ messages in thread
From: Dominic Sweetman @ 2002-02-26 10:49 UTC (permalink / raw)
To: Scott A McConnell; +Cc: linux-mips
Scott A McConnell (samcconn@cotw.com) writes:
> I have been trying to track down and resolve a spurious interrupt
> problem. I have attached some output and the code used to generate it in
> i8259.c.
Part of your problem may be write buffer hell.
Whatever you do to clear the interrupt when you've done with it
involves writing to the 8259 controller. It's probably a long way
away - probably through a PCI bus to a simulated ISA bus. Somewhere
along the line the writes will be 'posted'; your CPU is fast, so when
your CPU emerges from its interrupt routine the write may not have
reached the 8259 yet, and you'll get a spurious interrupt.
The code which switches off the interrupt at the 8259 should probably
be equipped with a 'barrier' call to some system function which waits
until the write has really happened.
Then 8259s are ugly things which have some very CPU-specific
interactions with x86 CPUs. In a non-x86 context you need to
initialise them in particular ways.
--
Dominic Sweetman
Algorithmics Ltd
The Fruit Farm, Ely Road, Chittering, CAMBS CB5 9PH, ENGLAND
phone +44 1223 706200/fax +44 1223 706250/direct +44 1223 706205
http://www.algor.co.uk
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: MIPS, i8259 and spurious interrupts.
2002-02-26 10:49 ` Dominic Sweetman
@ 2002-02-26 11:10 ` Alan Cox
2002-02-26 11:10 ` Alan Cox
0 siblings, 1 reply; 5+ messages in thread
From: Alan Cox @ 2002-02-26 11:10 UTC (permalink / raw)
To: Dominic Sweetman; +Cc: Scott A McConnell, linux-mips
> Then 8259s are ugly things which have some very CPU-specific
> interactions with x86 CPUs. In a non-x86 context you need to
> initialise them in particular ways.
Like with a soldering iron 8)
In paticular if you are getting hangs at the point where you allow an IRQ
to come in check the level/edge behaviour and see if in fact you are taking
a continuous stream of interrupts jamming the CPU in irq handling
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: MIPS, i8259 and spurious interrupts.
2002-02-26 11:10 ` Alan Cox
@ 2002-02-26 11:10 ` Alan Cox
0 siblings, 0 replies; 5+ messages in thread
From: Alan Cox @ 2002-02-26 11:10 UTC (permalink / raw)
To: Dominic Sweetman; +Cc: Scott A McConnell, linux-mips
> Then 8259s are ugly things which have some very CPU-specific
> interactions with x86 CPUs. In a non-x86 context you need to
> initialise them in particular ways.
Like with a soldering iron 8)
In paticular if you are getting hangs at the point where you allow an IRQ
to come in check the level/edge behaviour and see if in fact you are taking
a continuous stream of interrupts jamming the CPU in irq handling
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: MIPS, i8259 and spurious interrupts.
@ 2002-02-26 6:50 Zhang Fuxin
0 siblings, 0 replies; 5+ messages in thread
From: Zhang Fuxin @ 2002-02-26 6:50 UTC (permalink / raw)
To: Scott A McConnell; +Cc: linux-mips@oss.sgi.com
hi,
>/************************************************************************************/
>/* Why am I not returning from the following
>call? */
>/************************************************************************************/
>
> printk("*** SP 1 irq: %d***\n", irq);
> if (i8259A_irq_real(irq))
> /*
> * oops, the IRQ _is_ in service according to the
> * 8259A - not spurious, go handle it.
> */
> printk("*** SP 2 ***\n");
> goto handle_real_irq;
do you really mean it? the goto is unconditional now?
but your output susgest that i8259A_irq_real never return true
>
> {
> static int spurious_irq_mask = 0;
>
> printk("*** SP 3 ***\n");
>
> /*
> * At this point we can be sure the IRQ is spurious,
> * lets ACK and report it. [once per IRQ]
> */
> printk("*** SP 4 ***\n");
>
> if (!(spurious_irq_mask & irqmask)) {
> printk("spurious 8259A interrupt: IRQ%d.\n", irq);
> spurious_irq_mask |= irqmask;
> }
> printk("*** SP 5 ***\n");
>
> irq_err_count++;
> /*
> * Theoretically we do not have to handle this IRQ,
> * but in Linux this does not cause problems and is
> * simpler for us.
> */
> printk("*** SP 6 ***\n");
>
> goto handle_real_irq;
> }
>}
>
>
>Thanks in advance for any advice...
>
>--
>Scott A. McConnell
Regards
Zhang Fuxin
fxzhang@ict.ac.cn
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2002-02-26 11:56 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-02-25 19:50 MIPS, i8259 and spurious interrupts Scott A McConnell
2002-02-26 10:49 ` Dominic Sweetman
2002-02-26 11:10 ` Alan Cox
2002-02-26 11:10 ` Alan Cox
-- strict thread matches above, loose matches on Subject: below --
2002-02-26 6:50 Zhang Fuxin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox