Module Name:    src
Committed By:   msaitoh
Date:           Sat Jan  1 03:27:53 UTC 2022

Modified Files:
        src/sys/dev/pci: pci_subr.c pcireg.h

Log Message:
Print Physical Layer 16.0 GT/s and Lane Margining at the Receiver extended cap.

 - Decode Physical Layer 16.0 GT/s extended capability.
 - Decode Lane Margining at the Receiver extended capability.
 - Rename pcie_link_compliance_preset_deemphasis to
   pcie_link_preset_preshoot_deemphasis because the table is referenced from
   multiple places.
 - Print "reserved" instead of "unknown" when printing equalization preset.
   One of them is known to be the default value.
 - Rename PCI_EXTCAP_PYSLAY_16GT to PCI_EXTCAP_PL16G.


To generate a diff of this commit:
cvs rdiff -u -r1.235 -r1.236 src/sys/dev/pci/pci_subr.c
cvs rdiff -u -r1.162 -r1.163 src/sys/dev/pci/pcireg.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/pci_subr.c
diff -u src/sys/dev/pci/pci_subr.c:1.235 src/sys/dev/pci/pci_subr.c:1.236
--- src/sys/dev/pci/pci_subr.c:1.235	Tue Dec 28 09:19:02 2021
+++ src/sys/dev/pci/pci_subr.c	Sat Jan  1 03:27:53 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: pci_subr.c,v 1.235 2021/12/28 09:19:02 msaitoh Exp $	*/
+/*	$NetBSD: pci_subr.c,v 1.236 2022/01/01 03:27:53 msaitoh Exp $	*/
 
 /*
  * Copyright (c) 1997 Zubin D. Dittia.  All rights reserved.
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v 1.235 2021/12/28 09:19:02 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v 1.236 2022/01/01 03:27:53 msaitoh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_pci.h"
@@ -1833,10 +1833,10 @@ pci_print_pcie_link_deemphasis(pcireg_t 
 	}
 }
 
-static const struct _pcie_link_compliance_preset_deemphasis {
+static const struct _pcie_link_preset_preshoot_deemphasis {
 	const char *preshoot;
 	const char *deemphasis;
-} pcie_link_compliance_preset_deemphasis[] = {
+} pcie_link_preset_preshoot_deemphasis[] = {
 	{ "0.0",	"-6.0+-1.5" },	/* P0 */
 	{ "0.0",	"-3.5+-1" },	/* P1 */
 	{ "0.0",	"-4.4+-1.5" },	/* P2 */
@@ -1851,18 +1851,22 @@ static const struct _pcie_link_complianc
 };
 
 static void
