[Skiboot] [PATCH] hw/psi: Add LPC client names to PSI SIRQ interrupts

Nicholas Piggin npiggin at gmail.com
Sat Nov 16 14:59:13 AEDT 2024


Add a name string to LPC client irq sources.

Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
 hw/ast-bmc/ast-mctp.c |  3 +-
 hw/bt.c               |  2 +-
 hw/lpc-mbox.c         |  3 +-
 hw/lpc-uart.c         |  4 +--
 hw/lpc.c              | 33 ++++++++++++++------
 hw/psi.c              | 70 +++++++++++++++++++++++++++----------------
 include/lpc.h         |  5 +++-
 7 files changed, 79 insertions(+), 41 deletions(-)

diff --git a/hw/ast-bmc/ast-mctp.c b/hw/ast-bmc/ast-mctp.c
index 00f66abec..22578e0a5 100644
--- a/hw/ast-bmc/ast-mctp.c
+++ b/hw/ast-bmc/ast-mctp.c
@@ -356,7 +356,8 @@ int ast_mctp_init(void)
 	/* register an lpc client so we get an interrupt */
 	kcs_serial_irq = dt_prop_get_u32(n, "interrupts");
 	kcs_lpc_client.interrupts = LPC_IRQ(kcs_serial_irq);
-	lpc_register_client(dt_get_chip_id(n), &kcs_lpc_client, IRQ_ATTR_TARGET_OPAL);
+	lpc_register_client(dt_get_chip_id(n), &kcs_lpc_client, "lpc-mctp",
+				IRQ_ATTR_TARGET_OPAL);
 
 	return OPAL_SUCCESS;
 
diff --git a/hw/bt.c b/hw/bt.c
index f813185fe..8a88e223e 100644
--- a/hw/bt.c
+++ b/hw/bt.c
@@ -725,7 +725,7 @@ void bt_init(void)
 
 	irq = dt_prop_get_u32(n, "interrupts");
 	bt_lpc_client.interrupts = LPC_IRQ(irq);
