Module Name:    src
Committed By:   mrg
Date:           Tue Sep 20 23:01:42 UTC 2022

Modified Files:
        src/sys/dev/pci: pcireg.h
        src/sys/external/bsd/drm2/dist/drm/amd/amdgpu: amdgpu_device.c
        src/sys/external/bsd/drm2/include/linux: pci.h
        src/sys/external/bsd/drm2/linux: linux_pci.c

Log Message:
fill out more of the linux pci API compat

- implement pcie_get_speed_cap(), pcie_bandwidth_available(), and
  pci_is_root_bus().
- expand "enum pci_bus_speed" to add PCIe 5.x and 6.x speeds.
- add "enum pcie_link_width".
- add defines for PCIE_LCSR_LINKSPEED (PCIe generation) and PCIE_LCSR_NLW
  (negotiated lane width) to pcireg.h
- enable amdgpu_device_get_pcie_info() code now it works.

ok riastradh@


To generate a diff of this commit:
cvs rdiff -u -r1.165 -r1.166 src/sys/dev/pci/pcireg.h
cvs rdiff -u -r1.16 -r1.17 \
    src/sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_device.c
cvs rdiff -u -r1.53 -r1.54 src/sys/external/bsd/drm2/include/linux/pci.h
cvs rdiff -u -r1.23 -r1.24 src/sys/external/bsd/drm2/linux/linux_pci.c

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/pcireg.h
diff -u src/sys/dev/pci/pcireg.h:1.165 src/sys/dev/pci/pcireg.h:1.166
--- src/sys/dev/pci/pcireg.h:1.165	Mon Jan 31 10:14:55 2022
+++ src/sys/dev/pci/pcireg.h	Tue Sep 20 23:01:42 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: pcireg.h,v 1.165 2022/01/31 10:14:55 msaitoh Exp $	*/
+/*	$NetBSD: pcireg.h,v 1.166 2022/09/20 23:01:42 mrg Exp $	*/
 
 /*
  * Copyright (c) 1995, 1996, 1999, 2000
@@ -1063,7 +1063,20 @@ typedef u_int8_t pci_revision_t;
 #define PCIE_LCSR_LABIE		__BIT(11)      /* Link Autonomous BW Intr En */
 #define	PCIE_LCSR_DRSSGNL	__BITS(15, 14) /* DRS Signaling */
 #define	PCIE_LCSR_LINKSPEED	__BITS(19, 16) /* Link Speed */
+#define  PCIE_LCSR_LINKSPEED_2	1	       /* 2.5GT/s */
+#define  PCIE_LCSR_LINKSPEED_5	2	       /* 5GT/s */
+#define  PCIE_LCSR_LINKSPEED_8	3	       /* 8GT/s */
+#define  PCIE_LCSR_LINKSPEED_16	4	       /* 16GT/s */
+#define  PCIE_LCSR_LINKSPEED_32	5	       /* 32GT/s */
+#define  PCIE_LCSR_LINKSPEED_64	6	       /* 64GT/s */
 #define	PCIE_LCSR_NLW		__BITS(25, 20) /* Negotiated Link Width */
+#define  PCIE_LCSR_NLW_X1	__BIT(20)	/* Negotiated x1 */
+#define  PCIE_LCSR_NLW_X2	__BIT(21)	/* Negotiated x2 */
+#define  PCIE_LCSR_NLW_X4	__BIT(22)	/* Negotiated x4 */
+#define  PCIE_LCSR_NLW_X8	__BIT(23)	/* Negotiated x8 */
+#define  PCIE_LCSR_NLW_X12	__BITS(22, 23)	/* Negotiated x12 */
+#define  PCIE_LCSR_NLW_X16	__BIT(24)	/* Negotiated x16 */
+#define  PCIE_LCSR_NLW_X32	__BIT(25)	/* Negotiated x32 */
 #define	PCIE_LCSR_LINKTRAIN_ERR	__BIT(10 + 16) /* Link Training Error */
 #define	PCIE_LCSR_LINKTRAIN	__BIT(11 + 16) /* Link Training */
 #define	PCIE_LCSR_SLOTCLKCFG	__BIT(12 + 16) /* Slot Clock Configuration */