-pci_print_pcie_link_compliance_preset_deemphasis(pcireg_t val)
+pci_print_pcie_link_preset_preshoot_deemphasis(pcireg_t val)
 {
 	const char *deemphasis;
 
-	if (val >= __arraycount(pcie_link_compliance_preset_deemphasis)) {
-		printf("unknown value (0x%x)", val);
+	if (val >= __arraycount(pcie_link_preset_preshoot_deemphasis)) {
+		/*
+		 * This may be printed because the default value of some
+		 * register fields is 0b1111.
+		 */
+		printf("reserved value (0x%x)", val);
 		return;
 	}
 
 	printf("Preshoot %sdB",
-	    pcie_link_compliance_preset_deemphasis[val].preshoot);
-	deemphasis = pcie_link_compliance_preset_deemphasis[val].deemphasis;
+	    pcie_link_preset_preshoot_deemphasis[val].preshoot);
+	deemphasis = pcie_link_preset_preshoot_deemphasis[val].deemphasis;
 
 	if (deemphasis != NULL)
 		printf(", De-emphasis %sdB", deemphasis);
@@ -2402,7 +2406,7 @@ pci_conf_print_pcie_cap(const pcireg_t *
 		onoff("Enter Modified Compliance", reg, PCIE_LCSR2_EN_MCOMP);
 		onoff("Compliance SOS", reg, PCIE_LCSR2_COMP_SOS);
 		printf("      Compliance Preset/De-emphasis: ");
-		pci_print_pcie_link_compliance_preset_deemphasis(
+		pci_print_pcie_link_preset_preshoot_deemphasis(
 			PCIREG_SHIFTOUT(reg, PCIE_LCSR2_COMP_DEEMP));
 		printf("\n");
 
@@ -4300,6 +4304,179 @@ pci_conf_print_dlf_cap(const pcireg_t *r
 	onoff("Remote DLF supported Valid", reg, PCI_DLF_STAT_RMTVALID);
 }
 
+static void
+pci_conf_print_pl16g_cap(const pcireg_t *regs, int extcapoff)
+{
+	pcireg_t reg, lwidth;
+	int pcie_capoff;
+	unsigned int i, j;
+
+	printf("\n  Physical Layer 16.0 GT/s\n");
+	reg = regs[o2i(extcapoff + PCI_PL16G_CAP)];
+	printf("    Capability register: 0x%08x\n", reg);
+
+	reg = regs[o2i(extcapoff + PCI_PL16G_CTL)];
+	printf("    Control register: 0x%08x\n", reg);
+
+	reg = regs[o2i(extcapoff + PCI_PL16G_STAT)];
+	printf("    Status register: 0x%08x\n", reg);
+	onoff("Equalization 16.0 GT/s Complete", reg, PCI_PL16G_STAT_EQ_COMPL);
+	onoff("Equalization 16.0 GT/s Phase 1 Successful", reg,
+	    PCI_PL16G_STAT_EQ_P1S);
+	onoff("Equalization 16.0 GT/s Phase 2 Successful", reg,
+	    PCI_PL16G_STAT_EQ_P2S);
+	onoff("Equalization 16.0 GT/s Phase 3 Successful", reg,
+	    PCI_PL16G_STAT_EQ_P3S);
+
+	reg = regs[o2i(extcapoff + PCI_PL16G_LDPMS)];
+	printf("    Local Data Parity Mismatch Status register: 0x%08x\n",
+	    reg);
+
+	reg = regs[o2i(extcapoff + PCI_PL16G_FRDPMS)];
+	printf("    First Retimer Data Parity Mismatch Status register:"
+	    " 0x%08x\n", reg);
+
+	reg = regs[o2i(extcapoff + PCI_PL16G_SRDPMS)];
+	printf("    Second Retimer Data Parity Mismatch Status register:"
+	    " 0x%08x\n", reg);
+
+	if (pci_conf_find_cap(regs, PCI_CAP_PCIEXPRESS, &pcie_capoff) == 0)
+		return; /* error */
+
+	reg = regs[o2i(pcie_capoff + PCIE_LCAP)];
+	lwidth = PCIREG_SHIFTOUT(reg, PCIE_LCAP_MAX_WIDTH);
+
+	for (i = 0; i < lwidth;) {
+		reg = regs[o2i(extcapoff + PCI_PL16G_LEC + i)];
+
+		for (j = 0; j < 4; j++) {
+			pcireg_t up, down;
+
+			down = reg & 0x0000000f;
+			up = (reg >> 4) & 0x0000000f;
+			printf("      Lane %d downstream: ", i);
+			pci_print_pcie_link_preset_preshoot_deemphasis(down);
+			printf("\n      Lane %d upstream:   ", i);
+			pci_print_pcie_link_preset_preshoot_deemphasis(up);
+			printf("\n");
+
+			reg >>= 8;
+			i++;
+			if (i >= lwidth)
+				break;
+		}
+	}
+}
+
+static const char * const pcie_receive_number_dp[] = {
+	"Broadcast "
+	"(Downstream Port Receiver and all Retimer Pseudo Port Receiver",
+	"Rx(A) (Downstream Port Receiver)",
+	"Rx(B) (Retimer X or Z Upstream Pseudo Port Receiver)",
+	"Rx(C) (Retimer X or Z Downstream Pseudo Port Receiver)",
+	"Rx(D) (Retimer Y Upstream Pseudo Port Receiver)",
+	"Rx(E) (Retimer Y Downstream Pseudo Port Receiver)",
+	"Reserved",
+	"Reserved"
+};
+
+static const char * const pcie_receive_number_up[] = {
+	"Broadcast (Upstream Port Receiver)",
+	"Reserved",
+	"Reserved",
+	"Reserved",
+	"Reserved",
+	"Reserved",
+	"Rx(F) (Upstream Port Receiver)",
+	"Reserved"
+};
+
+/*
+ * Print PCI_LMR_LANECSR. This function is used for both control and status
+ * register. The reg argument in the lower 16bit has the control or status
+ * register. The encoding is the same except the receive number, so use _LCTL_
+ * macro.
+ */
+static void
+pci_conf_print_lmr_lcsr(pcireg_t reg, bool up, bool dp)
+{
+	int rnum;
+
+ 	printf("      Receive Number: ");
+	rnum = PCIREG_SHIFTOUT(reg, PCI_LMR_LCTL_RNUM);
+	if (up)
+		printf("%s\n", pcie_receive_number_up[rnum]);
+	else if (dp)
+		printf("%s\n", pcie_receive_number_dp[rnum]);
+	else
+		printf("%x\n", rnum);
+
+	printf("      Margin Type: %x\n",
+	    PCIREG_SHIFTOUT(reg, PCI_LMR_LCTL_MTYPE));
+	printf("      Usage Model: %s\n",
+	    (PCIREG_SHIFTOUT(reg, PCI_LMR_LCTL_UMODEL) == 0)
+	    ? "Lane Margining at Receiver" : "Reserved Encoding");
+	printf("      Margin Payload: 0x%02x\n",
+	    PCIREG_SHIFTOUT(reg, PCI_LMR_LCTL_MPAYLOAD));
+}
+
+static void
+pci_conf_print_lmr_cap(const pcireg_t *regs, int extcapoff)
+{
+	pcireg_t reg, lwidth;
+	int pcie_capoff;
+	int pcie_devtype;
+	unsigned int i;
+	bool up, dp;
+
+	printf("\n  Lane Margining at the Receiver\n");
+	reg = regs[o2i(extcapoff + PCI_LMR_PCAPSTAT)];
+	printf("    Port Capability register: 0x%04x\n", reg & 0xffff);
+	onoff("Margining uses Driver Software", reg, PCI_LMR_PCAP_MUDS);
+	printf("    Port Status register: 0x%04x\n", (reg >> 16) & 0xffff);
+	onoff("Margining Ready", reg, PCI_LMR_PSTAT_MR);
+	onoff("Margining Software Ready", reg, PCI_LMR_PSTAT_MSR);
+
+	if (pci_conf_find_cap(regs, PCI_CAP_PCIEXPRESS, &pcie_capoff) == 0)
+		return; /* error */
+
+	up = dp = false;
+	reg = regs[o2i(pcie_capoff)];
+	pcie_devtype = PCIE_XCAP_TYPE(reg);
+	switch (pcie_devtype) {
+	case PCIE_XCAP_TYPE_PCIE_DEV:	/* 0x0 */
+	case PCIE_XCAP_TYPE_PCI_DEV:	/* 0x1 */
+	case PCIE_XCAP_TYPE_UP:		/* 0x5 */
+	case PCIE_XCAP_TYPE_PCIE2PCI:	/* 0x7 */
+		up = true;
+		break;
+	case PCIE_XCAP_TYPE_RP:		/* 0x4 */
+	case PCIE_XCAP_TYPE_DOWN:	/* 0x6 */
+		dp = true;
+		break;
+	default:
+		printf("neither upstream nor downstream?(%x)\n", pcie_devtype);
+		break;
+	}
+
+	reg = regs[o2i(pcie_capoff + PCIE_LCAP)];
+	lwidth = PCIREG_SHIFTOUT(reg, PCIE_LCAP_MAX_WIDTH);
+
+	for (i = 0; i < lwidth; i++) {
+		pcireg_t lctl, lstat;
+
+		reg = regs[o2i(extcapoff + PCI_LMR_LANECSR + (i * 4))];
+
+		lctl = reg & 0xffff;
+		printf("    Lane %d control: 0x%04x\n", i, lctl);
+		pci_conf_print_lmr_lcsr(lctl, up, dp);
+
+		lstat = (reg >> 16) & 0xffff;
+		printf("    Lane %d status: 0x%04x\n", i, lstat);
+		pci_conf_print_lmr_lcsr(lstat, up, dp);
+	}
+}
+
 /* XXX pci_conf_print_hierarchyid_cap */
 /* XXX pci_conf_print_npem_cap */
 
@@ -4387,8 +4564,10 @@ static struct {
 	{ PCI_EXTCAP_VF_RESIZBAR, "VF Resizable BARs",
 	  NULL },
 	{ PCI_EXTCAP_DLF,	"Data link Feature", pci_conf_print_dlf_cap },
-	{ PCI_EXTCAP_PYSLAY_16GT, "Physical Layer 16.0 GT/s", NULL },
-	{ PCI_EXTCAP_LMR,	"Lane Margining at the Receiver", NULL },
+	{ PCI_EXTCAP_PL16G,	"Physical Layer 16.0 GT/s",
+	  pci_conf_print_pl16g_cap },
+	{ PCI_EXTCAP_LMR,	"Lane Margining at the Receiver",
+	  pci_conf_print_lmr_cap },
 	{ PCI_EXTCAP_HIERARCHYID, "Hierarchy ID",
 	  NULL },
 	{ PCI_EXTCAP_NPEM,	"Native PCIe Enclosure Management",

Index: src/sys/dev/pci/pcireg.h
diff -u src/sys/dev/pci/pcireg.h:1.162 src/sys/dev/pci/pcireg.h:1.163
--- src/sys/dev/pci/pcireg.h:1.162	Tue Dec 28 09:16:05 2021
+++ src/sys/dev/pci/pcireg.h	Sat Jan  1 03:27:53 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: pcireg.h,v 1.162 2021/12/28 09:16:05 msaitoh Exp $	*/
+/*	$NetBSD: pcireg.h,v 1.163 2022/01/01 03:27:53 msaitoh Exp $	*/
 
 /*
  * Copyright (c) 1995, 1996, 1999, 2000
@@ -1567,7 +1567,7 @@ struct pci_rom {
 #define	PCI_EXTCAP_DESIGVNDSP	0x0023	/* Designated Vendor-Specific */
 #define	PCI_EXTCAP_VF_RESIZBAR	0x0024	/* VF Resizable BAR */
 #define	PCI_EXTCAP_DLF		0x0025	/* Data link Feature */
-#define	PCI_EXTCAP_PYSLAY_16GT	0x0026	/* Physical Layer 16.0 GT/s */
+#define	PCI_EXTCAP_PL16G	0x0026	/* Physical Layer 16.0 GT/s */
 #define	PCI_EXTCAP_LMR		0x0027	/* Lane Margining at the Receiver */
 #define	PCI_EXTCAP_HIERARCHYID	0x0028	/* Hierarchy ID */
 #define	PCI_EXTCAP_NPEM		0x0029	/* Native PCIe Enclosure Management */
@@ -2208,6 +2208,37 @@ struct pci_rom {
  * Extended capability ID: 0x0026
  * Physical Layer 16.0 GT/s
  */
+#define	PCI_PL16G_CAP	0x04	/* Capabilities Register */
+#define	PCI_PL16G_CTL	0x08	/* Control Register */
+#define	PCI_PL16G_STAT	0x0c	/* Status Register */
+#define	PCI_PL16G_STAT_EQ_COMPL __BIT(0) /* Equalization 16.0 GT/s Complete */
+#define	PCI_PL16G_STAT_EQ_P1S	__BIT(1) /* Eq. 16.0 GT/s Phase 1 Successful */
+#define	PCI_PL16G_STAT_EQ_P2S	__BIT(2) /* Eq. 16.0 GT/s Phase 2 Successful */
+#define	PCI_PL16G_STAT_EQ_P3S	__BIT(3) /* Eq. 16.0 GT/s Phase 3 Successful */
+#define	PCI_PL16G_STAT_LEQR	__BIT(4) /* Link Eq. Request 16.0 GT/s */
+#define	PCI_PL16G_LDPMS	0x10	/* Local Data Parity Mismatch Status reg. */
+#define	PCI_PL16G_FRDPMS 0x14	/* First Retimer Data Parity Mismatch Status */
+#define	PCI_PL16G_SRDPMS 0x18  /* Second Retimer Data Parity Mismatch Status */
+  /* 0x1c reserved */
+#define	PCI_PL16G_LEC	0x20	/* Lane Equalization Control Register */
+
+/*
+ * Extended capability ID: 0x0027
+ * Lane Margining at the Receiver
+ */
+#define	PCI_LMR_PCAPSTAT 0x04	/* Port Capabilities and Status Register */
+#define	PCI_LMR_PCAP_MUDS	__BIT(0)   /* Margining uses Driver Software */
+#define	PCI_LMR_PSTAT_MR	__BIT(16)  /* Margining Ready */
+#define	PCI_LMR_PSTAT_MSR	__BIT(17)  /* Margining Software Ready */
+#define	PCI_LMR_LANECSR	0x08	/* Lane Control and Status Register */
+#define	PCI_LMR_LCTL_RNUM	__BITS(2, 0)	/* Receive Number */
+#define	PCI_LMR_LCTL_MTYPE	__BITS(5, 3)	/* Margin Type */
+#define	PCI_LMR_LCTL_UMODEL	__BIT(6)	/* Usage Model */
+#define	PCI_LMR_LCTL_MPAYLOAD	__BITS(15, 8)	/* Margin Payload */
+#define	PCI_LMR_LSTAT_RNUM	__BITS(18, 16)	/* Receive Number */
+#define	PCI_LMR_LSTAT_MTYPE	__BITS(21, 19)	/* Margin Type */
+#define	PCI_LMR_LSTAT_UMODEL	__BIT(22)	/* Usage Model */
+#define	PCI_LMR_LSTAT_MPAYLOAD	__BITS(31, 24)	/* Margin Payload */
 
 /*
  * Extended capability ID: 0x0028

Reply via email to