| From 4fcace47b9645557ce57bd9f0481ffbd5b72df1f Mon Sep 17 00:00:00 2001 |
| From: David S. Miller <davem@davemloft.net> |
| Date: Sat, 26 Apr 2008 02:19:18 -0700 |
| Subject: sparc64: Fix wedged irq regression. |
| |
| From: David S. Miller <davem@davemloft.net> |
| |
| [ Upstream commit: 92aa3573c9cd58fe0bcd1c52c9fd8f5708785917 ] |
| |
| Kernel bugzilla 10273 |
| |
| As reported by Jos van der Ende, ever since commit |
| 5a606b72a4309a656cd1a19ad137dc5557c4b8ea ("[SPARC64]: Do not ACK an |
| INO if it is disabled or inprogress.") sun4u interrupts |
| can get stuck. |
| |
| What this changset did was add the following conditional to |
| the various IRQ chip ->enable() handlers on sparc64: |
| |
| if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) |
| return; |
| |
| which is correct, however it means that special care is needed |
| in the ->enable() method. |
| |
| Specifically we must put the interrupt into IDLE state during |
| an enable, or else it might never be sent out again. |
| |
| Setting the INO interrupt state to IDLE resets the state machine, |
| the interrupt input to the INO is retested by the hardware, and |
| if an interrupt is being signalled by the device, the INO |
| moves back into TRANSMIT state, and an interrupt vector is sent |
| to the cpu. |
| |
| The two sun4v IRQ chip handlers were already doing this properly, |
| only sun4u got it wrong. |
| |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| arch/sparc64/kernel/irq.c | 3 ++- |
| 1 file changed, 2 insertions(+), 1 deletion(-) |
| |
| --- a/arch/sparc64/kernel/irq.c |
| +++ b/arch/sparc64/kernel/irq.c |
| @@ -1,6 +1,6 @@ |
| /* irq.c: UltraSparc IRQ handling/init/registry. |
| * |
| - * Copyright (C) 1997, 2007 David S. Miller (davem@davemloft.net) |
| + * Copyright (C) 1997, 2007, 2008 David S. Miller (davem@davemloft.net) |
| * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) |
| * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) |
| */ |
| @@ -308,6 +308,7 @@ static void sun4u_irq_enable(unsigned in |
| IMAP_AID_SAFARI | IMAP_NID_SAFARI); |
| val |= tid | IMAP_VALID; |
| upa_writeq(val, imap); |
| + upa_writeq(ICLR_IDLE, data->iclr); |
| } |
| } |
| |