From: Mattias Nissler <mnissler@meta.com>
To: <linux-pci@vger.kernel.org>
Cc: "Martin Mareš" <mj@ucw.cz>, "Mattias Nissler" <mnissler@meta.com>
Subject: [PATCH pciutils v2] ls-ecaps: Decode DPC RP PIO registers
Date: Thu, 16 Apr 2026 23:49:31 -0700 [thread overview]
Message-ID: <20260417064931.2073728-1-mnissler@meta.com> (raw)
The RP PIO registers in the DPC extended capability contain status
information and control bits related to how root ports handle failing
requests.
Sample output:
Capabilities: [380 v1] Downstream Port Containment
DpcCap: IntMsgNum 0, RPExt+ PoisonedTLP+ SwTrigger+ RP PIO Log 6, DL_ActiveErr+
DpcCtl: Trigger:0 Cmpl+ INT+ ErrCor+ PoisonedTLP- SwTrigger- DL_ActiveErr-
DpcSta: Trigger- Reason:00 INT- RPBusy- TriggerExt:00 RP PIO ErrPtr:11
Source: 0000
RP PIO:
Sta: CfgUR+ CfgCA- CfgCTO- IOUR- IOCA- IOCTO- MemUR- MemCA+ MemCTO-
Msk: CfgUR+ CfgCA+ CfgCTO+ IOUR+ IOCA+ IOCTO+ MemUR- MemCA- MemCTO-
Sev: CfgUR- CfgCA- CfgCTO- IOUR- IOCA- IOCTO- MemUR- MemCA- MemCTO-
Err: CfgUR- CfgCA- CfgCTO- IOUR- IOCA- IOCTO- MemUR- MemCA- MemCTO-
Exc: CfgUR- CfgCA- CfgCTO- IOUR- IOCA- IOCTO- MemUR- MemCA- MemCTO-
HeaderLog: 00001001 0000220f f7a01100 00000000
ImpSpecLog: 00000000
TLPPrefixLog: 00000000
Signed-off-by: Mattias Nissler <mnissler@meta.com>
---
Changes:
v2:
* fix style issues
* correct DW read index for prefix log
---
| 18 ++++++++++
ls-ecaps.c | 97 +++++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 102 insertions(+), 13 deletions(-)
--git a/lib/header.h b/lib/header.h
index 21fb628..507080f 100644
--- a/lib/header.h
+++ b/lib/header.h
@@ -1454,6 +1454,7 @@
#define PCI_DPC_CAP_SW_TRIGGER 0x80 /* DPC Software Trigger */
#define PCI_DPC_CAP_RP_LOG(x) (((x) >> 8) & 0xf) /* DPC RP PIO Log Size */
#define PCI_DPC_CAP_DL_ACT_ERR 0x1000 /* DPC DL_Active ERR_COR Signal */
+#define PCI_DPC_CAP_RP_PIO_LOG_SIZE4 0x2000 /* RP PIO Log Size [4] */
#define PCI_DPC_CTL 6 /* DPC Control */
#define PCI_DPC_CTL_TRIGGER(x) ((x) & 0x3) /* DPC Trigger Enable */
#define PCI_DPC_CTL_CMPL 0x4 /* DPC Completion Control */
@@ -1470,6 +1471,23 @@
#define PCI_DPC_STS_TRIGGER_EXT(x) (((x) >> 5) & 0x3) /* Trigger Reason Extension */
#define PCI_DPC_STS_PIO_FEP(x) (((x) >> 8) & 0x1f) /* DPC PIO First Error Pointer */
#define PCI_DPC_SOURCE 10 /* DPC Source ID */
+#define PCI_DPC_RP_PIO_STATUS 0xc /* DPC RP PIO Status */
+#define PCI_DPC_RP_PIO_CFG_UR 0x00000001 /* Cfg Request UR Completion */
+#define PCI_DPC_RP_PIO_CFG_CA 0x00000002 /* Cfg Request CA Completion */
+#define PCI_DPC_RP_PIO_CFG_CTO 0x00000004 /* Cfg Request Completion Timeout */
+#define PCI_DPC_RP_PIO_IO_UR 0x00000100 /* I/O Request UR Completion */
+#define PCI_DPC_RP_PIO_IO_CA 0x00000200 /* I/O Request CA Completion */
+#define PCI_DPC_RP_PIO_IO_CTO 0x00000400 /* I/O Request Completion Timeout */
+#define PCI_DPC_RP_PIO_MEM_UR 0x00010000 /* Mem Request UR Completion */
+#define PCI_DPC_RP_PIO_MEM_CA 0x00020000 /* Mem Request CA Completion */
+#define PCI_DPC_RP_PIO_MEM_CTO 0x00040000 /* Mem Request Completion Timeout */
+#define PCI_DPC_RP_PIO_MASK 0x10 /* DPC RP PIO Mask */
+#define PCI_DPC_RP_PIO_SEVERITY 0x14 /* DPC RP PIO Severity */
+#define PCI_DPC_RP_PIO_SYSERROR 0x18 /* DPC RP PIO SysError */
+#define PCI_DPC_RP_PIO_EXCEPTION 0x1c /* DPC RP PIO Exception */
+#define PCI_DPC_RP_PIO_HEADER_LOG 0x20 /* DPC RP PIO Header Log */
+#define PCI_DPC_RP_PIO_IMPSPEC_LOG 0x30 /* DPC RP PIO ImpSpec Log */
+#define PCI_DPC_RP_PIO_TLP_PREFIX_LOG 0x34 /* DPC RP PIO TLP Prefix Log */
/* L1 PM Substates Extended Capability */
#define PCI_L1PM_SUBSTAT_CAP 0x4 /* L1 PM Substate Capability */
diff --git a/ls-ecaps.c b/ls-ecaps.c
index 455c203..61a4dee 100644
--- a/ls-ecaps.c
+++ b/ls-ecaps.c
@@ -233,7 +233,9 @@ cap_aer(struct device *d, int where, int type)
static void cap_dpc(struct device *d, int where)
{
- u16 l;
+ u16 cap, w, log_size;
+ u32 l, l0, l1, l2, l3;
+ int i;
printf("Downstream Port Containment\n");
if (verbose < 2)
@@ -242,24 +244,93 @@ static void cap_dpc(struct device *d, int where)
if (!config_fetch(d, where + PCI_DPC_CAP, 8))
return;
- l = get_conf_word(d, where + PCI_DPC_CAP);
+ w = cap = get_conf_word(d, where + PCI_DPC_CAP);
+ log_size = PCI_DPC_CAP_RP_LOG(cap) | (!!(PCI_DPC_CAP_RP_PIO_LOG_SIZE4 & cap) << 4);
printf("\t\tDpcCap:\tIntMsgNum %d, RPExt%c PoisonedTLP%c SwTrigger%c RP PIO Log %d, DL_ActiveErr%c\n",
- PCI_DPC_CAP_INT_MSG(l), FLAG(l, PCI_DPC_CAP_RP_EXT), FLAG(l, PCI_DPC_CAP_TLP_BLOCK),
- FLAG(l, PCI_DPC_CAP_SW_TRIGGER), PCI_DPC_CAP_RP_LOG(l), FLAG(l, PCI_DPC_CAP_DL_ACT_ERR));
+ PCI_DPC_CAP_INT_MSG(w), FLAG(w, PCI_DPC_CAP_RP_EXT), FLAG(w, PCI_DPC_CAP_TLP_BLOCK),
+ FLAG(w, PCI_DPC_CAP_SW_TRIGGER), log_size, FLAG(w, PCI_DPC_CAP_DL_ACT_ERR));
- l = get_conf_word(d, where + PCI_DPC_CTL);
+ w = get_conf_word(d, where + PCI_DPC_CTL);
printf("\t\tDpcCtl:\tTrigger:%x Cmpl%c INT%c ErrCor%c PoisonedTLP%c SwTrigger%c DL_ActiveErr%c\n",
- PCI_DPC_CTL_TRIGGER(l), FLAG(l, PCI_DPC_CTL_CMPL), FLAG(l, PCI_DPC_CTL_INT),
- FLAG(l, PCI_DPC_CTL_ERR_COR), FLAG(l, PCI_DPC_CTL_TLP), FLAG(l, PCI_DPC_CTL_SW_TRIGGER),
- FLAG(l, PCI_DPC_CTL_DL_ACTIVE));
+ PCI_DPC_CTL_TRIGGER(w), FLAG(w, PCI_DPC_CTL_CMPL), FLAG(w, PCI_DPC_CTL_INT),
+ FLAG(w, PCI_DPC_CTL_ERR_COR), FLAG(w, PCI_DPC_CTL_TLP), FLAG(w, PCI_DPC_CTL_SW_TRIGGER),
+ FLAG(w, PCI_DPC_CTL_DL_ACTIVE));
- l = get_conf_word(d, where + PCI_DPC_STATUS);
+ w = get_conf_word(d, where + PCI_DPC_STATUS);
printf("\t\tDpcSta:\tTrigger%c Reason:%02x INT%c RPBusy%c TriggerExt:%02x RP PIO ErrPtr:%02x\n",
- FLAG(l, PCI_DPC_STS_TRIGGER), PCI_DPC_STS_REASON(l), FLAG(l, PCI_DPC_STS_INT),
- FLAG(l, PCI_DPC_STS_RP_BUSY), PCI_DPC_STS_TRIGGER_EXT(l), PCI_DPC_STS_PIO_FEP(l));
+ FLAG(w, PCI_DPC_STS_TRIGGER), PCI_DPC_STS_REASON(w), FLAG(w, PCI_DPC_STS_INT),
+ FLAG(w, PCI_DPC_STS_RP_BUSY), PCI_DPC_STS_TRIGGER_EXT(w), PCI_DPC_STS_PIO_FEP(w));
+
+ w = get_conf_word(d, where + PCI_DPC_SOURCE);
+ printf("\t\tSource:\t%04x\n", w);
- l = get_conf_word(d, where + PCI_DPC_SOURCE);
- printf("\t\tSource:\t%04x\n", l);
+ if ((cap & PCI_DPC_CAP_RP_EXT) && config_fetch(d, where + PCI_DPC_CAP + 8, 20 + 4 * log_size))
+ {
+ printf("\t\tRP PIO:\n");
+
+ l = get_conf_long(d, where + PCI_DPC_RP_PIO_STATUS);
+ printf("\t\t\tSta: CfgUR%c CfgCA%c CfgCTO%c IOUR%c IOCA%c IOCTO%c MemUR%c MemCA%c MemCTO%c\n",
+ FLAG(l, PCI_DPC_RP_PIO_CFG_UR), FLAG(l, PCI_DPC_RP_PIO_CFG_CA),
+ FLAG(l, PCI_DPC_RP_PIO_CFG_CTO), FLAG(l, PCI_DPC_RP_PIO_IO_UR),
+ FLAG(l, PCI_DPC_RP_PIO_IO_CA), FLAG(l, PCI_DPC_RP_PIO_IO_CTO),
+ FLAG(l, PCI_DPC_RP_PIO_MEM_UR), FLAG(l, PCI_DPC_RP_PIO_MEM_CA),
+ FLAG(l, PCI_DPC_RP_PIO_MEM_CTO));
+
+ l = get_conf_long(d, where + PCI_DPC_RP_PIO_MASK);
+ printf("\t\t\tMsk: CfgUR%c CfgCA%c CfgCTO%c IOUR%c IOCA%c IOCTO%c MemUR%c MemCA%c MemCTO%c\n",
+ FLAG(l, PCI_DPC_RP_PIO_CFG_UR), FLAG(l, PCI_DPC_RP_PIO_CFG_CA),
+ FLAG(l, PCI_DPC_RP_PIO_CFG_CTO), FLAG(l, PCI_DPC_RP_PIO_IO_UR),
+ FLAG(l, PCI_DPC_RP_PIO_IO_CA), FLAG(l, PCI_DPC_RP_PIO_IO_CTO),
+ FLAG(l, PCI_DPC_RP_PIO_MEM_UR), FLAG(l, PCI_DPC_RP_PIO_MEM_CA),
+ FLAG(l, PCI_DPC_RP_PIO_MEM_CTO));
+
+ l = get_conf_long(d, where + PCI_DPC_RP_PIO_SEVERITY);
+ printf("\t\t\tSev: CfgUR%c CfgCA%c CfgCTO%c IOUR%c IOCA%c IOCTO%c MemUR%c MemCA%c MemCTO%c\n",
+ FLAG(l, PCI_DPC_RP_PIO_CFG_UR), FLAG(l, PCI_DPC_RP_PIO_CFG_CA),
+ FLAG(l, PCI_DPC_RP_PIO_CFG_CTO), FLAG(l, PCI_DPC_RP_PIO_IO_UR),
+ FLAG(l, PCI_DPC_RP_PIO_IO_CA), FLAG(l, PCI_DPC_RP_PIO_IO_CTO),
+ FLAG(l, PCI_DPC_RP_PIO_MEM_UR), FLAG(l, PCI_DPC_RP_PIO_MEM_CA),
+ FLAG(l, PCI_DPC_RP_PIO_MEM_CTO));
+
+ l = get_conf_long(d, where + PCI_DPC_RP_PIO_SYSERROR);
+ printf("\t\t\tErr: CfgUR%c CfgCA%c CfgCTO%c IOUR%c IOCA%c IOCTO%c MemUR%c MemCA%c MemCTO%c\n",
+ FLAG(l, PCI_DPC_RP_PIO_CFG_UR), FLAG(l, PCI_DPC_RP_PIO_CFG_CA),
+ FLAG(l, PCI_DPC_RP_PIO_CFG_CTO), FLAG(l, PCI_DPC_RP_PIO_IO_UR),
+ FLAG(l, PCI_DPC_RP_PIO_IO_CA), FLAG(l, PCI_DPC_RP_PIO_IO_CTO),
+ FLAG(l, PCI_DPC_RP_PIO_MEM_UR), FLAG(l, PCI_DPC_RP_PIO_MEM_CA),
+ FLAG(l, PCI_DPC_RP_PIO_MEM_CTO));
+
+ l = get_conf_long(d, where + PCI_DPC_RP_PIO_EXCEPTION);
+ printf("\t\t\tExc: CfgUR%c CfgCA%c CfgCTO%c IOUR%c IOCA%c IOCTO%c MemUR%c MemCA%c MemCTO%c\n",
+ FLAG(l, PCI_DPC_RP_PIO_CFG_UR), FLAG(l, PCI_DPC_RP_PIO_CFG_CA),
+ FLAG(l, PCI_DPC_RP_PIO_CFG_CTO), FLAG(l, PCI_DPC_RP_PIO_IO_UR),
+ FLAG(l, PCI_DPC_RP_PIO_IO_CA), FLAG(l, PCI_DPC_RP_PIO_IO_CTO),
+ FLAG(l, PCI_DPC_RP_PIO_MEM_UR), FLAG(l, PCI_DPC_RP_PIO_MEM_CA),
+ FLAG(l, PCI_DPC_RP_PIO_MEM_CTO));
+
+ l0 = get_conf_long(d, where + PCI_DPC_RP_PIO_HEADER_LOG);
+ l1 = get_conf_long(d, where + PCI_DPC_RP_PIO_HEADER_LOG + 4);
+ l2 = get_conf_long(d, where + PCI_DPC_RP_PIO_HEADER_LOG + 8);
+ l3 = get_conf_long(d, where + PCI_DPC_RP_PIO_HEADER_LOG + 12);
+ printf("\t\t\tHeaderLog: %08x %08x %08x %08x\n", l0, l1, l2, l3);
+
+ if (log_size >= 5)
+ {
+ l = get_conf_long(d, where + PCI_DPC_RP_PIO_IMPSPEC_LOG);
+ printf("\t\t\tImpSpecLog: %08x\n", l);
+ }
+
+ if (log_size >= 6)
+ {
+ printf("\t\t\tTLPPrefixLog:");
+ for (i = 5; i < log_size; i++)
+ {
+ l = get_conf_long(d, where + PCI_DPC_RP_PIO_TLP_PREFIX_LOG + (i - 5) * 4);
+ printf(" %08x", l);
+ }
+ printf("\n");
+ }
+ }
}
static void
--
2.52.0
reply other threads:[~2026-04-17 6:49 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260417064931.2073728-1-mnissler@meta.com \
--to=mnissler@meta.com \
--cc=linux-pci@vger.kernel.org \
--cc=mj@ucw.cz \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox