aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2018-04-10 17:01:54 +1000
committerStewart Smith <stewart@linux.ibm.com>2018-04-11 17:59:57 -0500
commit9c21cae5aac4246ac4e438cac5a96a24907676c7 (patch)
tree2a68c58cc0adff8abc234105bb2a548885f9a995
parent379ec78e3da982cd1dff1533d50a9b29b025db5b (diff)
downloadskiboot-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.c33
-rw-r--r--hw/lpc.c2
-rw-r--r--hw/npu.c2
-rw-r--r--hw/npu2.c2
-rw-r--r--hw/p7ioc-phb.c2
-rw-r--r--hw/p7ioc.c2
-rw-r--r--hw/phb3.c2
-rw-r--r--hw/phb4.c2
-rw-r--r--hw/psi.c6
-rw-r--r--include/interrupts.h3
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);
diff --git a/hw/lpc.c b/hw/lpc.c
index dbb2d4b..fbc49c5 100644
--- a/hw/lpc.c
+++ b/hw/lpc.c
@@ -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)
diff --git a/hw/npu.c b/hw/npu.c
index 85750c9..08eee61 100644
--- a/hw/npu.c
+++ b/hw/npu.c
@@ -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;
}
diff --git a/hw/npu2.c b/hw/npu2.c
index b243e8e..4122af9 100644
--- a/hw/npu2.c
+++ b/hw/npu2.c
@@ -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;
}
diff --git a/hw/p7ioc.c b/hw/p7ioc.c
index e036433..44ce3d8 100644
--- a/hw/p7ioc.c
+++ b/hw/p7ioc.c
@@ -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 = {
diff --git a/hw/phb3.c b/hw/phb3.c
index f28f568..771ccfc 100644
--- a/hw/phb3.c
+++ b/hw/phb3.c
@@ -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;
}
diff --git a/hw/phb4.c b/hw/phb4.c
index b114c52..30949be 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -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;
}
diff --git a/hw/psi.c b/hw/psi.c
index 69e03e5..70095a6 100644
--- a/hw/psi.c
+++ b/hw/psi.c
@@ -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);