-	lpc_register_client(dt_get_chip_id(n), &bt_lpc_client,
+	lpc_register_client(dt_get_chip_id(n), &bt_lpc_client, "lpc-bt",
 			    IRQ_ATTR_TARGET_OPAL);
 
 	/* Enqueue an IPMI message to ask the BMC about its BT capabilities */
diff --git a/hw/lpc-mbox.c b/hw/lpc-mbox.c
index f5bb97ea4..3c58b8843 100644
--- a/hw/lpc-mbox.c
+++ b/hw/lpc-mbox.c
@@ -334,7 +334,8 @@ void mbox_init(void)
 
 	chip_id = dt_get_chip_id(np);
 	mbox_lpc_client.interrupts = LPC_IRQ(irq);
-	lpc_register_client(chip_id, &mbox_lpc_client, IRQ_ATTR_TARGET_OPAL);
+	lpc_register_client(chip_id, &mbox_lpc_client, "lpc-mbox",
+			IRQ_ATTR_TARGET_OPAL);
 
 	/* Enable interrupts */
 	bmc_mbox_outb(MBOX_STATUS_1_ATTN | MBOX_STATUS_1_RESP, MBOX_HOST_INT_EN_1);
diff --git a/hw/lpc-uart.c b/hw/lpc-uart.c
index 834011b37..c0f9c52ff 100644
--- a/hw/lpc-uart.c
+++ b/hw/lpc-uart.c
@@ -493,7 +493,7 @@ static void uart_setup_os_passthrough(void)
 	if (lpc_irq >= 0) {
 		uint32_t chip_id = dt_get_chip_id(uart_node);
 		uart_lpc_os_client.interrupts = LPC_IRQ(lpc_irq);
-		lpc_register_client(chip_id, &uart_lpc_os_client,
+		lpc_register_client(chip_id, &uart_lpc_os_client, "lpc-uart",
 				    IRQ_ATTR_TARGET_LINUX);
 	}
 	prlog(PR_DEBUG, "UART: Enabled as OS pass-through\n");
@@ -525,7 +525,7 @@ static void uart_setup_opal_console(void)
 	if (lpc_irq >= 0) {
 		uint32_t chip_id = dt_get_chip_id(uart_node);
 		uart_lpc_opal_client.interrupts = LPC_IRQ(lpc_irq);
-		lpc_register_client(chip_id, &uart_lpc_opal_client,
+		lpc_register_client(chip_id, &uart_lpc_opal_client, "lpc-uart",
 				    IRQ_ATTR_TARGET_OPAL);
 		has_irq = true;
 	}
diff --git a/hw/lpc.c b/hw/lpc.c
index caaacc461..398528084 100644
--- a/hw/lpc.c
+++ b/hw/lpc.c
@@ -136,6 +136,7 @@ struct lpcm {
 	bool			sirq_routed[LPC_NUM_SERIRQ];
 	uint32_t		sirq_rmasks[4];
 	uint8_t			sirq_ralloc[4];
+	const char		*sirq_name[4];
 	struct dt_node		*node;
 };
 
@@ -881,8 +882,8 @@ static void lpc_route_serirq(struct lpcm *lpc, uint32_t sirq,
 	opb_write(lpc, opb_master_reg_base + reg, val, 4);
 }
 
-static void lpc_alloc_route(struct lpcm *lpc, unsigned int irq,
-			    unsigned int policy)
+static void lpc_alloc_route(struct lpcm *lpc, const char *name,
+			    unsigned int irq, unsigned int policy)
 {
 	unsigned int i, r, c;
 	int route = -1;
@@ -892,8 +893,8 @@ static void lpc_alloc_route(struct lpcm *lpc, unsigned int irq,
 	else
 		r = LPC_ROUTE_LINUX;
 
-	prlog(PR_DEBUG, "Routing irq %d, policy: %d (r=%d)\n",
-	      irq, policy, r);
+	prlog(PR_DEBUG, "Routing %s irq %d, policy: %d (r=%d)\n",
+	      name, irq, policy, r);
 
 	/* Are we already routed ? */
 	if (lpc->sirq_routed[irq] &&
@@ -915,6 +916,7 @@ static void lpc_alloc_route(struct lpcm *lpc, unsigned int irq,
 		 */
 		if (lpc->sirq_ralloc[i] == LPC_ROUTE_FREE && c < 4) {
 			lpc->sirq_ralloc[i] = r;
+			lpc->sirq_name[i] = name;
 			route = i;
 			break;
 		}
@@ -924,8 +926,12 @@ static void lpc_alloc_route(struct lpcm *lpc, unsigned int irq,
 	 * with a matching policy
 	 */
 	for (i = 0; route < 0 && i < 4; i++) {
-		if (lpc->sirq_ralloc[i] == r)
+		if (lpc->sirq_ralloc[i] == r) {
+			prlog(PR_NOTICE, "Muxing PSI SIRQ%d (%s %s)\n", i, name,
+					lpc->sirq_name[i]);
+			lpc->sirq_name[i] = "muxed";
 			route = i;
+		}
 	}
 
 	/* Still no route ? bail. That should never happen */
@@ -954,6 +960,16 @@ unsigned int lpc_get_irq_policy(uint32_t chip_id, uint32_t psi_idx)
 		return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TYPE_LSI;
 }
 
+const char *lpc_get_irq_name(uint32_t chip_id, uint32_t psi_idx)
+{
+	struct proc_chip *c = get_chip(chip_id);
+
+	if (!c || !c->lpc)
+		return NULL;
+
+	return c->lpc->sirq_name[psi_idx];
+}
+
 static void lpc_create_int_map(struct lpcm *lpc, struct dt_node *psi_node)
 {
 	__be32 map[LPC_NUM_SERIRQ * 5], *pmap;
@@ -1432,9 +1448,8 @@ bool lpc_ok(void)
 	return !lock_held_by_me(&chip->lpc->lock);
 }
 
-void lpc_register_client(uint32_t chip_id,
-			 const struct lpc_client *clt,
-			 uint32_t policy)
+void lpc_register_client(uint32_t chip_id, const struct lpc_client *clt,
+			 const char *name, uint32_t policy)
 {
 	struct lpc_client_entry *ent;
 	struct proc_chip *chip;
@@ -1472,7 +1487,7 @@ void lpc_register_client(uint32_t chip_id,
 		unsigned int i;
 		for (i = 0; i < LPC_NUM_SERIRQ; i++)
 			if (clt->interrupts & LPC_IRQ(i))
-				lpc_alloc_route(lpc, i, policy);
+				lpc_alloc_route(lpc, name, i, policy);
 	}
 
 	if (lpc->has_serirq)
diff --git a/hw/psi.c b/hw/psi.c
index aa7e020c7..b16901b56 100644
--- a/hw/psi.c
+++ b/hw/psi.c
@@ -520,17 +520,17 @@ static const char *psi_p9_irq_names[P9_PSI_NUM_IRQS] = {
 	"fsp",
 	"occ",
 	"fsi",
-	"lpchc",
+	"lpc-hc",
 	"local_err",
 	"global_err",
 	"external",
-	"lpc_serirq_mux0", /* Have a callback to get name ? */
-	"lpc_serirq_mux1", /* Have a callback to get name ? */
-	"lpc_serirq_mux2", /* Have a callback to get name ? */
-	"lpc_serirq_mux3", /* Have a callback to get name ? */
+	"lpc-mux0-unused",
+	"lpc-mux1-unused",
+	"lpc-mux2-unused",
+	"lpc-mux3-unused",
 	"i2c",
 	"dio",
-	"psu"
+	"psu(sbe)"
 };
 
 static void psi_p9_mask_all(struct psi *psi)
@@ -623,29 +623,40 @@ static void psihb_p9_interrupt(struct irq_source *is, uint32_t isn)
 	}
 }
 
+static bool is_lpc_serirq(int irq)
+{
+	return (irq == P9_PSI_IRQ_LPC_SIRQ0 ||
+		  irq == P9_PSI_IRQ_LPC_SIRQ1 ||
+		  irq == P9_PSI_IRQ_LPC_SIRQ2 ||
+		  irq == P9_PSI_IRQ_LPC_SIRQ3);
+}
+
+/* PSI SERIRQ to LPC */
+static int lpc_irq_nr(int irq)
+{
+	assert(is_lpc_serirq(irq));
+	return irq - P9_PSI_IRQ_LPC_SIRQ0;
+}
+
 static uint64_t psi_p9_irq_attributes(struct irq_source *is __unused,
 				      uint32_t isn)
 {
 	struct psi *psi = is->data;
-	unsigned int idx = isn & 0xf;
-	bool is_lpc_serirq;
-
-	 is_lpc_serirq =
-		 (idx == P9_PSI_IRQ_LPC_SIRQ0 ||
-		  idx == P9_PSI_IRQ_LPC_SIRQ1 ||
-		  idx == P9_PSI_IRQ_LPC_SIRQ2 ||
-		  idx == P9_PSI_IRQ_LPC_SIRQ3);
-
-	/* If LPC interrupts are disabled, route them to Linux
-	 * (who will not request them since they aren't referenced
-	 * in the device tree)
-	 */
-	 if (is_lpc_serirq && psi->no_lpc_irqs)
-		return IRQ_ATTR_TARGET_LINUX;
+	uint32_t idx = isn - psi->interrupt;
+
+	assert(idx == (isn & 0xf));
+
+	 if (is_lpc_serirq(idx)) {
+		/* If LPC interrupts are disabled, route them to Linux
+		 * (who will not request them since they aren't referenced
+		 * in the device tree)
+		 */
+		 if (psi->no_lpc_irqs)
+			return IRQ_ATTR_TARGET_LINUX;
 
-	 /* For serirq, check the LPC layer for policy */
-	 if (is_lpc_serirq)
-		 return lpc_get_irq_policy(psi->chip_id, idx - P9_PSI_IRQ_LPC_SIRQ0);
+		 /* For serirq, check the LPC layer for policy */
+		 return lpc_get_irq_policy(psi->chip_id, lpc_irq_nr(idx));
+	 }
 
 	/* Only direct external interrupts to OPAL if we have a handler */
 	if (idx == P9_PSI_IRQ_EXTERNAL && !platform.external_irq)
@@ -658,13 +669,20 @@ static char *psi_p9_irq_name(struct irq_source *is, uint32_t isn)
 {
 	struct psi *psi = is->data;
 	uint32_t idx = isn - psi->interrupt;
+	const char *name = NULL;
 	char tmp[30];
 
 	if (idx >= ARRAY_SIZE(psi_p9_irq_names))
 		return NULL;
 
-	snprintf(tmp, sizeof(tmp), "psi#%x:%s",
-		 psi->chip_id, psi_p9_irq_names[idx]);
+	assert(idx == (isn & 0xf));
+
+	 if (is_lpc_serirq(idx))
+		 name = lpc_get_irq_name(psi->chip_id, lpc_irq_nr(idx));
+	if (!name)
+		name = psi_p9_irq_names[idx];
+
+	snprintf(tmp, sizeof(tmp), "psi#%x:%s", psi->chip_id, name);
 
 	return strdup(tmp);
 }
diff --git a/include/lpc.h b/include/lpc.h
index ce9c33dc7..4a62d4d1f 100644
--- a/include/lpc.h
+++ b/include/lpc.h
@@ -82,11 +82,14 @@ struct lpc_client {
 };
 
 extern void lpc_register_client(uint32_t chip_id, const struct lpc_client *clt,
-				uint32_t policy);
+				const char *name, uint32_t policy);
 
 /* Return the policy for a given serirq */
 extern unsigned int lpc_get_irq_policy(uint32_t chip_id, uint32_t psi_idx);
 
+/* Return the name for a given serirq */
+extern const char *lpc_get_irq_name(uint32_t chip_id, uint32_t psi_idx);
+
 /* Default bus accessors that perform error logging */
 extern int64_t lpc_write(enum OpalLPCAddressType addr_type, uint32_t addr,
 			 uint32_t data, uint32_t sz);
-- 
2.45.2



More information about the Skiboot mailing list