Commit 17328f21 authored by Frederic Barrat's avatar Frederic Barrat Committed by Michael Ellerman

powerpc/xive: Discard ESB load value when interrupt is invalid

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: da15c03b ("powerpc/xive: Implement get_irqchip_state method for XIVE to fix shutdown race")
Cc: stable@vger.kernel.org # v5.4+
Signed-off-by: default avatarFrederic Barrat <fbarrat@linux.ibm.com>
[clg: wrote a commit log, introduced XIVE_ESB_INVALID ]
Signed-off-by: default avatarCédric Le Goater <clg@kaod.org>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200113130118.27969-1-clg@kaod.org
parent a2db55dd
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#define XIVE_ESB_VAL_P 0x2 #define XIVE_ESB_VAL_P 0x2
#define XIVE_ESB_VAL_Q 0x1 #define XIVE_ESB_VAL_Q 0x1
#define XIVE_ESB_INVALID 0xFF
/* /*
* Thread Management (aka "TM") registers * Thread Management (aka "TM") registers
......
...@@ -972,12 +972,21 @@ static int xive_get_irqchip_state(struct irq_data *data, ...@@ -972,12 +972,21 @@ static int xive_get_irqchip_state(struct irq_data *data,
enum irqchip_irq_state which, bool *state) enum irqchip_irq_state which, bool *state)
{ {
struct xive_irq_data *xd = irq_data_get_irq_handler_data(data); struct xive_irq_data *xd = irq_data_get_irq_handler_data(data);
u8 pq;
switch (which) { switch (which) {
case IRQCHIP_STATE_ACTIVE: case IRQCHIP_STATE_ACTIVE:
*state = !xd->stale_p && pq = xive_esb_read(xd, XIVE_ESB_GET);
(xd->saved_p ||
!!(xive_esb_read(xd, XIVE_ESB_GET) & XIVE_ESB_VAL_P)); /*
* 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; return 0;
default: default:
return -EINVAL; return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment