Module Name:    src
Committed By:   martin
Date:           Sat Jan 29 17:08:33 UTC 2022

Modified Files:
        src/sys/dev/pci [netbsd-9]: pci_subr.c pcireg.h

Log Message:
Pull up the following revisions, requested by msaitoh in ticket #1412:

        sys/dev/pci/pci_subr.c                          1.232-1.239 via patch
        sys/dev/pci/pcireg.h                            1.62-1.63

- Decode link control2's Compliance Preset/De-emphasis more.
- Decode Physical Layer 16.0 GT/s extended capability.
- Decode Lane Margining at the Receiver extended capability.
- Print "reserved" instead of "unknown" when printing equalization
  preset. One of them is known to be the default value.
- Fix typo.


To generate a diff of this commit:
cvs rdiff -u -r1.215.2.5 -r1.215.2.6 src/sys/dev/pci/pci_subr.c
cvs rdiff -u -r1.147.4.3 -r1.147.4.4 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.215.2.5 src/sys/dev/pci/pci_subr.c:1.215.2.6
--- src/sys/dev/pci/pci_subr.c:1.215.2.5	Fri Dec  3 19:40:38 2021
+++ src/sys/dev/pci/pci_subr.c	Sat Jan 29 17:08:33 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: pci_subr.c,v 1.215.2.5 2021/12/03 19:40:38 martin Exp $	*/
+/*	$NetBSD: pci_subr.c,v 1.215.2.6 2022/01/29 17:08:33 martin 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.215.2.5 2021/12/03 19:40:38 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v 1.215.2.6 2022/01/29 17:08:33 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_pci.h"
@@ -1787,6 +1787,45 @@ pci_print_pcie_link_deemphasis(pcireg_t 
 	}
 }
 
+static const struct _pcie_link_preset_preshoot_deemphasis {
+	const char *preshoot;
+	const char *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 */
+	{ "0.0",	"-2.5+-1" },	/* P3 */
+	{ "0.0",	"0.0" },	/* P4 */
+	{ "1.9+-1",	"0.0" },	/* P5 */
+	{ "2.5+-1",	"0.0" },	/* P6 */
+	{ "3.5+-1",	"-6.0+-1.5" },	/* P7 */
+	{ "3.5+-1",	"-3.5+-1" },	/* P8 */
+	{ "3.5+-1",	"0.0" },	/* P9 */
+	{ "0.0",	NULL }		/* P10 */
+};
+
+static void
+pci_print_pcie_link_preset_preshoot_deemphasis(pcireg_t val)
+{
+	const char *deemphasis;
+
+	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_preset_preshoot_deemphasis[val].preshoot);
+	deemphasis = pcie_link_preset_preshoot_deemphasis[val].deemphasis;
+
+	if (deemphasis != NULL)
+		printf(", De-emphasis %sdB", deemphasis);
+}
+
 static void
 pci_conf_print_pcie_cap(const pcireg_t *regs, int capoff)
 {
@@ -2320,8 +2359,8 @@ pci_conf_print_pcie_cap(const pcireg_t *
 		    (unsigned int)__SHIFTOUT(reg,  PCIE_LCSR2_TX_MARGIN));
 		onoff("Enter Modified Compliance", reg, PCIE_LCSR2_EN_MCOMP);
 		onoff("Compliance SOS", reg, PCIE_LCSR2_COMP_SOS);
-		printf("      Compliance Present/De-emphasis: ");
-		pci_print_pcie_link_deemphasis(
+		printf("      Compliance Preset/De-emphasis: ");
+		pci_print_pcie_link_preset_preshoot_deemphasis(
 			__SHIFTOUT(reg, PCIE_LCSR2_COMP_DEEMP));
 		printf("\n");
 
@@ -3854,7 +3893,7 @@ pci_conf_print_sec_pcie_cap(const pcireg
 		reg = regs[o2i(pcie_capoff + PCIE_LCAP)];
 		maxlinkwidth = __SHIFTOUT(reg, PCIE_LCAP_MAX_WIDTH);
 	} else {
-		printf("error: falied to get PCIe capablity\n");
+		printf("error: failed to get PCIe capability\n");
 		return;
 	}
 	for (i = 0; i < maxlinkwidth; i++) {
@@ -4220,6 +4259,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 = __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[] = {
+	[0] = ("Broadcast "
+	    "(Downstream Port Receiver and all Retimer Pseudo Port Receiver)"),
+	[1] =  "Rx(A) (Downstream Port Receiver)",
+	[2] = "Rx(B) (Retimer X or Z Upstream Pseudo Port Receiver)",
+	[3] = "Rx(C) (Retimer X or Z Downstream Pseudo Port Receiver)",
+	[4] = "Rx(D) (Retimer Y Upstream Pseudo Port Receiver)",
+	[5] = "Rx(E) (Retimer Y Downstream Pseudo Port Receiver)",
+	[6] = "Reserved",
+	[7] = "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 = __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",
+	    (uint32_t)__SHIFTOUT(reg, PCI_LMR_LCTL_MTYPE));
+	printf("      Usage Model: %s\n",
+	    (__SHIFTOUT(reg, PCI_LMR_LCTL_UMODEL) == 0)
+	    ? "Lane Margining at Receiver" : "Reserved Encoding");
+	printf("      Margin Payload: 0x%02x\n",
+	    (uint32_t)__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 = __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 */
 
@@ -4307,8 +4519,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.147.4.3 src/sys/dev/pci/pcireg.h:1.147.4.4
--- src/sys/dev/pci/pcireg.h:1.147.4.3	Fri Dec  3 19:40:38 2021
+++ src/sys/dev/pci/pcireg.h	Sat Jan 29 17:08:33 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: pcireg.h,v 1.147.4.3 2021/12/03 19:40:38 martin Exp $	*/
+/*	$NetBSD: pcireg.h,v 1.147.4.4 2022/01/29 17:08:33 martin Exp $	*/
 
 /*
  * Copyright (c) 1995, 1996, 1999, 2000
@@ -1159,7 +1159,7 @@ typedef u_int8_t pci_revision_t;
 #define PCIE_LCSR2_TX_MARGIN	__BITS(9, 7)   /* Transmit Margin */
 #define PCIE_LCSR2_EN_MCOMP	__BIT(10)      /* Enter Modified Compliance */
 #define PCIE_LCSR2_COMP_SOS	__BIT(11)      /* Compliance SOS */
-#define PCIE_LCSR2_COMP_DEEMP	__BITS(15, 12) /* Compliance Present/De-emph */
+#define PCIE_LCSR2_COMP_DEEMP	__BITS(15, 12) /* Compliance Preset/De-emph */
 #define PCIE_LCSR2_DEEMP_LVL	__BIT(0 + 16)  /* Current De-emphasis Level */
 #define PCIE_LCSR2_EQ_COMPL	__BIT(1 + 16)  /* Equalization Complete */
 #define PCIE_LCSR2_EQP1_SUC	__BIT(2 + 16)  /* Equaliz Phase 1 Successful */
@@ -1552,7 +1552,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 */
@@ -2193,6 +2193,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