]> git.ipfire.org Git - thirdparty/pciutils.git/commitdiff
Merge remote-tracking branch 'am/lspci-flit-log'
authorMartin Mareš <mj@ucw.cz>
Sun, 28 Dec 2025 20:20:03 +0000 (21:20 +0100)
committerMartin Mareš <mj@ucw.cz>
Sun, 28 Dec 2025 20:20:03 +0000 (21:20 +0100)
1  2 
lib/header.h
ls-ecaps.c

diff --cc lib/header.h
index 3a910c63c69740ff4a23e50f811c5f1690f84c44,17b571a4e2be8e653496c2cbf13d612e4d852c3c..e9f3f642697f56f13f3b223d7d154eeed0c44baf
  /* IDE Address Association Register 2 is "Memory Limit Upper" */
  /* IDE Address Association Register 3 is "Memory Base Upper" */
  
 +/* MMIO Register Block Locator Capability */
 +#define PCI_MRBL_CAP          0x04    /* MRBL Capabilities Register */
 +#define PCI_MRBL_REG          0x08    /* MRBL Locator Register base */
 +#define PCI_MRBL_REG_SIZE     0x08    /* MRBL Locator Register size */
 +#define  PCI_MRBL_CAP_STRUCT_LEN(x)   ((x) & 0xFFF) /* MRBL Structure Length in bytes */
 +#define  PCI_MRBL_LOC_BIR(x)          ((x) & 0x7) /* MRBL Locator BIR */
 +#define  PCI_MRBL_LOC_BID(x)          (((x) >> 8) & 0xff) /* MRBL Locator Block ID */
 +#define  PCI_MRBL_LOC_OFF_LOW(x)      ((x) & 0xffff0000) /* MRBL Locator Offset Low */
 +
 +/* Flit Error Injection Capability */
 +#define PCI_FLIT_EI_CAP               0x04    /* Error Injection Capability Register */
 +#define PCI_FLIT_EI_CTL1      0x08    /* Flit Error Injection Control 1 Register */
 +#define  PCI_FLIT_EI_CTL1_EN  0x0001  /* Flit Error Injection Enable */
 +#define  PCI_FLIT_EI_CTL1_TX  0x0002  /* Inject Errors on Transmitted Flits */
 +#define  PCI_FLIT_EI_CTL1_RX  0x0004  /* Inject Errors on Received Flits */
 +#define  PCI_FLIT_EI_CTL1_25GT        0x0040 /* Flit Error Injection Enable 2.5 GT/s Data Rate */
 +#define  PCI_FLIT_EI_CTL1_50GT        0x0080 /* Flit Error Injection Enable 5.0 GT/s Data Rate */
 +#define  PCI_FLIT_EI_CTL1_80GT        0x0100 /* Flit Error Injection Enable 8.0 GT/s Data Rate */
 +#define  PCI_FLIT_EI_CTL1_16GT        0x0200 /* Flit Error Injection Enable 16.0 GT/s Data Rate */
 +#define  PCI_FLIT_EI_CTL1_32GT        0x0400 /* Flit Error Injection Enable 32.0 GT/s Data Rate */
 +#define  PCI_FLIT_EI_CTL1_64GT        0x0800 /* Flit Error Injection Enable 64.0 GT/s Data Rate */
 +#define  PCI_FLIT_EI_CTL1_NUM_ERR(x) (((x) >> 16) & 0x1F) /* Number of Errors Injected */
 +#define  PCI_FLIT_EI_CTL1_SPACING(x) (((x) >> 21) & 0xFF) /* Spacing Between Injected Errors */
 +#define  PCI_FLIT_EI_CTL1_FLIT_TY(x) (((x) >> 29) & 0x3) /* Injection on Flit Type */
 +#define PCI_FLIT_EI_CTL2      0x0C    /* Flit Error Injection Control 2 Register */
 +#define  PCI_FLIT_EI_CTL2_CONSEC(x) ((x) & 0x7) /* Consecutive Error Injection */
 +#define  PCI_FLIT_EI_CTL2_TYPE(x) (((x) >> 3) & 0x3) /* Error Type Being Injected */
 +#define  PCI_FLIT_EI_CTL2_OFFS(x) (((x) >> 5) & 0x7F) /* Error Offset within Flit */
 +#define  PCI_FLIT_EI_CTL2_MAG(x) (((x) >> 12) & 0xFF) /* Error Magnitude */
 +#define PCI_FLIT_EI_STS               0x10    /* Flit Error Injection Status Register */
 +#define  PCI_FLIT_EI_STS_TX(x) ((x) & 0x3) /* Flit Error Tx Injection Status */
 +#define  PCI_FLIT_EI_STS_RX(x) (((x) >> 2) & 0x3) /* Flit Error Rx Injection Status */
 +#define PCI_FLIT_EI_OS_CTL1   0x14    /* Ordered Set Error Injection Control 1 Register */
 +#define  PCI_FLIT_EI_OS_CTL1_EN       0x00000001 /* Ordered Set Error Injection Enable */
 +#define  PCI_FLIT_EI_OS_CTL1_TX       0x00000002 /* Inject Errors on Transmitted Ordered Sets */
 +#define  PCI_FLIT_EI_OS_CTL1_RX       0x00000004 /* Inject Errors on Received Ordered Sets */
 +#define  PCI_FLIT_EI_OS_CTL1_NUM(x) (((x) >> 3) & 0x1F) /* Number of Errors injected */
 +#define  PCI_FLIT_EI_OS_CTL1_SPACING(x) (((x) >> 8) & 0xFF) /* Spacing Between Injected Errors */
 +#define  PCI_FLIT_EI_OS_CTL1_TS0      0x00010000 /* Inject Error on TS0 OS */
 +#define  PCI_FLIT_EI_OS_CTL1_TS1      0x00020000 /* Inject Error on TS1 OS */
 +#define  PCI_FLIT_EI_OS_CTL1_TS2      0x00040000 /* Inject Error on TS2 OS */
 +#define  PCI_FLIT_EI_OS_CTL1_SKP      0x00080000 /* Inject Error on SKP OS */
 +#define  PCI_FLIT_EI_OS_CTL1_EIEOS    0x00100000 /* Inject Error on EIEOS OS */
 +#define  PCI_FLIT_EI_OS_CTL1_EIOS     0x00200000 /* Inject Error on EIOS OS */
 +#define  PCI_FLIT_EI_OS_CTL1_SDS      0x00400000 /* Inject Error on SDS OS */
 +#define  PCI_FLIT_EI_OS_CTL1_POLL     0x00800000 /* Inject Error in Polling State */
 +#define  PCI_FLIT_EI_OS_CTL1_CONF     0x01000000 /* Inject errors in the Configuration LTSSM state */
 +#define  PCI_FLIT_EI_OS_CTL1_L0               0x02000000 /* Inject errors in the L0 LTSSM state */
 +#define  PCI_FLIT_EI_OS_CTL1_NOEQ     0x04000000 /* Inject errors in the Recovery LTSSM states */
 +#define  PCI_FLIT_EI_OS_CTL1_EQ01     0x08000000 /* Inject errors Recovery.Equalization Phase 0 and Phase 1 */
 +#define  PCI_FLIT_EI_OS_CTL1_EQ2      0x10000000 /* Inject errors Recovery.Equalization Phase 2 */
 +#define  PCI_FLIT_EI_OS_CTL1_EQ3      0x20000000 /* Inject errors Recovery.Equalization Phase 3 */
 +#define PCI_FLIT_EI_OS_CTL2   0x18    /* Ordered Set Error Injection Control 2 Register */
 +#define  PCI_FLIT_EI_OS_CTL2_BYTES(x) ((x) & 0xFFFF) /* Error Injection Bytes */
 +#define  PCI_FLIT_EI_OS_CTL2_LANES(x) (((x) >> 16) & 0xFFFF) /* Lane Number for Error Injection */
 +#define PCI_FLIT_EI_OS_TX     0x1C    /* Ordered Set Error Tx Injection Status Registe */
 +#define  PCI_FLIT_EI_OS_TX_TS0(x) ((x) & 0x3) /* Tx Injection Status TS0 */
 +#define  PCI_FLIT_EI_OS_TX_TS1(x) (((x) >> 2) & 0x3) /* Tx Injection Status TS1 */
 +#define  PCI_FLIT_EI_OS_TX_TS2(x) (((x) >> 4) & 0x3) /* Tx Injection Status TS2 */
 +#define  PCI_FLIT_EI_OS_TX_SKP(x) (((x) >> 6) & 0x3) /* Tx Injection Status SKP */
 +#define  PCI_FLIT_EI_OS_TX_EIEOS(x) (((x) >> 8) & 0x3) /* Tx Injection Status EIEOS */
 +#define  PCI_FLIT_EI_OS_TX_EIOS(x) (((x) >> 10) & 0x3) /* Tx Injection Status EIOS */
 +#define  PCI_FLIT_EI_OS_TX_SDS(x) (((x) >> 12) & 0x3) /* Tx Injection Status SDS */
 +#define  PCI_FLIT_EI_OS_TX_POLL(x) (((x) >> 14) & 0x3) /* Tx Injection Status Polling */
 +#define  PCI_FLIT_EI_OS_TX_CONF(x) (((x) >> 16) & 0x3) /* Tx Injection Status Configuration */
 +#define  PCI_FLIT_EI_OS_TX_L0(x) (((x) >> 18) & 0x3) /* Tx Injection Status L0 */
 +#define  PCI_FLIT_EI_OS_TX_NOEQ(x) (((x) >> 20) & 0x3) /* Tx Injection Status non-EQ Recovery */
 +#define  PCI_FLIT_EI_OS_TX_EQ01(x) (((x) >> 22) & 0x3) /* Tx Injection Status Recovery.Equalization Phase 0 and 1 */
 +#define  PCI_FLIT_EI_OS_TX_EQ2(x) (((x) >> 24) & 0x3) /* Tx Injection Status Recovery.Equalization Phase 2 */
 +#define  PCI_FLIT_EI_OS_TX_EQ3(x) (((x) >> 26) & 0x3) /* Tx Injection Status Recovery.Equalization Phase 3 */
 +#define PCI_FLIT_EI_OS_RX     0x20    /* Ordered Set Error Rx Injection Status Register */
 +#define  PCI_FLIT_EI_OS_RX_TS0(x) ((x) & 0x3) /* Rx Injection Status TS0 */
 +#define  PCI_FLIT_EI_OS_RX_TS1(x) (((x) >> 2) & 0x3) /* Rx Injection Status TS1 */
 +#define  PCI_FLIT_EI_OS_RX_TS2(x) (((x) >> 4) & 0x3) /* Rx Injection Status TS2 */
 +#define  PCI_FLIT_EI_OS_RX_SKP(x) (((x) >> 6) & 0x3) /* Rx Injection Status SKP */
 +#define  PCI_FLIT_EI_OS_RX_EIEOS(x) (((x) >> 8) & 0x3) /* Rx Injection Status EIEOS */
 +#define  PCI_FLIT_EI_OS_RX_EIOS(x) (((x) >> 10) & 0x3) /* Rx Injection Status EIOS */
 +#define  PCI_FLIT_EI_OS_RX_SDS(x) (((x) >> 12) & 0x3) /* Rx Injection Status SDS */
 +#define  PCI_FLIT_EI_OS_RX_POLL(x) (((x) >> 14) & 0x3) /* Rx Injection Status Polling */
 +#define  PCI_FLIT_EI_OS_RX_CONF(x) (((x) >> 16) & 0x3) /* Rx Injection Status Configuration */
 +#define  PCI_FLIT_EI_OS_RX_L0(x) (((x) >> 18) & 0x3) /* Rx Injection Status L0 */
 +#define  PCI_FLIT_EI_OS_RX_NOEQ(x) (((x) >> 20) & 0x3) /* Rx Injection Status non-EQ Recovery */
 +#define  PCI_FLIT_EI_OS_RX_EQ01(x) (((x) >> 22) & 0x3) /* Rx Injection Status Recovery.Equalization Phase 0 and 1 */
 +#define  PCI_FLIT_EI_OS_RX_EQ2(x) (((x) >> 24) & 0x3) /* Rx Injection Status Recovery.Equalization Phase 2 */
 +#define  PCI_FLIT_EI_OS_RX_EQ3(x) (((x) >> 26) & 0x3) /* Rx Injection Status Recovery.Equalization Phase 3 */
 +
