aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOliver O'Halloran <oohall@gmail.com>2019-09-05 20:50:41 +1000
committerOliver O'Halloran <oohall@gmail.com>2019-09-06 16:59:59 +1000
commitfa161cd89fbf6f543f302651a0fd447b8dfc8b06 (patch)
tree533fe230300e57761a7210a251ddd4d357519505
parentfb2f03ea913793caa5f82e1181d1efd5c159ca91 (diff)
downloadskiboot-fa161cd89fbf6f543f302651a0fd447b8dfc8b06.zip
skiboot-fa161cd89fbf6f543f302651a0fd447b8dfc8b06.tar.gz
skiboot-fa161cd89fbf6f543f302651a0fd447b8dfc8b06.tar.bz2
hw/psi-p9: Mask OPAL-owned LSIs without handlers
Some versions of Swift have the TPM interrupt line of the second chip pulled up instead of down. This causes the PSI's external (TPM) interrupt to constantly re-fire since it's an LSI and the interrupt signal is constantly active. There's nothing that can be done to clear the underlying interrupt condition so we to ensure that it's masked. The problem isn't really specific to the external interrupt and will occur for any of the PSI interrupts that don't have an actual handler (FSP, global error, and sometimes the external). When one of these is delivered to OPAL we should log that it happened and mask it to prevent re-firing. Reviewed-by: Cédric Le Goater <clg@kaod.org> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
-rw-r--r--hw/psi.c35
-rw-r--r--hw/xive.c7
-rw-r--r--include/xive.h2
3 files changed, 38 insertions, 6 deletions
diff --git a/hw/psi.c b/hw/psi.c
index 70cf120..d466f5a 100644
--- a/hw/psi.c
+++ b/hw/psi.c
@@ -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);
}
}
diff --git a/hw/xive.c b/hw/xive.c
index 5dc6659..96a9bc6 100644
--- a/hw/xive.c
+++ b/hw/xive.c
@@ -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__ */