@@ -3102,7 +3102,7 @@ static int64_t opal_xive_get_xirr(uint32_t *out_xirr, bool just_poll)
break;
case TM_QW3_NSR_HE_PHYS:
/* Mark pending and keep track of the CPPR update */
- if (!just_poll) {
+ if (!just_poll && (ack & 0xff) != 0xff) {
xs->cppr = ack & 0xff;
xs->pending |= 1 << xs->cppr;
}
@@ -3158,6 +3158,12 @@ static int64_t opal_xive_get_xirr(uint32_t *out_xirr, bool just_poll)
if (val)
xive_cpu_vdbg(c, " found irq, prio=%d\n", prio);
+ } 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);
+ xive_cpu_vdbg(c, " nothing active, restored CPPR to %d\n",
+ old_cppr);
}
skip:
There is a theorical possibility that if we don't get any pending interrupt in the queue in opal_xive_get_xirr() due to a spurious notification we leave the CPPR elevated. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- hw/xive.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)