[Skiboot] [PATCH 16/60] xive/phb4: Handle bad ESB offsets in PHB4 DD1
Benjamin Herrenschmidt
benh at kernel.crashing.org
Thu Dec 22 14:16:24 AEDT 2016
Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
---
hw/phb4.c | 6 ++++--
hw/xive.c | 23 ++++++++++++++++-------
include/opal-api.h | 1 +
include/xive.h | 1 +
4 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/hw/phb4.c b/hw/phb4.c
index 016e2fa..fa8bc7b 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -3205,11 +3205,13 @@ static void phb4_create(struct dt_node *np)
phb4_init_hw(p, true);
/* Register all interrupt sources with XIVE */
- xive_register_hw_source(p->base_msi, p->num_irqs - 8, 16, p->int_mmio, 0,
+ xive_register_hw_source(p->base_msi, p->num_irqs - 8, 16,
+ p->int_mmio, XIVE_SRC_SHIFT_BUG,
NULL, NULL);
xive_register_hw_source(p->base_lsi, 8, 16,
p->int_mmio + ((p->num_irqs - 8) << 16),
- XIVE_SRC_LSI, p, &phb4_lsi_ops);
+ XIVE_SRC_LSI | XIVE_SRC_SHIFT_BUG,
+ p, &phb4_lsi_ops);
/* Platform additional setup */
if (platform.pci_setup_phb)
diff --git a/hw/xive.c b/hw/xive.c
index 9784b95..05b9daf 100644
--- a/hw/xive.c
+++ b/hw/xive.c
@@ -1685,13 +1685,19 @@ static int64_t xive_source_get_xive(struct irq_source *is __unused,
static void xive_update_irq_mask(struct xive_src *s, uint32_t idx, bool masked)
{
void *mmio_base = s->esb_mmio + (1ul << s->esb_shift) * idx;
+ uint32_t offset;
if (s->flags & XIVE_SRC_EOI_PAGE1)
mmio_base += 1ull << (s->esb_shift - 1);
if (masked)
- in_be64(mmio_base + 0xd00); /* PQ = 01 */
+ offset = 0xd00; /* PQ = 01 */
else
- in_be64(mmio_base + 0xc00); /* PQ = 00 */
+ offset = 0xc00; /* PQ = 00 */
+
+ if (s->flags & XIVE_SRC_SHIFT_BUG)
+ offset <<= 4;
+
+ in_be64(mmio_base + offset);
}
static int64_t xive_source_set_xive(struct irq_source *is, uint32_t isn,
@@ -1752,17 +1758,20 @@ static void xive_source_eoi(struct irq_source *is, uint32_t isn)
if (s->flags & XIVE_SRC_STORE_EOI)
out_be64(mmio_base, 0);
else {
+ uint64_t offset;
+
/* Otherwise for EOI, we use the special MMIO that does
* a clear of both P and Q and returns the old Q.
*
* This allows us to then do a re-trigger if Q was set
rather than synthetizing an interrupt in software
*/
- if (s->flags & XIVE_SRC_EOI_PAGE1) {
- uint64_t p1off = 1ull << (s->esb_shift - 1);
- eoi_val = in_be64(mmio_base + p1off + 0xc00);
- } else
- eoi_val = in_be64(mmio_base + 0xc00);
+ if (s->flags & XIVE_SRC_EOI_PAGE1)
+ mmio_base += 1ull << (s->esb_shift - 1);
+ offset = 0xc00;
+ if (s->flags & XIVE_SRC_SHIFT_BUG)
+ offset <<= 4;
+ eoi_val = in_be64(mmio_base + offset);
xive_vdbg(s->xive, "ISN: %08x EOI=%llx\n", isn, eoi_val);
if ((s->flags & XIVE_SRC_LSI) || !(eoi_val & 1))
return;
diff --git a/include/opal-api.h b/include/opal-api.h
index 96b8f79..00e2134 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -1091,6 +1091,7 @@ enum {
OPAL_XIVE_IRQ_TRIGGER_PAGE = 0x00000001,
OPAL_XIVE_IRQ_STORE_EOI = 0x00000002,
OPAL_XIVE_IRQ_LSI = 0x00000004,
+ OPAL_XIVE_IRQ_SHIFT_BUG = 0x00000008,
};
/* Flags for OPAL_XIVE_GET/SET_QUEUE_INFO */
diff --git a/include/xive.h b/include/xive.h
index a6dc7be..c1d07c4 100644
--- a/include/xive.h
+++ b/include/xive.h
@@ -414,6 +414,7 @@ uint32_t xive_get_notify_base(uint32_t girq);
#define XIVE_SRC_EOI_PAGE1 OPAL_XIVE_IRQ_TRIGGER_PAGE
#define XIVE_SRC_STORE_EOI OPAL_XIVE_IRQ_STORE_EOI
#define XIVE_SRC_LSI OPAL_XIVE_IRQ_LSI
+#define XIVE_SRC_SHIFT_BUG OPAL_XIVE_IRQ_SHIFT_BUG
struct irq_source_ops;
void xive_register_hw_source(uint32_t base, uint32_t count, uint32_t shift,
--
2.9.3
More information about the Skiboot
mailing list