diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2017-04-27 15:56:39 +0200 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-04-28 15:11:15 +1000 |
commit | 0bca35a2570f1dc24c8eb6a36113e7bce28bdc99 (patch) | |
tree | f18cd8e15de43661c4a0e3b325c48f0b1f355033 /hw | |
parent | 0aff8c2f9e6d60a71bdbd7c6e06df3e4f1debccd (diff) | |
download | skiboot-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.c | 3 | ||||
-rw-r--r-- | hw/xive.c | 15 |
2 files changed, 14 insertions, 4 deletions
@@ -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, @@ -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) |