diff options
-rw-r--r-- | hw/psi.c | 35 | ||||
-rw-r--r-- | hw/xive.c | 7 | ||||
-rw-r--r-- | include/xive.h | 2 |
3 files changed, 38 insertions, 6 deletions
@@ -531,6 +531,30 @@ static const char *psi_p9_irq_names[P9_PSI_NUM_IRQS] = { "psu" }; +static void psi_p9_mask_unhandled_irq(struct irq_source *is, uint32_t isn) +{ + struct psi *psi = is->data; + int idx = isn - psi->interrupt; + const char *name; + + if (idx < ARRAY_SIZE(psi_p9_irq_names)) + name = psi_p9_irq_names[idx]; + else + name = "unknown!"; + + prerror("PSI[0x%03x]: Masking unhandled LSI %d (%s)\n", + psi->chip_id, idx, name); + + /* + * All the PSI interrupts are LSIs and will be constantly re-fired + * unless the underlying interrupt condition is cleared. If we don't + * have a handler for the interrupt then it needs to be masked to + * prevent the IRQ from locking up the thread which handles it. + */ + xive_source_mask(is, isn); + +} + static void psihb_p9_interrupt(struct irq_source *is, uint32_t isn) { struct psi *psi = is->data; @@ -543,21 +567,17 @@ static void psihb_p9_interrupt(struct irq_source *is, uint32_t isn) case P9_PSI_IRQ_OCC: occ_p9_interrupt(psi->chip_id); break; - case P9_PSI_IRQ_FSI: - printf("PSI: FSI irq received\n"); - break; case P9_PSI_IRQ_LPCHC: lpc_interrupt(psi->chip_id); break; case P9_PSI_IRQ_LOCAL_ERR: prd_psi_interrupt(psi->chip_id); break; - case P9_PSI_IRQ_GLOBAL_ERR: - printf("PSI: Global error irq received\n"); - break; case P9_PSI_IRQ_EXTERNAL: if (platform.external_irq) platform.external_irq(psi->chip_id); + else + psi_p9_mask_unhandled_irq(is, isn); break; case P9_PSI_IRQ_LPC_SIRQ0: case P9_PSI_IRQ_LPC_SIRQ1: @@ -575,6 +595,9 @@ static void psihb_p9_interrupt(struct irq_source *is, uint32_t isn) case P9_PSI_IRQ_PSU: p9_sbe_interrupt(psi->chip_id); break; + + default: + psi_p9_mask_unhandled_irq(is, isn); } } @@ -2732,6 +2732,13 @@ static char *xive_source_name(struct irq_source *is, uint32_t isn) return s->orig_ops->name(is, isn); } +void xive_source_mask(struct irq_source *is, uint32_t isn) +{ + struct xive_src *s = container_of(is, struct xive_src, is); + + xive_update_irq_mask(s, isn - s->esb_base, true); +} + static const struct irq_source_ops xive_irq_source_ops = { .get_xive = xive_source_get_xive, .set_xive = xive_source_set_xive, diff --git a/include/xive.h b/include/xive.h index 4100e71..b88cdab 100644 --- a/include/xive.h +++ b/include/xive.h @@ -512,4 +512,6 @@ void *xive_get_trigger_port(uint32_t girq); struct irq_source; void __xive_source_eoi(struct irq_source *is, uint32_t isn); +void xive_source_mask(struct irq_source *is, uint32_t isn); + #endif /* __XIVE_H__ */ |