[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