diff options
| author | Anton Blanchard <anton@samba.org> | 2011-11-24 14:39:36 -0500 |
|---|---|---|
| committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2011-11-27 19:42:09 -0500 |
| commit | 3ce21cdfe93efffa4ffba9cf3ca2576d3d60d6dc (patch) | |
| tree | 463576e41c593246365e7e41cfcd3c0197718967 /arch/powerpc/sysdev/xics | |
| parent | 3bfd0c9c8f9cd2c09cf3e5376c7113eec3370ebd (diff) | |
powerpc/xics: Harden xics hypervisor backend
During kdump stress testing I sometimes see the kdump kernel panic
with:
Interrupt 0x306 (real) is invalid, disabling it.
Kernel panic - not syncing: bad return code EOI - rc = -4, value=ff000306
Instead of panicing print the error message, dump the stack the first
time it happens and continue on. Add some more information to the
debug messages as well.
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/sysdev/xics')
| -rw-r--r-- | arch/powerpc/sysdev/xics/icp-hv.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/arch/powerpc/sysdev/xics/icp-hv.c b/arch/powerpc/sysdev/xics/icp-hv.c index 9518d367a64f..784b3fc6f071 100644 --- a/arch/powerpc/sysdev/xics/icp-hv.c +++ b/arch/powerpc/sysdev/xics/icp-hv.c | |||
| @@ -27,33 +27,49 @@ static inline unsigned int icp_hv_get_xirr(unsigned char cppr) | |||
| 27 | { | 27 | { |
| 28 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; | 28 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; |
| 29 | long rc; | 29 | long rc; |
| 30 | unsigned int ret = XICS_IRQ_SPURIOUS; | ||
| 30 | 31 | ||
| 31 | rc = plpar_hcall(H_XIRR, retbuf, cppr); | 32 | rc = plpar_hcall(H_XIRR, retbuf, cppr); |
| 32 | if (rc != H_SUCCESS) | 33 | if (rc == H_SUCCESS) { |
| 33 | panic(" bad return code xirr - rc = %lx\n", rc); | 34 | ret = (unsigned int)retbuf[0]; |
| 34 | return (unsigned int)retbuf[0]; | 35 | } else { |
| 36 | pr_err("%s: bad return code xirr cppr=0x%x returned %ld\n", | ||
| 37 | __func__, cppr, rc); | ||
| 38 | WARN_ON_ONCE(1); | ||
| 39 | } | ||
| 40 | |||
| 41 | return ret; | ||
| 35 | } | 42 | } |
| 36 | 43 | ||
| 37 | static inline void icp_hv_set_xirr(unsigned int value) | 44 | static inline void icp_hv_set_xirr(unsigned int value) |
| 38 | { | 45 | { |
| 39 | long rc = plpar_hcall_norets(H_EOI, value); | 46 | long rc = plpar_hcall_norets(H_EOI, value); |
| 40 | if (rc != H_SUCCESS) | 47 | if (rc != H_SUCCESS) { |
| 41 | panic("bad return code EOI - rc = %ld, value=%x\n", rc, value); | 48 | pr_err("%s: bad return code eoi xirr=0x%x returned %ld\n", |
| 49 | __func__, value, rc); | ||
| 50 | WARN_ON_ONCE(1); | ||
| 51 | } | ||
| 42 | } | 52 | } |
| 43 | 53 | ||
| 44 | static inline void icp_hv_set_cppr(u8 value) | 54 | static inline void icp_hv_set_cppr(u8 value) |
| 45 | { | 55 | { |
| 46 | long rc = plpar_hcall_norets(H_CPPR, value); | 56 | long rc = plpar_hcall_norets(H_CPPR, value); |
| 47 | if (rc != H_SUCCESS) | 57 | if (rc != H_SUCCESS) { |
| 48 | panic("bad return code cppr - rc = %lx\n", rc); | 58 | pr_err("%s: bad return code cppr cppr=0x%x returned %ld\n", |
| 59 | __func__, value, rc); | ||
| 60 | WARN_ON_ONCE(1); | ||
| 61 | } | ||
| 49 | } | 62 | } |
| 50 | 63 | ||
| 51 | static inline void icp_hv_set_qirr(int n_cpu , u8 value) | 64 | static inline void icp_hv_set_qirr(int n_cpu , u8 value) |
| 52 | { | 65 | { |
| 53 | long rc = plpar_hcall_norets(H_IPI, get_hard_smp_processor_id(n_cpu), | 66 | int hw_cpu = get_hard_smp_processor_id(n_cpu); |
| 54 | value); | 67 | long rc = plpar_hcall_norets(H_IPI, hw_cpu, value); |
| 55 | if (rc != H_SUCCESS) | 68 | if (rc != H_SUCCESS) { |
| 56 | panic("bad return code qirr - rc = %lx\n", rc); | 69 | pr_err("%s: bad return code qirr cpu=%d hw_cpu=%d mfrr=0x%x " |
| 70 | "returned %ld\n", __func__, n_cpu, hw_cpu, value, rc); | ||
| 71 | WARN_ON_ONCE(1); | ||
| 72 | } | ||
| 57 | } | 73 | } |
| 58 | 74 | ||
| 59 | static void icp_hv_eoi(struct irq_data *d) | 75 | static void icp_hv_eoi(struct irq_data *d) |
