aboutsummaryrefslogtreecommitdiff
path: root/hw/phb4.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/phb4.c')
-rw-r--r--hw/phb4.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/hw/phb4.c b/hw/phb4.c
index b578ae8..3f22a2c 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -114,7 +114,7 @@
#include <nvram.h>
/* Enable this to disable error interrupts for debug purposes */
-#define DISABLE_ERR_INTS
+#undef DISABLE_ERR_INTS
static void phb4_init_hw(struct phb4 *p);
@@ -3538,6 +3538,33 @@ static void phb4_int_unmask_all(struct phb4 *p)
out_be64(p->regs + PHB_RXE_TCE_ERR_IRQ_ENABLE, 0x60510050c0000000ull);
}
+/*
+ * Mask the IRQ for any currently set error bits. This prevents the PHB's ERR
+ * and INF interrupts from being re-fired before the kernel can handle the
+ * underlying condition.
+ */
+static void phb4_int_mask_active(struct phb4 *p)
+{
+ const uint64_t error_regs[] = {
+ PHB_ERR_STATUS,
+ PHB_TXE_ERR_STATUS,
+ PHB_RXE_ARB_ERR_STATUS,
+ PHB_RXE_MRG_ERR_STATUS,
+ PHB_RXE_TCE_ERR_STATUS
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(error_regs); i++) {
+ uint64_t stat, mask;
+
+ /* The IRQ mask reg is always offset 0x20 from the status reg */
+ stat = phb4_read_reg(p, error_regs[i]);
+ mask = phb4_read_reg(p, error_regs[i] + 0x20);
+
+ phb4_write_reg(p, error_regs[i] + 0x20, mask & ~stat);
+ }
+}
+
static uint64_t phb4_get_pesta(struct phb4 *p, uint64_t pe_number)
{
uint64_t pesta;
@@ -3855,6 +3882,14 @@ static int64_t phb4_eeh_next_error(struct phb *phb,
*severity = OPAL_EEH_SEV_NO_ERROR;
phb4_set_err_pending(p, false);
}
+
+ /*
+ * Unmask all our error interrupts once all pending errors
+ * have been handled.
+ */
+ if (!phb4_err_pending(p))
+ phb4_int_unmask_all(p);
+
return OPAL_SUCCESS;
}
@@ -5593,6 +5628,9 @@ static void phb4_err_interrupt(struct irq_source *is, uint32_t isn)
PHBDBG(p, "Got interrupt 0x%08x\n", isn);
+ /* mask the interrupt conditions to prevent it from re-firing */
+ phb4_int_mask_active(p);
+
/* Update pending event */
opal_update_pending_evt(OPAL_EVENT_PCI_ERROR,
OPAL_EVENT_PCI_ERROR);