Index: src/sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_device.c
diff -u src/sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_device.c:1.16 src/sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_device.c:1.17
--- src/sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_device.c:1.16	Sun Dec 19 12:41:33 2021
+++ src/sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_device.c	Tue Sep 20 23:01:42 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: amdgpu_device.c,v 1.16 2021/12/19 12:41:33 riastradh Exp $	*/
+/*	$NetBSD: amdgpu_device.c,v 1.17 2022/09/20 23:01:42 mrg Exp $	*/
 
 /*
  * Copyright 2008 Advanced Micro Devices, Inc.
@@ -28,7 +28,7 @@
  *          Jerome Glisse
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: amdgpu_device.c,v 1.16 2021/12/19 12:41:33 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: amdgpu_device.c,v 1.17 2022/09/20 23:01:42 mrg Exp $");
 
 #include <linux/power_supply.h>
 #include <linux/kthread.h>
@@ -4447,7 +4447,6 @@ skip_sched_resume:
  */
 static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev)
 {
-#ifndef __NetBSD__		/* XXX amdgpu pcie */
 	struct pci_dev *pdev;
 	enum pci_bus_speed speed_cap, platform_speed_cap;
 	enum pcie_link_width platform_link_width;
@@ -4571,7 +4570,6 @@ static void amdgpu_device_get_pcie_info(
 			}
 		}
 	}
-#endif
 }
 
 int amdgpu_device_baco_enter(struct drm_device *dev)

Index: src/sys/external/bsd/drm2/include/linux/pci.h
diff -u src/sys/external/bsd/drm2/include/linux/pci.h:1.53 src/sys/external/bsd/drm2/include/linux/pci.h:1.54
--- src/sys/external/bsd/drm2/include/linux/pci.h:1.53	Sun Feb 27 14:23:08 2022
+++ src/sys/external/bsd/drm2/include/linux/pci.h	Tue Sep 20 23:01:42 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: pci.h,v 1.53 2022/02/27 14:23:08 riastradh Exp $	*/
+/*	$NetBSD: pci.h,v 1.54 2022/09/20 23:01:42 mrg Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -190,6 +190,24 @@ enum pci_bus_speed {
 	PCIE_SPEED_5_0GT,
 	PCIE_SPEED_8_0GT,
 	PCIE_SPEED_16_0GT,
+	PCIE_SPEED_32_0GT,
+	PCIE_SPEED_64_0GT,
+};
+
+/*
+ * Actually values from the Link Status register, bits 16-19.  Don't use
+ * these as a bit-mask -- these are the only known, valid values.
+ */
+enum pcie_link_width {
+	PCIE_LNK_WIDTH_RESRV   = 0,
+	PCIE_LNK_X1            = __BIT(0),
+	PCIE_LNK_X2            = __BIT(1),
+	PCIE_LNK_X4            = __BIT(2),
+	PCIE_LNK_X8            = __BIT(3),
+	PCIE_LNK_X12           = __BITS(2,3),
+	PCIE_LNK_X16           = __BIT(4),
+	PCIE_LNK_X32           = __BIT(5),
+	PCIE_LNK_WIDTH_UNKNOWN = __BITS(0, 7),
 };
 
 #define	PCIBIOS_MIN_MEM	0x100000	/* XXX bogus x86 kludge bollocks */
