diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2018-04-10 17:01:54 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.ibm.com> | 2018-04-11 17:59:57 -0500 |
commit | 9c21cae5aac4246ac4e438cac5a96a24907676c7 (patch) | |
tree | 2a68c58cc0adff8abc234105bb2a548885f9a995 | |
parent | 379ec78e3da982cd1dff1533d50a9b29b025db5b (diff) | |
download | skiboot-9c21cae5aac4246ac4e438cac5a96a24907676c7.zip skiboot-9c21cae5aac4246ac4e438cac5a96a24907676c7.tar.gz skiboot-9c21cae5aac4246ac4e438cac5a96a24907676c7.tar.bz2 |
interrupts: Create an "interrupts" property in the OPAL node
Deprecate the old "opal-interrupts", it's still there, but the new
property follows the standard and allow us to specify whether an
interrupt is level or edge sensitive.
Similarly create "interrupt-names" whose content is identical to
"opal-interrupts-names".
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
-rw-r--r-- | core/interrupts.c | 33 | ||||
-rw-r--r-- | hw/lpc.c | 2 | ||||
-rw-r--r-- | hw/npu.c | 2 | ||||
-rw-r--r-- | hw/npu2.c | 2 | ||||
-rw-r--r-- | hw/p7ioc-phb.c | 2 | ||||
-rw-r--r-- | hw/p7ioc.c | 2 | ||||
-rw-r--r-- | hw/phb3.c | 2 | ||||
-rw-r--r-- | hw/phb4.c | 2 | ||||
-rw-r--r-- | hw/psi.c | 6 | ||||
-rw-r--r-- | include/interrupts.h | 3 |
10 files changed, 39 insertions, 17 deletions
diff --git a/core/interrupts.c b/core/interrupts.c index 9161960..50ff77a 100644 --- a/core/interrupts.c +++ b/core/interrupts.c @@ -224,14 +224,21 @@ void add_opal_interrupts(void) continue; for (isn = is->start; isn < is->end; isn++) { uint64_t attr = is->ops->attributes(is, isn); + uint32_t iflags; char *name; if (attr & IRQ_ATTR_TARGET_LINUX) continue; + if (attr & IRQ_ATTR_TYPE_MSI) + iflags = 0; + else + iflags = 1; name = is->ops->name ? is->ops->name(is, isn) : NULL; ns = name ? strlen(name) : 0; - prlog(PR_DEBUG, "irq %x name: %s (%d/%d)\n", - isn, name ? name : "<null>", ns, tns); + prlog(PR_DEBUG, "irq %x name: %s %s\n", + isn, + name ? name : "<null>", + iflags ? "[level]" : "[edge]"); names = realloc(names, tns + ns + 1); if (name) { strcpy(names + tns, name); @@ -240,20 +247,32 @@ void add_opal_interrupts(void) } else names[tns++] = 0; i = count++; - irqs = realloc(irqs, 4 * count); - irqs[i] = isn; + irqs = realloc(irqs, 8 * count); + irqs[i*2] = isn; + irqs[i*2+1] = iflags; } } unlock(&irq_lock); - /* The opal-interrupts property has one cell per interrupt, - * it is not a standard interrupt property. + /* First create the standard "interrupts" property and the + * corresponding names property + */ + dt_add_property_cells(opal_node, "interrupt-parent", get_ics_phandle()); + dt_add_property(opal_node, "interrupts", irqs, count * 8); + dt_add_property(opal_node, "opal-interrupts-names", names, tns); + dt_add_property(opal_node, "interrupt-names", names, tns); + + /* Now "reduce" it to the old style "opal-interrupts" property + * format by stripping out the flags. The "opal-interrupts" + * property has one cell per interrupt, it is not a standard + * "interrupt" property. * * Note: Even if empty, create it, otherwise some bogus error * handling in Linux can cause problems. */ + for (i = 1; i < count; i++) + irqs[i] = irqs[i * 2]; dt_add_property(opal_node, "opal-interrupts", irqs, count * 4); - dt_add_property(opal_node, "opal-interrupts-names", names, tns); free(irqs); free(names); @@ -757,7 +757,7 @@ unsigned int lpc_get_irq_policy(uint32_t chip_id, uint32_t psi_idx) if (c->lpc->sirq_ralloc[psi_idx] == LPC_ROUTE_LINUX) return IRQ_ATTR_TARGET_LINUX; else - return IRQ_ATTR_TARGET_OPAL; + return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TYPE_LSI; } static void lpc_create_int_map(struct lpcm *lpc, struct dt_node *psi_node) @@ -617,7 +617,7 @@ static uint64_t npu_lsi_attributes(struct irq_source *is, uint32_t isn) uint32_t idx = isn - p->base_lsi; if (idx >= 4) - return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE; + return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE | IRQ_ATTR_TYPE_LSI; return IRQ_ATTR_TARGET_LINUX; } @@ -1840,7 +1840,7 @@ static uint64_t npu2_ipi_attributes(struct irq_source *is __unused, uint32_t isn if (idx == 18) /* TCE Interrupt - used to detect a frozen PE */ - return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE; + return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE | IRQ_ATTR_TYPE_MSI; else return IRQ_ATTR_TARGET_LINUX; } diff --git a/hw/p7ioc-phb.c b/hw/p7ioc-phb.c index fafd841..e8730f4 100644 --- a/hw/p7ioc-phb.c +++ b/hw/p7ioc-phb.c @@ -2518,7 +2518,7 @@ static uint64_t p7ioc_lsi_attributes(struct irq_source *is __unused, uint32_t irq = (isn & 0x7); if (irq == PHB_LSI_PCIE_ERROR) - return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE; + return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE | IRQ_ATTR_TYPE_LSI; return IRQ_ATTR_TARGET_LINUX; } @@ -584,7 +584,7 @@ static void p7ioc_rgc_interrupt(struct irq_source *is, uint32_t isn) static uint64_t p7ioc_rgc_irq_attributes(struct irq_source *is __unused, uint32_t isn __unused) { - return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE; + return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE | IRQ_ATTR_TYPE_LSI; } static const struct irq_source_ops p7ioc_rgc_irq_ops = { @@ -1969,7 +1969,7 @@ static uint64_t phb3_lsi_attributes(struct irq_source *is, uint32_t isn) uint32_t idx = isn - p->base_lsi; if (idx == PHB3_LSI_PCIE_INF || idx == PHB3_LSI_PCIE_ER) - return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE; + return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE | IRQ_ATTR_TYPE_LSI; #endif return IRQ_ATTR_TARGET_LINUX; } @@ -5003,7 +5003,7 @@ static uint64_t phb4_lsi_attributes(struct irq_source *is __unused, uint32_t idx = isn - p->base_lsi; if (idx == PHB3_LSI_PCIE_INF || idx == PHB3_LSI_PCIE_ER) - return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE; + return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE | IRQ_ATTR_TYPE_LSI; #endif return IRQ_ATTR_TARGET_LINUX; } @@ -377,7 +377,7 @@ static int64_t psi_p7_get_xive(struct irq_source *is, uint32_t isn __unused, static uint64_t psi_p7_irq_attributes(struct irq_source *is __unused, uint32_t isn __unused) { - return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_FREQUENT; + return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_FREQUENT | IRQ_ATTR_TYPE_LSI; } static const uint32_t psi_p8_irq_to_xivr[P8_IRQ_PSI_IRQ_COUNT] = { @@ -530,7 +530,7 @@ static uint64_t psi_p8_irq_attributes(struct irq_source *is, uint32_t isn) psi_ext_irq_policy == EXTERNAL_IRQ_POLICY_LINUX) return IRQ_ATTR_TARGET_LINUX; - attr = IRQ_ATTR_TARGET_OPAL; + attr = IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TYPE_LSI; if (idx == P8_IRQ_PSI_EXTERNAL || idx == P8_IRQ_PSI_LPC || idx == P8_IRQ_PSI_FSP) attr |= IRQ_ATTR_TARGET_FREQUENT; @@ -634,7 +634,7 @@ static uint64_t psi_p9_irq_attributes(struct irq_source *is __unused, if (is_lpc_serirq) return lpc_get_irq_policy(psi->chip_id, idx - P9_PSI_IRQ_LPC_SIRQ0); - return IRQ_ATTR_TARGET_OPAL; + return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TYPE_LSI; } static char *psi_p9_irq_name(struct irq_source *is, uint32_t isn) diff --git a/include/interrupts.h b/include/interrupts.h index b412812..2c4fa7e 100644 --- a/include/interrupts.h +++ b/include/interrupts.h @@ -282,6 +282,9 @@ struct irq_source_ops { /* For OPAL interrupts, estimate frequency */ #define IRQ_ATTR_TARGET_RARE 0x0 #define IRQ_ATTR_TARGET_FREQUENT 0x2 +/* For OPAL interrupts, level vs. edge setting */ +#define IRQ_ATTR_TYPE_LSI 0x0 +#define IRQ_ATTR_TYPE_MSI 0x4 void (*interrupt)(struct irq_source *is, uint32_t isn); void (*eoi)(struct irq_source *is, uint32_t isn); char *(*name)(struct irq_source *is, uint32_t isn); |