[Skiboot] [PATCH] xive+phb4: Fix exposing trigger page to Linux
Benjamin Herrenschmidt
benh at kernel.crashing.org
Thu Apr 27 23:56:39 AEST 2017
We currently don't expose the trigger page of MSIs to Linux which
breaks re-sending of a queued one. To fix that properly we need
to understand out a subtle API complication:
- The "internal" XIVE_SRC_TRIGGER_PAGE indicates that a trigger
page is supported, whether it's the same page as the EOI page
or not.
- The "external" OPAL_XIVE_IRQ_TRIGGER_PAGE indicates that a
*separate* trigger page exists. To know if triggers are supported
the caller should simply check if a valid (non-0) value is returned
in "out_trig_page" of opal_xive_get_irq_info().
So PHB4 must set XIVE_SRC_TRIGGER_PAGE for MSIs and the xive code
needs to do the "right" thing for setting whether
OPAL_XIVE_IRQ_TRIGGER_PAGE should be set or not.
Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
---
hw/phb4.c | 3 ++-
hw/xive.c | 15 ++++++++++++---
include/xive.h | 14 +++++++++-----
3 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/hw/phb4.c b/hw/phb4.c
index 12e17bd..e1f0bcb 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -3383,7 +3383,8 @@ static void phb4_create(struct dt_node *np)
/* Register all interrupt sources with XIVE */
xive_register_hw_source(p->base_msi, p->num_irqs - 8, 16,
- p->int_mmio, XIVE_SRC_SHIFT_BUG,
+ p->int_mmio,
+ XIVE_SRC_SHIFT_BUG | XIVE_SRC_TRIGGER_PAGE,
NULL, NULL);
xive_register_hw_source(p->base_lsi, 8, 16,
diff --git a/hw/xive.c b/hw/xive.c
index ed1dc90..1952ce6 100644
--- a/hw/xive.c
+++ b/hw/xive.c
@@ -3372,8 +3372,14 @@ static uint64_t xive_convert_irq_flags(uint64_t iflags)
if (iflags & XIVE_SRC_STORE_EOI)
oflags |= OPAL_XIVE_IRQ_STORE_EOI;
- if (iflags & XIVE_SRC_TRIGGER_PAGE)
+
+ /* OPAL_XIVE_IRQ_TRIGGER_PAGE is only meant to be set if
+ * the interrupt has a *separate* trigger page.
+ */
+ if ((iflags & XIVE_SRC_EOI_PAGE1) &&
+ (iflags & XIVE_SRC_TRIGGER_PAGE))
oflags |= OPAL_XIVE_IRQ_TRIGGER_PAGE;
+
if (iflags & XIVE_SRC_LSI)
oflags |= OPAL_XIVE_IRQ_LSI;
if (iflags & XIVE_SRC_SHIFT_BUG)
@@ -3422,14 +3428,17 @@ static int64_t opal_xive_get_irq_info(uint32_t girq,
mm_base = (uint64_t)s->esb_mmio + (1ull << s->esb_shift) * idx;
+ /* The EOI page can either be the first or second page */
if (s->flags & XIVE_SRC_EOI_PAGE1) {
uint64_t p1off = 1ull << (s->esb_shift - 1);
eoi_page = mm_base + p1off;
- if (s->flags & XIVE_SRC_TRIGGER_PAGE)
- trig_page = mm_base;
} else
eoi_page = mm_base;
+ /* The trigger page, if it exists, is always the first page */
+ if (s->flags & XIVE_SRC_TRIGGER_PAGE)
+ trig_page = mm_base;
+
if (out_eoi_page)
*out_eoi_page = eoi_page;
if (out_trig_page)
diff --git a/include/xive.h b/include/xive.h
index 06aad8b..d2ef1d9 100644
--- a/include/xive.h
+++ b/include/xive.h
@@ -447,11 +447,15 @@ uint64_t xive_get_notify_port(uint32_t chip_id, uint32_t ent);
uint32_t xive_get_notify_base(uint32_t girq);
/* Internal IRQ flags */
-#define XIVE_SRC_TRIGGER_PAGE 0x01
-#define XIVE_SRC_EOI_PAGE1 0x02
-#define XIVE_SRC_STORE_EOI 0x04
-#define XIVE_SRC_LSI 0x08
-#define XIVE_SRC_SHIFT_BUG 0x10
+#define XIVE_SRC_TRIGGER_PAGE 0x01 /* Trigger page exist (either separate
+ * or not, so different from the OPAL
+ * flag which is only set when the
+ * trigger page is separate).
+ */
+#define XIVE_SRC_EOI_PAGE1 0x02 /* EOI on the second page */
+#define XIVE_SRC_STORE_EOI 0x04 /* EOI using stores supported */
+#define XIVE_SRC_LSI 0x08 /* Interrupt is an LSI */
+#define XIVE_SRC_SHIFT_BUG 0x10 /* ESB update offset << 4 */
struct irq_source_ops;
void xive_register_hw_source(uint32_t base, uint32_t count, uint32_t shift,
--
2.9.3
More information about the Skiboot
mailing list