From: Alex Martens Date: Thu, 13 Nov 2025 22:50:21 +0000 (-0800) Subject: lspci: decode flit logging X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3384df6f24b2565e9e59817dff45000eb6e0e262;p=thirdparty%2Fpciutils.git lspci: decode flit logging The flit logging extended capability is defined in the PCI express base specification revision 6.4. Signed-off-by: Alex Martens --- diff --git a/lib/header.h b/lib/header.h index b68f2a0..17b571a 100644 --- a/lib/header.h +++ b/lib/header.h @@ -1593,6 +1593,63 @@ /* IDE Address Association Register 2 is "Memory Limit Upper" */ /* IDE Address Association Register 3 is "Memory Base Upper" */ +/* Flit Logging Extended Capability */ +#define PCI_FLIT_LOG_ERR1 0x04 /* Flit Error Log 1 Register */ +#define PCI_FLIT_LOG_ERR1_VLD 0x00000001 /* Flit Error Log Valid */ +#define PCI_FLIT_LOG_ERR1_WIDTH(x) (((x) >> 1) & 0x7) /* Flit Error Link Width */ +#define PCI_FLIT_LOG_ERR1_OFFS(x) (((x) >> 4) & 0xf) /* Flit Offset from the Last Logged Flit in Error */ +#define PCI_FLIT_LOG_ERR1_CONS(x) (((x) >> 8) & 0x1f) /* Consecutive Flit Error after the Last Flit Error */ +#define PCI_FLIT_LOG_ERR1_MORE 0x00002000 /* More Entries for Flit Error Log Register are Valid */ +#define PCI_FLIT_LOG_ERR1_UNREC 0x00004000 /* Unrecognized Flit */ +#define PCI_FLIT_LOG_ERR1_UNCOR 0x00008000 /* FEC Uncorrectable Error in Flit */ +#define PCI_FLIT_LOG_ERR1_PAR_GRP0(x) (((x) >> 16) & 0xff) /* Syndrome Parity for ECC Group 0 */ +#define PCI_FLIT_LOG_ERR1_CHK_GRP0(x) (((x) >> 24) & 0xff) /* Syndrome Check for ECC Group 0 */ +#define PCI_FLIT_LOG_ERR2 0x08 /* Flit Error Log 2 Register */ +#define PCI_FLIT_LOG_ERR2_PAR_GRP1(x) ((x) & 0xff) /* Syndrome Parity for ECC Group 1 */ +#define PCI_FLIT_LOG_ERR2_CHK_GRP1(x) (((x) >> 8) & 0xff) /* Syndrome Check for ECC Group 1 */ +#define PCI_FLIT_LOG_ERR2_PAR_GRP2(x) (((x) >> 16) & 0xff) /* Syndrome Parity for ECC Group 2 */ +#define PCI_FLIT_LOG_ERR2_CHK_GRP2(x) (((x) >> 24) & 0xff) /* Syndrome Check for ECC Group 2 */ +#define PCI_FLIT_LOG_CNT_CTL 0x0C /* Flit Error Counter Control Register */ +#define PCI_FLIT_LOG_CNT_CTL_EN 0x00000001 /* Flit Error Counter Enable */ +#define PCI_FLIT_LOG_CNT_CTL_INT 0x00000002 /* Flit Error Counter Interrupt Enable */ +#define PCI_FLIT_LOG_CNT_CTL_EVNT(x) (((x) >> 2) & 0x3) /* Events to count */ +#define PCI_FLIT_LOG_CNT_CTL_TRG(x) (((x) >> 4) & 0xff) /* Trigger Event on Error Count */ +#define PCI_FLIT_LOG_CNT_STS 0x0E /* Flit Error Counter Status Register */ +#define PCI_FLIT_LOG_CNT_STS_WIDTH(x) ((x) & 0x7) /* Link Width when Error Counter Started */ +#define PCI_FLIT_LOG_CNT_STS_INT 0x00000004 /* Interrupt Generated based on Trigger Event Count */ +#define PCI_FLIT_LOG_CNT_STS_CNT(x) (((x) >> 8) & 0xFF) /* Flit Error Counter */ +#define PCI_FLIT_LOG_MES_CTL 0x10 /* FBER Measurement Control Register */ +#define PCI_FLIT_LOG_MES_CTL_EN 0x00000001 /* FBER Measurement Enable */ +#define PCI_FLIT_LOG_MES_CTL_CLR 0x00000002 /* Clear FBER Counters */ +#define PCI_FLIT_LOG_MES_CTL_GRAN(x) (((x) >> 2) & 0x3) /* Granularity of per-Lane Error reported */ +#define PCI_FLIT_LOG_MES_STS1 0x14 /* FBER Measurement Status 1 Register */ +#define PCI_FLIT_LOG_MES_STS2 0x18 /* FBER Measurement Status 2 Register */ +#define PCI_FLIT_LOG_MES_STS2_INV(x) ((x) & 0xffff) /* Invalid Flit Counter */ +#define PCI_FLIT_LOG_MES_STS3 0x1C /* FBER Measurement Status 3 Register */ +#define PCI_FLIT_LOG_MES_STS3_LN0(x) ((x) & 0xffff) /* Lane #0 Correctable Counter */ +#define PCI_FLIT_LOG_MES_STS3_LN1(x) (((x) >> 16) & 0xffff) /* Lane #1 Correctable Counter */ +#define PCI_FLIT_LOG_MES_STS4 0x20 /* FBER Measurement Status 4 Register */ +#define PCI_FLIT_LOG_MES_STS4_LN2(x) ((x) & 0xffff) /* Lane #2 Correctable Counter */ +#define PCI_FLIT_LOG_MES_STS4_LN3(x) (((x) >> 16) & 0xffff) /* Lane #3 Correctable Counter */ +#define PCI_FLIT_LOG_MES_STS5 0x24 /* FBER Measurement Status 5 Register */ +#define PCI_FLIT_LOG_MES_STS5_LN4(x) ((x) & 0xffff) /* Lane #4 Correctable Counter */ +#define PCI_FLIT_LOG_MES_STS5_LN5(x) (((x) >> 16) & 0xffff) /* Lane #5 Correctable Counter */ +#define PCI_FLIT_LOG_MES_STS6 0x28 /* FBER Measurement Status 6 Register */ +#define PCI_FLIT_LOG_MES_STS6_LN6(x) ((x) & 0xffff) /* Lane #6 Correctable Counter */ +#define PCI_FLIT_LOG_MES_STS6_LN7(x) (((x) >> 16) & 0xffff) /* Lane #7 Correctable Counter */ +#define PCI_FLIT_LOG_MES_STS7 0x2C /* FBER Measurement Status 7 Register */ +#define PCI_FLIT_LOG_MES_STS7_LN8(x) ((x) & 0xffff) /* Lane #8 Correctable Counter */ +#define PCI_FLIT_LOG_MES_STS7_LN9(x) (((x) >> 16) & 0xffff) /* Lane #9 Correctable Counter */ +#define PCI_FLIT_LOG_MES_STS8 0x30 /* FBER Measurement Status 8 Register */ +#define PCI_FLIT_LOG_MES_STS8_LN10(x) ((x) & 0xffff) /* Lane #10 Correctable Counter */ +#define PCI_FLIT_LOG_MES_STS8_LN11(x) (((x) >> 16) & 0xffff) /* Lane #11 Correctable Counter */ +#define PCI_FLIT_LOG_MES_STS9 0x34 /* FBER Measurement Status 9 Register */ +#define PCI_FLIT_LOG_MES_STS9_LN12(x) ((x) & 0xffff) /* Lane #12 Correctable Counter */ +#define PCI_FLIT_LOG_MES_STS9_LN13(x) (((x) >> 16) & 0xffff) /* Lane #13 Correctable Counter */ +#define PCI_FLIT_LOG_MES_STS10 0x38 /* FBER Measurement Status 10 Register */ +#define PCI_FLIT_LOG_MES_STS10_LN14(x) ((x) & 0xffff) /* Lane #14 Correctable Counter */ +#define PCI_FLIT_LOG_MES_STS10_LN15(x) (((x) >> 16) & 0xffff) /* Lane #15 Correctable Counter */ + /* * The PCI interface treats multi-function devices as independent * devices. The slot/function address of each device is encoded diff --git a/ls-ecaps.c b/ls-ecaps.c index 0bb7412..21b43fb 100644 --- a/ls-ecaps.c +++ b/ls-ecaps.c @@ -1910,6 +1910,116 @@ cap_dev3(struct device *d, int where) FLAG(devsta3, PCI_DEV3_DEVSTA3_REMOTE_L0P_SUPP)); } +static const char *flit_log_mes_ctl_gran(char *buf, size_t buflen, u8 sts) +{ + switch (sts) + { + case 0b00: + return "all"; + case 0b001: + return "even"; + case 0b010: + return "odd"; + case 0b011: + return "mismatch"; + default: + snprintf(buf, buflen, "Unknown (%u)", sts); + return buf; + } +} + +static void +cap_flit_log(struct device *d, int where) +{ + char buf[16]; + + printf("Flit Logging\n"); + + if (verbose < 2) + return; + + if (!config_fetch(d, where + PCI_FLIT_LOG_ERR1, 56)) + return; + + u32 err_log_1 = get_conf_long(d, where + PCI_FLIT_LOG_ERR1); + printf("\t\tLog1: Valid%c, Link Width: %s\n" + "\t\t\t More entries%c Unrecognized flit%c FEC uncorrectable%c\n" + "\t\t\t SyndParityGrp0: %02x, SyndCheckGrp0: %02x\n", + FLAG(err_log_1, PCI_FLIT_LOG_ERR1_VLD), + link_width_str(buf, sizeof(buf), PCI_FLIT_LOG_ERR1_WIDTH(err_log_1)), + FLAG(err_log_1, PCI_FLIT_LOG_ERR1_MORE), + FLAG(err_log_1, PCI_FLIT_LOG_ERR1_UNREC), + FLAG(err_log_1, PCI_FLIT_LOG_ERR1_UNCOR), + PCI_FLIT_LOG_ERR1_PAR_GRP0(err_log_1), + PCI_FLIT_LOG_ERR1_CHK_GRP0(err_log_1)); + + u32 err_log_2 = get_conf_long(d, where + PCI_FLIT_LOG_ERR2); + printf("\t\tLog2: SyndParityGrp1: %02x, SyndCheckGrp1: %02x\n" + "\t\t\t SyndParityGrp2: %02x, SyndCheckGrp2: %02x\n", + PCI_FLIT_LOG_ERR2_PAR_GRP1(err_log_2), + PCI_FLIT_LOG_ERR2_CHK_GRP1(err_log_2), + PCI_FLIT_LOG_ERR2_PAR_GRP2(err_log_2), + PCI_FLIT_LOG_ERR2_CHK_GRP2(err_log_2)); + + u16 err_cnt_ctl = get_conf_word(d, where + PCI_FLIT_LOG_CNT_CTL); + printf("\t\tCntCtl: Flit Error Counter En%c Flit Error Counter Interrupt En%c\n" + "\t\t\t Events to count: %u, Trigger Event on Error Count: %02x\n", + FLAG(err_cnt_ctl, PCI_FLIT_LOG_CNT_CTL_EN), + FLAG(err_cnt_ctl, PCI_FLIT_LOG_CNT_CTL_INT), + PCI_FLIT_LOG_CNT_CTL_EVNT(err_cnt_ctl), + PCI_FLIT_LOG_CNT_CTL_TRG(err_cnt_ctl)); + + u16 err_cnt_sts = get_conf_word(d, where + PCI_FLIT_LOG_CNT_STS); + printf("\t\tCntSts: Link Width when Error Counter Started %s\n" + "\t\t\t Interrupt Generated based on Trigger Event Count%c, FlitErr: %u\n", + link_width_str(buf, sizeof(buf), PCI_FLIT_LOG_CNT_STS_WIDTH(err_cnt_sts)), + FLAG(err_cnt_sts, PCI_FLIT_LOG_CNT_STS_INT), + PCI_FLIT_LOG_CNT_STS_CNT(err_cnt_sts)); + + u32 mes_ctl = get_conf_long(d, where + PCI_FLIT_LOG_MES_CTL); + printf("\t\tMeasCtl: En%c Granularity: %s\n", + FLAG(mes_ctl, PCI_FLIT_LOG_MES_CTL_EN), + flit_log_mes_ctl_gran(buf, sizeof(buf), PCI_FLIT_LOG_MES_CTL_GRAN(mes_ctl))); + + u32 mes_sts1 = get_conf_long(d, where + PCI_FLIT_LOG_MES_STS1); + printf("\t\tMeasSts1: Flit Counter: %u\n", mes_sts1); + u32 mes_sts2 = get_conf_long(d, where + PCI_FLIT_LOG_MES_STS2); + printf("\t\tMeasSts2: Invalid Flit Counter: %u\n", + PCI_FLIT_LOG_MES_STS2_INV(mes_sts2)); + u32 mes_sts3 = get_conf_long(d, where + PCI_FLIT_LOG_MES_STS3); + printf("\t\tMeasSts3: Lane0: %5u, Lane1: %5u\n", + PCI_FLIT_LOG_MES_STS3_LN0(mes_sts3), + PCI_FLIT_LOG_MES_STS3_LN1(mes_sts3)); + u32 mes_sts4 = get_conf_long(d, where + PCI_FLIT_LOG_MES_STS4); + printf("\t\tMeasSts4: Lane2: %5u, Lane3: %5u\n", + PCI_FLIT_LOG_MES_STS4_LN2(mes_sts4), + PCI_FLIT_LOG_MES_STS4_LN3(mes_sts4)); + u32 mes_sts5 = get_conf_long(d, where + PCI_FLIT_LOG_MES_STS5); + printf("\t\tMeasSts5: Lane4: %5u, Lane5: %5u\n", + PCI_FLIT_LOG_MES_STS5_LN4(mes_sts5), + PCI_FLIT_LOG_MES_STS5_LN5(mes_sts5)); + u32 mes_sts6 = get_conf_long(d, where + PCI_FLIT_LOG_MES_STS6); + printf("\t\tMeasSts6: Lane6: %5u, Lane7: %5u\n", + PCI_FLIT_LOG_MES_STS6_LN6(mes_sts6), + PCI_FLIT_LOG_MES_STS6_LN7(mes_sts6)); + u32 mes_sts7 = get_conf_long(d, where + PCI_FLIT_LOG_MES_STS7); + printf("\t\tMeasSts7: Lane8: %5u, Lane9: %5u\n", + PCI_FLIT_LOG_MES_STS7_LN8(mes_sts7), + PCI_FLIT_LOG_MES_STS7_LN9(mes_sts7)); + u32 mes_sts8 = get_conf_long(d, where + PCI_FLIT_LOG_MES_STS8); + printf("\t\tMeasSts8: Lane10: %5u, Lane11: %5u\n", + PCI_FLIT_LOG_MES_STS8_LN10(mes_sts8), + PCI_FLIT_LOG_MES_STS8_LN11(mes_sts8)); + u32 mes_sts9 = get_conf_long(d, where + PCI_FLIT_LOG_MES_STS9); + printf("\t\tMeasSts9: Lane12: %5u, Lane13: %5u\n", + PCI_FLIT_LOG_MES_STS9_LN12(mes_sts9), + PCI_FLIT_LOG_MES_STS9_LN13(mes_sts9)); + u32 mes_sts10 = get_conf_long(d, where + PCI_FLIT_LOG_MES_STS10); + printf("\t\tMeasSts10: Lane14: %5u, Lane15: %5u\n", + PCI_FLIT_LOG_MES_STS10_LN14(mes_sts10), + PCI_FLIT_LOG_MES_STS10_LN15(mes_sts10)); +} + void show_ext_caps(struct device *d, int type) { @@ -2072,6 +2182,9 @@ show_ext_caps(struct device *d, int type) case PCI_EXT_CAP_ID_DEV3: cap_dev3(d, where); break; + case PCI_EXT_CAP_ID_FLIT_LOG: + cap_flit_log(d, where); + break; default: printf("Extended Capability ID %#02x\n", id); break;