@@ -242,6 +260,8 @@ enum pci_bus_speed {
 #define	pci_write_config_dword		linux_pci_write_config_dword
 #define	pci_write_config_word		linux_pci_write_config_word
 #define	pcibios_align_resource		linux_pcibios_align_resource
+#define	pcie_get_speed_cap		linux_pcie_get_speed_cap
+#define	pcie_bandwidth_available	linux_pcie_bandwidth_available
 
 /* NetBSD local additions.  */
 void		linux_pci_dev_init(struct pci_dev *, device_t, device_t,
@@ -323,6 +343,12 @@ void		pci_iounmap(struct pci_dev *, void
 void		pci_save_state(struct pci_dev *);
 void		pci_restore_state(struct pci_dev *);
 
+enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev);
+unsigned	pcie_bandwidth_available(struct pci_dev *dev,
+					 struct pci_dev **limiting_dev,
+					 enum pci_bus_speed *speed,
+					 enum pcie_link_width *width);
+
 static inline bool
 dev_is_pci(struct device *dev)
 {

Index: src/sys/external/bsd/drm2/linux/linux_pci.c
diff -u src/sys/external/bsd/drm2/linux/linux_pci.c:1.23 src/sys/external/bsd/drm2/linux/linux_pci.c:1.24
--- src/sys/external/bsd/drm2/linux/linux_pci.c:1.23	Wed Jul 20 01:20:20 2022
+++ src/sys/external/bsd/drm2/linux/linux_pci.c	Tue Sep 20 23:01:42 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_pci.c,v 1.23 2022/07/20 01:20:20 riastradh Exp $	*/
+/*	$NetBSD: linux_pci.c,v 1.24 2022/09/20 23:01:42 mrg Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_pci.c,v 1.23 2022/07/20 01:20:20 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_pci.c,v 1.24 2022/09/20 23:01:42 mrg Exp $");
 
 #if NACPICA > 0
 #include <dev/acpi/acpivar.h>
@@ -716,8 +716,7 @@ bool
 pci_is_root_bus(struct pci_bus *bus)
 {
 
-	/* XXX Cop-out. */
-	return false;
+	return bus->number == 0;
 }
 
 int
@@ -800,3 +799,141 @@ linux_pci_dev_destroy(struct pci_dev *pd
 	KASSERT(pdev->pd_saved_state == NULL);
 	KASSERT(pdev->pd_intr_handles == NULL);
 }
+
+enum pci_bus_speed
+pcie_get_speed_cap(struct pci_dev *dev)
+{
+	pci_chipset_tag_t pc = dev->pd_pa.pa_pc;
+	pcitag_t tag = dev->pd_pa.pa_tag;
+	pcireg_t lcap, lcap2, xcap;
+	int off;
+
+	/* Must have capabilities. */
+	if (pci_get_capability(pc, tag, PCI_CAP_PCIEXPRESS, &off, NULL) == 0)
+		return PCI_SPEED_UNKNOWN;
+
+	/* Only PCIe 3.x has LCAP2. */
+	xcap = pci_conf_read(pc, tag, off + PCIE_XCAP);
+	if (__SHIFTOUT(xcap, PCIE_XCAP_VER_MASK) >= 2) {
+		lcap2 = pci_conf_read(pc, tag, off + PCIE_LCAP2);
+		if (lcap2) {
+			if ((lcap2 & PCIE_LCAP2_SUP_LNKS64) != 0) {
+				return PCIE_SPEED_64_0GT;
+			}
+			if ((lcap2 & PCIE_LCAP2_SUP_LNKS32) != 0) {
+				return PCIE_SPEED_32_0GT;
+			}
+			if ((lcap2 & PCIE_LCAP2_SUP_LNKS16) != 0) {
+				return PCIE_SPEED_16_0GT;
+			}
+			if ((lcap2 & PCIE_LCAP2_SUP_LNKS8) != 0) {
+				return PCIE_SPEED_8_0GT;
+			}
+			if ((lcap2 & PCIE_LCAP2_SUP_LNKS5) != 0) {
+				return PCIE_SPEED_5_0GT;
+			}
+			if ((lcap2 & PCIE_LCAP2_SUP_LNKS2) != 0) {
+				return PCIE_SPEED_2_5GT;
+			}
+		}
+	}
+
+	lcap = pci_conf_read(pc, tag, off + PCIE_LCAP);
+	if ((lcap & PCIE_LCAP_MAX_SPEED) == PCIE_LCAP_MAX_SPEED_64) {
+		return PCIE_SPEED_64_0GT;
+	}
+	if ((lcap & PCIE_LCAP_MAX_SPEED) == PCIE_LCAP_MAX_SPEED_32) {
+		return PCIE_SPEED_32_0GT;
+	}
+	if ((lcap & PCIE_LCAP_MAX_SPEED) == PCIE_LCAP_MAX_SPEED_16) {
+		return PCIE_SPEED_16_0GT;
+	}
+	if ((lcap & PCIE_LCAP_MAX_SPEED) == PCIE_LCAP_MAX_SPEED_8) {
+		return PCIE_SPEED_8_0GT;
+	}
+	if ((lcap & PCIE_LCAP_MAX_SPEED) == PCIE_LCAP_MAX_SPEED_5) {
+		return PCIE_SPEED_5_0GT;
+	}
+	if ((lcap & PCIE_LCAP_MAX_SPEED) == PCIE_LCAP_MAX_SPEED_2) {
+		return PCIE_SPEED_2_5GT;
+	}
+
+	return PCI_SPEED_UNKNOWN;
+}
+
+/*
+ * This should walk the tree, it only checks this device currently.
+ * It also does not write to limiting_dev (the only caller in drm2
+ * currently does not use it.)
+ */
+unsigned
+pcie_bandwidth_available(struct pci_dev *dev,
+    struct pci_dev **limiting_dev,
+    enum pci_bus_speed *speed,
+    enum pcie_link_width *width)
+{
+	pci_chipset_tag_t pc = dev->pd_pa.pa_pc;
+	pcitag_t tag = dev->pd_pa.pa_tag;
+	pcireg_t lcsr;
+	unsigned per_line_speed, num_lanes;
+	int off;
+
+	/* Must have capabilities. */
+	if (pci_get_capability(pc, tag, PCI_CAP_PCIEXPRESS, &off, NULL) == 0)
+		return 0;
+
+	if (speed)
+		*speed = PCI_SPEED_UNKNOWN;
+	if (width)
+		*width = 0;
+
+	lcsr = pci_conf_read(pc, tag, off + PCIE_LCSR);
+
+	switch (lcsr & PCIE_LCSR_NLW) {
+	case PCIE_LCSR_NLW_X1:
+	case PCIE_LCSR_NLW_X2:
+	case PCIE_LCSR_NLW_X4:
+	case PCIE_LCSR_NLW_X8:
+	case PCIE_LCSR_NLW_X12:
+	case PCIE_LCSR_NLW_X16:
+	case PCIE_LCSR_NLW_X32:
+		num_lanes = __SHIFTOUT(lcsr, PCIE_LCSR_NLW);
+		if (width)
+			*width = num_lanes;
+		break;
+	default:
+		num_lanes = 0;
+		break;
+	}
+
+	switch (__SHIFTOUT(lcsr, PCIE_LCSR_LINKSPEED)) {
+	case PCIE_LCSR_LINKSPEED_2:
+		*speed = PCIE_SPEED_2_5GT;
+		per_line_speed = 2500 * 8 / 10;
+		break;
+	case PCIE_LCSR_LINKSPEED_5:
+		*speed = PCIE_SPEED_5_0GT;
+		per_line_speed = 5000 * 8 / 10;
+		break;
+	case PCIE_LCSR_LINKSPEED_8:
+		*speed = PCIE_SPEED_8_0GT;
+		per_line_speed = 8000 * 128 / 130;
+		break;
+	case PCIE_LCSR_LINKSPEED_16:
+		*speed = PCIE_SPEED_16_0GT;
+		per_line_speed = 16000 * 128 / 130;
+		break;
+	case PCIE_LCSR_LINKSPEED_32:
+		*speed = PCIE_SPEED_32_0GT;
+		per_line_speed = 32000 * 128 / 130;
+		break;
+	case PCIE_LCSR_LINKSPEED_64:
+		*speed = PCIE_SPEED_64_0GT;
+		per_line_speed = 64000 * 128 / 130;
+		break;
+	default:
+		per_line_speed = 0;
+	}
+
+	return num_lanes * per_line_speed;
+}

Reply via email to