+ /* 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 --cc ls-ecaps.c
index 0eeafb3d4578da51d720ad1f36c7888a79ccee99,21b43fb4d53d9fc8cbacba6d3c02b88a845803a8..455c203895304aa7ef13250d6d5757db62f36f73
@@@ -1915,263 -1910,116 +1915,373 @@@ cap_dev3(struct device *d, int where
           FLAG(devsta3, PCI_DEV3_DEVSTA3_REMOTE_L0P_SUPP));
  }
  
 +static const char *mmio_rbl_bid(char *buf, size_t buflen, u8 bid)
 +{
 +  switch (bid)
 +    {
 +      case 0x00:
 +        return "Empty";
 +      case 0x01:
 +        return "MCAP";
 +      case 0xFF:
 +        return "MDVS";
 +      default:
 +        snprintf(buf, buflen, "Reserved (%u)", bid);
 +        return buf;
 +    }
 +}
 +
 +static void
 +cap_mmio_rbl(struct device *d, int where)
 +{
 +  char buf[16];
 +
 +  printf("MMIO Register Block Locator\n");
 +
 +  if (verbose < 2)
 +    return;
 +
 +  if (!config_fetch(d, where + PCI_MRBL_CAP, 0x0C))
 +    {
 +      printf("\t\t<unreadable>\n");
 +      return;
 +    }
 +
 +  u32 cap = get_conf_long(d, where + PCI_MRBL_CAP);
 +  u32 mrbllen = PCI_MRBL_CAP_STRUCT_LEN(cap);
 +
 +  if (!config_fetch(d, where + PCI_MRBL_REG, mrbllen))
 +    {
 +      printf("\t\t<unreadable>\n");
 +      return;
 +    }
 +
 +  u32 num_mrbl = (mrbllen / 8) - 1;
 +
 +  for (u32 i = 0; i < num_mrbl; i++)
 +    {
 +      unsigned int pos = where + PCI_MRBL_REG + i * PCI_MRBL_REG_SIZE;
 +      if (!config_fetch(d, pos, PCI_MRBL_REG_SIZE))
 +      {
 +        printf("\t\t<unreadable>\n");
 +        return;
 +      }
 +
 +      u32 lo = get_conf_long(d, pos);
 +      u32 hi = get_conf_long(d, pos + 0x04);
 +
 +      u64 offs = ((u64) hi << 32) | PCI_MRBL_LOC_OFF_LOW(lo);
 +
 +      printf("\t\tLocator%u: BIR: BAR%u, ID: %s, offset: %016" PCI_U64_FMT_X "\n",
 +           i,
 +           PCI_MRBL_LOC_BIR(lo),
 +           mmio_rbl_bid(buf, sizeof(buf), PCI_MRBL_LOC_BID(lo)),
 +           offs);
 +    }
 +}
 +
 +static const char *flit_ei_flit_type_str(char *buf, size_t buflen, u8 type)
 +{
 +  switch (type)
 +    {
 +      case 0b000:
 +        return "any";
 +      case 0b001:
 +        return "any non-IDLE";
 +      case 0b010:
 +        return "only payload";
 +      case 0b011:
 +        return "only NOP";
 +      case 0b100:
 +        return "only IDLE";
 +      case 0b101:
 +        return "only payload+seq";
 +      case 0b110:
 +        return "only payload+1seq";
 +      default:
 +        snprintf(buf, buflen, "Unknown (%u)", type);
 +        return buf;
 +    }
 +}
 +
 +static const char *flit_ei_consec_str(char *buf, size_t buflen, u8 consec)
 +{
 +  switch (consec)
 +    {
 +      case 0b000:
 +        return "none";
 +      case 0b001:
 +      case 0b010:
 +      case 0b011:
 +      case 0b101:
 +      case 0b110:
 +        snprintf(buf, buflen, "%u", consec);
 +        return buf;
 +      case 0b111:
 +        return "pseudo-random";
 +      default:
 +        snprintf(buf, buflen, "Unknown (%u)", consec);
 +        return buf;
 +    }
 +}
 +
 +static const char *flit_ei_err_type_str(char *buf, size_t buflen, u8 type)
 +{
 +  switch (type)
 +    {
 +      case 0b00:
 +        return "random";
 +      case 0b01:
 +        return "correctable single group";
 +      case 0b10:
 +        return "correctable three groups";
 +      case 0b011:
 +        return "uncorrectable";
 +      default:
 +        snprintf(buf, buflen, "Unknown (%u)", type);
 +        return buf;
 +    }
 +}
 +
 +static const char *flit_ei_sts_str(char *buf, size_t buflen, u8 sts)
 +{
 +  switch (sts)
 +    {
 +      case 0b00:
 +        return "not started";
 +      case 0b001:
 +        return "started";
 +      case 0b010:
 +        return "completed";
 +      case 0b011:
 +        return "error";
 +      default:
 +        snprintf(buf, buflen, "Unknown (%u)", sts);
 +        return buf;
 +    }
 +}
 +
 +static void
 +cap_flit_ei(struct device *d, int where)
 +{
 +  char buf0[16], buf1[16], buf2[16];
 +
 +  printf("Flit Error Injection\n");
 +
 +  if (verbose < 2)
 +    return;
 +
 +  if (!config_fetch(d, where + PCI_FLIT_EI_CAP, 32))
 +    return;
 +
 +  u32 flit_ei_ctl1 = get_conf_long(d, where + PCI_FLIT_EI_CTL1);
 +
 +  printf("\t\tFlitEiCtl1:   En%c Tx%c Rx%c 2.5GT/s%c 5.0GT/s%c 8.0GT/s%c 16.0GT/s%c 32.0GT/s%c 64.0GT/s%c\n"
 +         "\t\t\t      Number of errors: %u, Spacing between errors: %u, Flit Type: %s\n",
 +         FLAG(flit_ei_ctl1, PCI_FLIT_EI_CTL1_EN),
 +         FLAG(flit_ei_ctl1, PCI_FLIT_EI_CTL1_TX),
 +         FLAG(flit_ei_ctl1, PCI_FLIT_EI_CTL1_RX),
 +         FLAG(flit_ei_ctl1, PCI_FLIT_EI_CTL1_25GT),
 +         FLAG(flit_ei_ctl1, PCI_FLIT_EI_CTL1_50GT),
 +         FLAG(flit_ei_ctl1, PCI_FLIT_EI_CTL1_80GT),
 +         FLAG(flit_ei_ctl1, PCI_FLIT_EI_CTL1_16GT),
 +         FLAG(flit_ei_ctl1, PCI_FLIT_EI_CTL1_32GT),
 +         FLAG(flit_ei_ctl1, PCI_FLIT_EI_CTL1_64GT),
 +         PCI_FLIT_EI_CTL1_NUM_ERR(flit_ei_ctl1),
 +         PCI_FLIT_EI_CTL1_SPACING(flit_ei_ctl1),
 +         flit_ei_flit_type_str(buf0, sizeof(buf0), PCI_FLIT_EI_CTL1_FLIT_TY(flit_ei_ctl1)));
 +
 +  u32 flit_ei_ctl2 = get_conf_long(d, where + PCI_FLIT_EI_CTL2);
 +  printf("\t\tFlitEiCtl2:   Consecutive: %s, Type: %s, Offset: %u, Magnitude: %u\n",
 +         flit_ei_consec_str(buf0, sizeof(buf0), PCI_FLIT_EI_CTL2_CONSEC(flit_ei_ctl2)),
 +         flit_ei_err_type_str(buf1, sizeof(buf1), PCI_FLIT_EI_CTL2_TYPE(flit_ei_ctl2)),
 +         PCI_FLIT_EI_CTL2_OFFS(flit_ei_ctl2),
 +         PCI_FLIT_EI_CTL2_MAG(flit_ei_ctl2));
 +
 +  u32 flit_ei_sts = get_conf_long(d, where + PCI_FLIT_EI_STS);
 +  printf("\t\tFlitEiSts:    Tx: %s, Rx: %s\n",
 +         flit_ei_sts_str(buf0, sizeof(buf0), PCI_FLIT_EI_STS_TX(flit_ei_sts)),
 +         flit_ei_sts_str(buf1, sizeof(buf1), PCI_FLIT_EI_STS_RX(flit_ei_sts)));
 +
 +  u32 flit_ei_os_ctl1 = get_conf_long(d, where + PCI_FLIT_EI_OS_CTL1);
 +  printf("\t\tFlitEiOsCtl1: En%c Tx%c Rx%c TS0%c TS1%c TS2%c SKP%c EIEOS%c EIOS%c\n"
 +        "\t\t\t      SDS%c Poll%c Conf%c L0%c NoEq%c Eq01%c Eq2%c Eq3%c\n",
 +        FLAG(flit_ei_os_ctl1, PCI_FLIT_EI_OS_CTL1_EN),
 +        FLAG(flit_ei_os_ctl1, PCI_FLIT_EI_OS_CTL1_TX),
 +        FLAG(flit_ei_os_ctl1, PCI_FLIT_EI_OS_CTL1_RX),
 +        FLAG(flit_ei_os_ctl1, PCI_FLIT_EI_OS_CTL1_TS0),
 +        FLAG(flit_ei_os_ctl1, PCI_FLIT_EI_OS_CTL1_TS1),
 +        FLAG(flit_ei_os_ctl1, PCI_FLIT_EI_OS_CTL1_TS2),
 +        FLAG(flit_ei_os_ctl1, PCI_FLIT_EI_OS_CTL1_SKP),
 +        FLAG(flit_ei_os_ctl1, PCI_FLIT_EI_OS_CTL1_EIEOS),
 +        FLAG(flit_ei_os_ctl1, PCI_FLIT_EI_OS_CTL1_EIOS),
 +        FLAG(flit_ei_os_ctl1, PCI_FLIT_EI_OS_CTL1_SDS),
 +        FLAG(flit_ei_os_ctl1, PCI_FLIT_EI_OS_CTL1_POLL),
 +        FLAG(flit_ei_os_ctl1, PCI_FLIT_EI_OS_CTL1_CONF),
 +        FLAG(flit_ei_os_ctl1, PCI_FLIT_EI_OS_CTL1_L0),
 +        FLAG(flit_ei_os_ctl1, PCI_FLIT_EI_OS_CTL1_NOEQ),
 +        FLAG(flit_ei_os_ctl1, PCI_FLIT_EI_OS_CTL1_EQ01),
 +        FLAG(flit_ei_os_ctl1, PCI_FLIT_EI_OS_CTL1_EQ2),
 +        FLAG(flit_ei_os_ctl1, PCI_FLIT_EI_OS_CTL1_EQ3));
 +
 +  u32 flit_ei_os_ctl2 = get_conf_long(d, where + PCI_FLIT_EI_OS_CTL2);
 +  printf("\t\tFlitEiOsCtl2: Bytes: %04x, Lanes: %04x\n",
 +         PCI_FLIT_EI_OS_CTL2_BYTES(flit_ei_os_ctl2),
 +         PCI_FLIT_EI_OS_CTL2_LANES(flit_ei_os_ctl2));
 +
 +  u32 flit_ei_os_tx = get_conf_long(d, where + PCI_FLIT_EI_OS_TX);
 +  printf("\t\tFlitEiOsTx:   TS0: %s, TS1: %s, TS2: %s\n",
 +         flit_ei_sts_str(buf0, sizeof(buf0), PCI_FLIT_EI_OS_TX_TS0(flit_ei_os_tx)),
 +         flit_ei_sts_str(buf1, sizeof(buf1), PCI_FLIT_EI_OS_TX_TS1(flit_ei_os_tx)),
 +         flit_ei_sts_str(buf2, sizeof(buf2), PCI_FLIT_EI_OS_TX_TS2(flit_ei_os_tx)));
 +  printf("\t\t\t      SKP: %s, EIEOS: %s, EIOS: %s\n",
 +         flit_ei_sts_str(buf0, sizeof(buf0), PCI_FLIT_EI_OS_TX_SKP(flit_ei_os_tx)),
 +         flit_ei_sts_str(buf1, sizeof(buf1), PCI_FLIT_EI_OS_TX_EIEOS(flit_ei_os_tx)),
 +         flit_ei_sts_str(buf2, sizeof(buf2), PCI_FLIT_EI_OS_TX_EIOS(flit_ei_os_tx)));
 +  printf("\t\t\t      SDS: %s, Polling: %s, Configuration: %s\n",
 +         flit_ei_sts_str(buf0, sizeof(buf0), PCI_FLIT_EI_OS_TX_SDS(flit_ei_os_tx)),
 +         flit_ei_sts_str(buf1, sizeof(buf1), PCI_FLIT_EI_OS_TX_POLL(flit_ei_os_tx)),
 +         flit_ei_sts_str(buf2, sizeof(buf2), PCI_FLIT_EI_OS_TX_CONF(flit_ei_os_tx)));
 +  printf("\t\t\t      L0: %s, non-EQ recovery: %s, Eq01: %s\n",
 +         flit_ei_sts_str(buf0, sizeof(buf0), PCI_FLIT_EI_OS_TX_L0(flit_ei_os_tx)),
 +         flit_ei_sts_str(buf1, sizeof(buf1), PCI_FLIT_EI_OS_TX_NOEQ(flit_ei_os_tx)),
 +         flit_ei_sts_str(buf2, sizeof(buf2), PCI_FLIT_EI_OS_TX_EQ01(flit_ei_os_tx)));
 +  printf("\t\t\t      Eq2: %s, Eq3: %s\n",
 +         flit_ei_sts_str(buf0, sizeof(buf0), PCI_FLIT_EI_OS_TX_EQ2(flit_ei_os_tx)),
 +         flit_ei_sts_str(buf1, sizeof(buf1), PCI_FLIT_EI_OS_TX_EQ3(flit_ei_os_tx)));
 +
 +  u32 flit_ei_os_rx = get_conf_long(d, where + PCI_FLIT_EI_OS_RX);
 +  printf("\t\tFlitEiOsRx:   TS0: %s, TS1: %s, TS2: %s\n",
 +         flit_ei_sts_str(buf0, sizeof(buf0), PCI_FLIT_EI_OS_RX_TS0(flit_ei_os_rx)),
 +         flit_ei_sts_str(buf1, sizeof(buf1), PCI_FLIT_EI_OS_RX_TS1(flit_ei_os_rx)),
 +         flit_ei_sts_str(buf2, sizeof(buf2), PCI_FLIT_EI_OS_RX_TS2(flit_ei_os_rx)));
 +  printf("\t\t\t      SKP: %s, EIEOS: %s, EIOS: %s\n",
 +         flit_ei_sts_str(buf0, sizeof(buf0), PCI_FLIT_EI_OS_RX_SKP(flit_ei_os_rx)),
 +         flit_ei_sts_str(buf1, sizeof(buf1), PCI_FLIT_EI_OS_RX_EIEOS(flit_ei_os_rx)),
 +         flit_ei_sts_str(buf2, sizeof(buf2), PCI_FLIT_EI_OS_RX_EIOS(flit_ei_os_rx)));
 +  printf("\t\t\t      SDS: %s, Polling: %s, Configuration: %s\n",
 +         flit_ei_sts_str(buf0, sizeof(buf0), PCI_FLIT_EI_OS_RX_SDS(flit_ei_os_rx)),
 +         flit_ei_sts_str(buf1, sizeof(buf1), PCI_FLIT_EI_OS_RX_POLL(flit_ei_os_rx)),
 +         flit_ei_sts_str(buf2, sizeof(buf2), PCI_FLIT_EI_OS_RX_CONF(flit_ei_os_rx)));
 +  printf("\t\t\t      L0: %s, non-EQ recovery: %s, Eq01: %s\n",
 +         flit_ei_sts_str(buf0, sizeof(buf0), PCI_FLIT_EI_OS_RX_L0(flit_ei_os_rx)),
 +         flit_ei_sts_str(buf1, sizeof(buf1), PCI_FLIT_EI_OS_RX_NOEQ(flit_ei_os_rx)),
 +         flit_ei_sts_str(buf2, sizeof(buf2), PCI_FLIT_EI_OS_RX_EQ01(flit_ei_os_rx)));
 +  printf("\t\t\t      Eq2: %s, Eq3: %s\n",
 +         flit_ei_sts_str(buf0, sizeof(buf0), PCI_FLIT_EI_OS_RX_EQ2(flit_ei_os_rx)),
 +         flit_ei_sts_str(buf1, sizeof(buf1), PCI_FLIT_EI_OS_RX_EQ3(flit_ei_os_rx)));
 +}
 +
+ 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)
  {
          case PCI_EXT_CAP_ID_DEV3:
            cap_dev3(d, where);
            break;
 +        case PCI_EXT_CAP_ID_MMIO_RBL:
 +          cap_mmio_rbl(d, where);
 +          break;
 +        case PCI_EXT_CAP_ID_FLIT_EI:
 +          cap_flit_ei(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;