From: Mattias Nissler Date: Fri, 17 Apr 2026 10:42:23 +0000 (-0700) Subject: ls-ecaps: Decode DPC RP PIO registers X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;p=pciutils.git ls-ecaps: Decode DPC RP PIO registers 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 --- diff --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..8239fd2 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,96 @@ 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); + + 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)); + + if (log_size >= 4) + { + 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); + } - l = get_conf_word(d, where + PCI_DPC_SOURCE); - printf("\t\tSource:\t%04x\n", l); + 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