Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 13 Mar 2019 19:15:37 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r345103 - head/sys/compat/linuxkpi/common/include/linux
Message-ID:  <201903131915.x2DJFbRk002502@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Wed Mar 13 19:15:36 2019
New Revision: 345103
URL: https://svnweb.freebsd.org/changeset/base/345103

Log:
  Implement more PCI speed related functions and macros in the LinuxKPI.
  
  Submitted by:		Johannes Lundberg <johalun0@gmail.com>
  MFC after:		1 week
  Sponsored by:		Limelight Networks
  Sponsored by:		Mellanox Technologies

Modified:
  head/sys/compat/linuxkpi/common/include/linux/pci.h

Modified: head/sys/compat/linuxkpi/common/include/linux/pci.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/pci.h	Wed Mar 13 19:04:06 2019	(r345102)
+++ head/sys/compat/linuxkpi/common/include/linux/pci.h	Wed Mar 13 19:15:36 2019	(r345103)
@@ -139,10 +139,13 @@ struct pci_device_id {
 #define	PCI_EXP_TYPE_RC_EC	PCIEM_TYPE_ROOT_EC		/* Root Complex Event Collector */
 #define	PCI_EXP_LNKCAP_SLS_2_5GB 0x01	/* Supported Link Speed 2.5GT/s */
 #define	PCI_EXP_LNKCAP_SLS_5_0GB 0x02	/* Supported Link Speed 5.0GT/s */
+#define	PCI_EXP_LNKCAP_SLS_8_0GB 0x04	/* Supported Link Speed 8.0GT/s */
+#define	PCI_EXP_LNKCAP_SLS_16_0GB 0x08	/* Supported Link Speed 16.0GT/s */
 #define	PCI_EXP_LNKCAP_MLW	0x03f0	/* Maximum Link Width */
 #define	PCI_EXP_LNKCAP2_SLS_2_5GB 0x02	/* Supported Link Speed 2.5GT/s */
 #define	PCI_EXP_LNKCAP2_SLS_5_0GB 0x04	/* Supported Link Speed 5.0GT/s */
 #define	PCI_EXP_LNKCAP2_SLS_8_0GB 0x08	/* Supported Link Speed 8.0GT/s */
+#define	PCI_EXP_LNKCAP2_SLS_16_0GB 0x10	/* Supported Link Speed 16.0GT/s */
 
 #define PCI_EXP_LNKCTL_HAWD	PCIEM_LINK_CTL_HAWD
 #define PCI_EXP_LNKCAP_CLKPM	0x00040000
@@ -157,10 +160,19 @@ enum pci_bus_speed {
 	PCIE_SPEED_2_5GT,
 	PCIE_SPEED_5_0GT,
 	PCIE_SPEED_8_0GT,
+	PCIE_SPEED_16_0GT,
 };
 
 enum pcie_link_width {
-	PCIE_LNK_WIDTH_UNKNOWN = 0xFF,
+	PCIE_LNK_WIDTH_RESRV	= 0x00,
+	PCIE_LNK_X1		= 0x01,
+	PCIE_LNK_X2		= 0x02,
+	PCIE_LNK_X4		= 0x04,
+	PCIE_LNK_X8		= 0x08,
+	PCIE_LNK_X12		= 0x0c,
+	PCIE_LNK_X16		= 0x10,
+	PCIE_LNK_X32		= 0x20,
+	PCIE_LNK_WIDTH_UNKNOWN	= 0xff,
 };
 
 typedef int pci_power_t;
@@ -848,6 +860,67 @@ static inline int
 pci_num_vf(struct pci_dev *dev)
 {
 	return (0);
+}
+
+static inline enum pci_bus_speed
+pcie_get_speed_cap(struct pci_dev *dev)
+{
+	device_t root;
+	uint32_t lnkcap, lnkcap2;
+	int error, pos;
+
+	root = device_get_parent(dev->dev.bsddev);
+	if (root == NULL)
+		return (PCI_SPEED_UNKNOWN);
+	root = device_get_parent(root);
+	if (root == NULL)
+		return (PCI_SPEED_UNKNOWN);
+	root = device_get_parent(root);
+	if (root == NULL)
+		return (PCI_SPEED_UNKNOWN);
+
+	if (pci_get_vendor(root) == PCI_VENDOR_ID_VIA ||
+	    pci_get_vendor(root) == PCI_VENDOR_ID_SERVERWORKS)
+		return (PCI_SPEED_UNKNOWN);
+
+	if ((error = pci_find_cap(root, PCIY_EXPRESS, &pos)) != 0)
+		return (PCI_SPEED_UNKNOWN);
+
+	lnkcap2 = pci_read_config(root, pos + PCIER_LINK_CAP2, 4);
+
+	if (lnkcap2) {	/* PCIe r3.0-compliant */
+		if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB)
+			return (PCIE_SPEED_2_5GT);
+		if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB)
+			return (PCIE_SPEED_5_0GT);
+		if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB)
+			return (PCIE_SPEED_8_0GT);
+		if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_16_0GB)
+			return (PCIE_SPEED_16_0GT);
+	} else {	/* pre-r3.0 */
+		lnkcap = pci_read_config(root, pos + PCIER_LINK_CAP, 4);
+		if (lnkcap & PCI_EXP_LNKCAP_SLS_2_5GB)
+			return (PCIE_SPEED_2_5GT);
+		if (lnkcap & PCI_EXP_LNKCAP_SLS_5_0GB)
+			return (PCIE_SPEED_5_0GT);
+		if (lnkcap & PCI_EXP_LNKCAP_SLS_8_0GB)
+			return (PCIE_SPEED_8_0GT);
+		if (lnkcap & PCI_EXP_LNKCAP_SLS_16_0GB)
+			return (PCIE_SPEED_16_0GT);
+	}
+	return (PCI_SPEED_UNKNOWN);
+}
+
+static inline enum pcie_link_width
+pcie_get_width_cap(struct pci_dev *dev)
+{
+	uint32_t lnkcap;
+
+	pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap);
+	if (lnkcap)
+		return ((lnkcap & PCI_EXP_LNKCAP_MLW) >> 4);
+
+	return (PCIE_LNK_WIDTH_UNKNOWN);
 }
 
 #endif	/* _LINUX_PCI_H_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201903131915.x2DJFbRk002502>