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; +}