aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2017-04-27 15:56:39 +0200
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-04-28 15:11:15 +1000
commit0bca35a2570f1dc24c8eb6a36113e7bce28bdc99 (patch)
treef18cd8e15de43661c4a0e3b325c48f0b1f355033 /hw
parent0aff8c2f9e6d60a71bdbd7c6e06df3e4f1debccd (diff)
downloadskiboot-0bca35a2570f1dc24c8eb6a36113e7bce28bdc99.zip
skiboot-0bca35a2570f1dc24c8eb6a36113e7bce28bdc99.tar.gz
skiboot-0bca35a2570f1dc24c8eb6a36113e7bce28bdc99.tar.bz2
xive+phb4: Fix exposing trigger page to Linux
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@kernel.crashing.org> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/phb4.c3
-rw-r--r--hw/xive.c15
2 files changed, 14 insertions, 4 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)