[Skiboot] [RFC][PATCH] interrupts: Create an "interrupts" property in the OPAL node

Benjamin Herrenschmidt benh at kernel.crashing.org
Mon Apr 9 14:46:32 AEST 2018


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 at kernel.crashing.org>
---
 core/interrupts.c    | 32 +++++++++++++++++++++++++-------
 hw/lpc.c             |  2 +-
 hw/npu.c             |  2 +-
 hw/npu2.c            |  2 +-
 hw/p7ioc-phb.c       |  2 +-
 hw/p7ioc.c           |  2 +-
 hw/phb3.c            |  2 +-
 hw/phb4.c            |  2 +-
 hw/psi.c             |  6 +++---
 include/interrupts.h |  3 +++
 10 files changed, 38 insertions(+), 17 deletions(-)

diff --git a/core/interrupts.c b/core/interrupts.c
index 91619602..dfe20e71 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,31 @@ 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(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 dbb2d4b2..fbc49c55 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 85750c92..08eee61c 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 06e06d4f..57992761 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 fafd841e..e8730f48 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 e036433a..44ce3d80 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 f28f568f..771ccfcc 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 323c4939..531e8a62 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -5026,7 +5026,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 69e03e54..70095a63 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 b412812a..2c4fa7e9 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);



More information about the Skiboot mailing list