[Skiboot] [PATCH 14/32] xive/phb4: Handle bad ESB offsets in PHB4 DD1

Benjamin Herrenschmidt benh at kernel.crashing.org
Tue Nov 22 13:13:16 AEDT 2016


Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
---
 hw/phb4.c          |  6 ++++--
 hw/xive.c          | 23 ++++++++++++++++-------
 include/opal-api.h |  1 +
 include/xive.h     |  1 +
 4 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/hw/phb4.c b/hw/phb4.c
index 0ba6392..e61e7c5 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -3193,11 +3193,13 @@ static void phb4_create(struct dt_node *np)
 	phb4_init_hw(p, true);
 
 	/* Register all interrupt sources with XIVE */
-	xive_register_hw_source(p->base_msi, p->num_irqs - 8, 16, p->int_mmio, 0,
+	xive_register_hw_source(p->base_msi, p->num_irqs - 8, 16,
+				p->int_mmio, XIVE_SRC_SHIFT_BUG,
 				NULL, NULL);
 	xive_register_hw_source(p->base_lsi, 8, 16,
 				p->int_mmio + ((p->num_irqs - 8) << 16),
-				XIVE_SRC_LSI, p, &phb4_lsi_ops);
+				XIVE_SRC_LSI | XIVE_SRC_SHIFT_BUG,
+				p, &phb4_lsi_ops);
 
 	/* Platform additional setup */
 	if (platform.pci_setup_phb)
diff --git a/hw/xive.c b/hw/xive.c
index 4dfff0d..6a0e9d4 100644
--- a/hw/xive.c
+++ b/hw/xive.c
@@ -1685,13 +1685,19 @@ static int64_t xive_source_get_xive(struct irq_source *is __unused,
 static void xive_update_irq_mask(struct xive_src *s, uint32_t idx, bool masked)
 {
 	void *mmio_base = s->esb_mmio + (1ul << s->esb_shift) * idx;
+	uint32_t offset;
 
 	if (s->flags & XIVE_SRC_EOI_PAGE1)
 		mmio_base += 1ull << (s->esb_shift - 1);
 	if (masked)
-		in_be64(mmio_base + 0xd00); /* PQ = 01 */
+		offset = 0xd00; /* PQ = 01 */
 	else
-		in_be64(mmio_base + 0xc00); /* PQ = 00 */
+		offset = 0xc00; /* PQ = 00 */
+
+	if (s->flags & XIVE_SRC_SHIFT_BUG)
+		offset <<= 4;
+
+	in_be64(mmio_base + offset);
 }
 
 static int64_t xive_source_set_xive(struct irq_source *is, uint32_t isn,
@@ -1752,17 +1758,20 @@ static void xive_source_eoi(struct irq_source *is, uint32_t isn)
 	if (s->flags & XIVE_SRC_STORE_EOI)
 		out_be64(mmio_base, 0);
 	else {
+		uint64_t offset;
+
 		/* Otherwise for EOI, we use the special MMIO that does
 		 * a clear of both P and Q and returns the old Q.
 		 *
 		 * This allows us to then do a re-trigger if Q was set
 		 rather than synthetizing an interrupt in software
 		*/
-		if (s->flags & XIVE_SRC_EOI_PAGE1) {
-			uint64_t p1off = 1ull << (s->esb_shift - 1);
-			eoi_val = in_be64(mmio_base + p1off + 0xc00);
-		} else
-			eoi_val = in_be64(mmio_base + 0xc00);
+		if (s->flags & XIVE_SRC_EOI_PAGE1)
+			mmio_base += 1ull << (s->esb_shift - 1);
+		offset = 0xc00;
+		if (s->flags & XIVE_SRC_SHIFT_BUG)
+			offset <<= 4;
+		eoi_val = in_be64(mmio_base + offset);
 		xive_vdbg(s->xive, "ISN: %08x EOI=%llx\n", isn, eoi_val);
 		if ((s->flags & XIVE_SRC_LSI) || !(eoi_val & 1))
 			return;
diff --git a/include/opal-api.h b/include/opal-api.h
index 27223c6..cecc00e 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -1076,6 +1076,7 @@ enum {
 	OPAL_XIVE_IRQ_TRIGGER_PAGE	= 0x00000001,
 	OPAL_XIVE_IRQ_STORE_EOI		= 0x00000002,
 	OPAL_XIVE_IRQ_LSI		= 0x00000004,
+	OPAL_XIVE_IRQ_SHIFT_BUG		= 0x00000008,
 };
 
 /* Flags for OPAL_XIVE_GET/SET_QUEUE_INFO */
diff --git a/include/xive.h b/include/xive.h
index a6dc7be..c1d07c4 100644
--- a/include/xive.h
+++ b/include/xive.h
@@ -414,6 +414,7 @@ uint32_t xive_get_notify_base(uint32_t girq);
 #define XIVE_SRC_EOI_PAGE1	OPAL_XIVE_IRQ_TRIGGER_PAGE
 #define XIVE_SRC_STORE_EOI	OPAL_XIVE_IRQ_STORE_EOI
 #define XIVE_SRC_LSI		OPAL_XIVE_IRQ_LSI
+#define XIVE_SRC_SHIFT_BUG	OPAL_XIVE_IRQ_SHIFT_BUG
 
 struct irq_source_ops;
 void xive_register_hw_source(uint32_t base, uint32_t count, uint32_t shift,
-- 
2.7.4



More information about the Skiboot mailing list