powerpc/xive: Discard ESB load value when interrupt is invalid
authorFrederic Barrat <fbarrat@linux.ibm.com>
Mon, 13 Jan 2020 13:01:18 +0000 (14:01 +0100)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 22 Jan 2020 09:31:41 +0000 (20:31 +1100)
A load on an ESB page returning all 1's means that the underlying
device has invalidated the access to the PQ state of the interrupt
through mmio. It may happen, for example when querying a PHB interrupt
while the PHB is in an error state.

In that case, we should consider the interrupt to be invalid when
checking its state in the irq_get_irqchip_state() handler.

Fixes: da15c03b047d ("powerpc/xive: Implement get_irqchip_state method for XIVE to fix shutdown race")
Cc: stable@vger.kernel.org # v5.4+
Signed-off-by: Frederic Barrat <fbarrat@linux.ibm.com>
[clg: wrote a commit log, introduced XIVE_ESB_INVALID ]
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200113130118.27969-1-clg@kaod.org
arch/powerpc/include/asm/xive-regs.h
arch/powerpc/sysdev/xive/common.c

index f2dfcd50a2d3e67763b8ebf7f32d20edae34688e..33aee7490cbb1fc2b4ca57a029578f56297c72db 100644 (file)
@@ -39,6 +39,7 @@
 
 #define XIVE_ESB_VAL_P         0x2
 #define XIVE_ESB_VAL_Q         0x1
+#define XIVE_ESB_INVALID       0xFF
 
 /*
  * Thread Management (aka "TM") registers
index f5fadbd2533a8f1c5b5512fba1423a22b714bd34..9651ca061828a06be50d5636508d90505fdcfcc2 100644 (file)
@@ -972,12 +972,21 @@ static int xive_get_irqchip_state(struct irq_data *data,
                                  enum irqchip_irq_state which, bool *state)
 {
        struct xive_irq_data *xd = irq_data_get_irq_handler_data(data);
+       u8 pq;
 
        switch (which) {
        case IRQCHIP_STATE_ACTIVE:
-               *state = !xd->stale_p &&
-                        (xd->saved_p ||
-                         !!(xive_esb_read(xd, XIVE_ESB_GET) & XIVE_ESB_VAL_P));
+               pq = xive_esb_read(xd, XIVE_ESB_GET);
+
+               /*
+                * The esb value being all 1's means we couldn't get
+                * the PQ state of the interrupt through mmio. It may
+                * happen, for example when querying a PHB interrupt
+                * while the PHB is in an error state. We consider the
+                * interrupt to be inactive in that case.
+                */
+               *state = (pq != XIVE_ESB_INVALID) && !xd->stale_p &&
+                       (xd->saved_p || !!(pq & XIVE_ESB_VAL_P));
                return 0;
        default:
                return -EINVAL;