diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2017-04-21 08:59:57 +1000 |
---|---|---|
committer | Michael Neuling <mikey@neuling.org> | 2017-04-21 11:36:13 +1000 |
commit | 2889f18cef25f13587bc6982003af0ce42e0d3a5 (patch) | |
tree | 7efd666945ef3eb226e3a1396482fa691e2cf732 /hw | |
parent | e780f230b141e5ba5b0098faf0a9e9d7c1482efe (diff) | |
download | skiboot-2889f18cef25f13587bc6982003af0ce42e0d3a5.zip skiboot-2889f18cef25f13587bc6982003af0ce42e0d3a5.tar.gz skiboot-2889f18cef25f13587bc6982003af0ce42e0d3a5.tar.bz2 |
xive: Fix potential for lost IPIs when manipulating CPPR
We don't trigger the IPI in set_mfrr() if the CPPR of the
destination is more favored than the MFRR. However, we fail
to re-evaluate it when the CPPR later changes.
This fixes it. The way this is implemented can lead to
spurious IPIs but these are harmless.
(Mikey remove bogus line setting xs->ipi_sent)
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Michael Neuling <mikey@neuling.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/xive.c | 33 |
1 files changed, 19 insertions, 14 deletions
@@ -3066,6 +3066,22 @@ static inline uint8_t opal_xive_check_pending(struct xive_cpu_state *xs, return xs->pending & mask; } +static void opal_xive_update_cppr(struct xive_cpu_state *xs, u8 cppr) +{ + /* Peform the update */ + xs->cppr = cppr; + out_8(xs->tm_ring1 + TM_QW3_HV_PHYS + TM_CPPR, cppr); + + /* Trigger the IPI if it's still more favored than the CPPR + * + * This can lead to a bunch of spurrious retriggers if the + * IPI is queued up behind other interrupts but that's not + * a big deal and keeps the code simpler + */ + if (xs->mfrr < cppr) + xive_ipi_trigger(xs->xive, GIRQ_TO_IDX(xs->ipi_irq)); +} + static int64_t opal_xive_eoi(uint32_t xirr) { struct cpu_thread *c = this_cpu(); @@ -3150,13 +3166,6 @@ static int64_t opal_xive_eoi(uint32_t xirr) /* Is it an IPI ? */ if (special_ipi) { xive_ipi_eoi(src_x, idx); - - /* Check mfrr and eventually re-trigger. We check - * against the new CPPR since we are about to update - * the HW. - */ - if (xs->mfrr < cppr) - xive_ipi_trigger(src_x, idx); } else { /* Otherwise go through the source mechanism */ xive_vdbg(src_x, "EOI of IDX %x in EXT range\n", idx); @@ -3167,8 +3176,7 @@ static int64_t opal_xive_eoi(uint32_t xirr) } /* Finally restore CPPR */ - xs->cppr = cppr; - out_8(xs->tm_ring1 + TM_QW3_HV_PHYS + TM_CPPR, cppr); + opal_xive_update_cppr(xs, cppr); xive_cpu_vdbg(c, " pending=0x%x cppr=%d\n", xs->pending, cppr); @@ -3297,8 +3305,7 @@ static int64_t opal_xive_get_xirr(uint32_t *out_xirr, bool just_poll) } else { /* Nothing was active, this is a fluke, restore CPPR */ - xs->cppr = old_cppr; - out_8(xs->tm_ring1 + TM_QW3_HV_PHYS + TM_CPPR, old_cppr); + opal_xive_update_cppr(xs, old_cppr); xive_cpu_vdbg(c, " nothing active, restored CPPR to %d\n", old_cppr); } @@ -3328,9 +3335,7 @@ static int64_t opal_xive_set_cppr(uint8_t cppr) xive_cpu_vdbg(c, "CPPR setting to %d\n", cppr); lock(&xs->lock); - c->xstate->cppr = cppr; - out_8(xs->tm_ring1 + TM_QW3_HV_PHYS + TM_CPPR, cppr); - + opal_xive_update_cppr(xs, cppr); unlock(&xs->lock); return OPAL_SUCCESS; |