]> git.ipfire.org Git - thirdparty/pciutils.git/commitdiff
lspci: decode flit logging
authorAlex Martens <alex.martens@asteralabs.com>
Thu, 13 Nov 2025 22:50:21 +0000 (14:50 -0800)
committerAlex Martens <alex.martens@asteralabs.com>
Thu, 13 Nov 2025 23:30:19 +0000 (15:30 -0800)
The flit logging extended capability is defined in the PCI express base
specification revision 6.4.

Signed-off-by: Alex Martens <alex.martens@asteralabs.com>
lib/header.h
ls-ecaps.c

index b68f2a0559e5ae2f31e00e65a8b19de36a28e07d..17b571a4e2be8e653496c2cbf13d612e4d852c3c 100644 (file)
 /* 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
index 0bb7412467e020dfe414c59a63fbd130568a6361..21b43fb4d53d9fc8cbacba6d3c02b88a845803a8 100644 (file)
@@ -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;