drm: enable almost all PCIe functionality

linux_pci.c revisions 1.24 and 1.25 implemented most of the remaining
missing PCIe backends, but only enabled them for some amdgpu portions.

this enables all code marked with "XXX amdgpu pcie", "XXX radeon pcie",
and "XXX pcie speed".  for most of it, simply removing #ifndefs __NetBSD__
to enable compliation was required, once the new "bus->max_bus_speed"
member was added to struct pci_bus.  add an "always fails" backend for
pci_enable_atomic_ops_to_root() which seems to only be necessary
for virtual GPU functionality (and could be implemented if needed.)

tested on radeon 5450, 7750, R7 240 [radeon], and RX 550 [amdgpu], and
nvidia 750 and 1030 [nouveau].


this still does not quite work on nvidia cards.  there are two problems
that remain:

- the call to set the link speed is skipped because the speed is set
  to the default value of "-1".  nvkm_pcie_set_link() will actually
  determine the right value for this and for some cards, calling this
  function if the current speed is -1 helps set the link speed.  it
  may be that on linux other paths we don't have enabled properly
  would set this (there's one via debugfs, and a jetson specific one,
  though perhaps setting either AC or DC speed values as boot options
  (after hooking up these for netbsd) would currently work.

- worse, cards newer than kepler - geforce 900, 1000, and newer, are
  all lacking the backing support to set pcie link speed.  the GT 1030
  card i have been testing with remains at pcie 1.0.
This commit is contained in:
mrg 2023-09-30 10:46:45 +00:00
parent 77e2579da2
commit 00c5a72cc0
14 changed files with 61 additions and 80 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: amdgpu_cik.c,v 1.6 2022/10/17 03:05:32 mrg Exp $ */
/* $NetBSD: amdgpu_cik.c,v 1.7 2023/09/30 10:46:45 mrg Exp $ */
/*
* Copyright 2012 Advanced Micro Devices, Inc.
@ -24,7 +24,7 @@
* Authors: Alex Deucher
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: amdgpu_cik.c,v 1.6 2022/10/17 03:05:32 mrg Exp $");
__KERNEL_RCSID(0, "$NetBSD: amdgpu_cik.c,v 1.7 2023/09/30 10:46:45 mrg Exp $");
#include <linux/firmware.h>
#include <linux/slab.h>
@ -1733,9 +1733,6 @@ static void cik_program_aspm(struct amdgpu_device *adev)
WREG32_PCIE(ixPCIE_LC_LINK_WIDTH_CNTL, data);
if (!disable_clkreq) {
#ifdef __NetBSD__ /* XXX amdgpu pcie */
clk_req_support = false;
#else
struct pci_dev *root = adev->pdev->bus->self;
u32 lnkcap;
@ -1743,7 +1740,6 @@ static void cik_program_aspm(struct amdgpu_device *adev)
pcie_capability_read_dword(root, PCI_EXP_LNKCAP, &lnkcap);
if (lnkcap & PCI_EXP_LNKCAP_CLKPM)
clk_req_support = true;
#endif
} else {
clk_req_support = false;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: amdgpu_device.c,v 1.19 2023/05/25 12:07:43 riastradh Exp $ */
/* $NetBSD: amdgpu_device.c,v 1.20 2023/09/30 10:46:45 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.19 2023/05/25 12:07:43 riastradh Exp $");
__KERNEL_RCSID(0, "$NetBSD: amdgpu_device.c,v 1.20 2023/09/30 10:46:45 mrg Exp $");
#include <linux/power_supply.h>
#include <linux/kthread.h>
@ -3091,7 +3091,6 @@ int amdgpu_device_init(struct amdgpu_device *adev,
DRM_INFO("PCI I/O BAR is not found.\n");
/* enable PCIE atomic ops */
#ifndef __NetBSD__ /* XXX amdgpu pcie atomics */
r = pci_enable_atomic_ops_to_root(adev->pdev,
PCI_EXP_DEVCAP2_ATOMIC_COMP32 |
PCI_EXP_DEVCAP2_ATOMIC_COMP64);
@ -3101,7 +3100,6 @@ int amdgpu_device_init(struct amdgpu_device *adev,
} else {
adev->have_atomics_support = true;
}
#endif
amdgpu_device_get_pcie_info(adev);

View File

@ -1,4 +1,4 @@
/* $NetBSD: amdgpu_si.c,v 1.4 2022/10/17 03:05:32 mrg Exp $ */
/* $NetBSD: amdgpu_si.c,v 1.5 2023/09/30 10:46:45 mrg Exp $ */
/*
* Copyright 2015 Advanced Micro Devices, Inc.
@ -24,7 +24,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: amdgpu_si.c,v 1.4 2022/10/17 03:05:32 mrg Exp $");
__KERNEL_RCSID(0, "$NetBSD: amdgpu_si.c,v 1.5 2023/09/30 10:46:45 mrg Exp $");
#include <linux/firmware.h>
#include <linux/slab.h>
@ -2077,7 +2077,6 @@ static void si_program_aspm(struct amdgpu_device *adev)
static void si_fix_pci_max_read_req_size(struct amdgpu_device *adev)
{
#ifndef __NetBSD__ /* XXX amdgpu pcie */
int readrq;
u16 v;
@ -2085,7 +2084,6 @@ static void si_fix_pci_max_read_req_size(struct amdgpu_device *adev)
v = ffs(readrq) - 8;
if ((v == 0) || (v == 6) || (v == 7))
pcie_set_readrq(adev->pdev, 512);
#endif
}
static int si_common_hw_init(void *handle)

View File

@ -1,4 +1,4 @@
/* $NetBSD: amdgpu_vi.c,v 1.3 2021/12/19 12:21:29 riastradh Exp $ */
/* $NetBSD: amdgpu_vi.c,v 1.4 2023/09/30 10:46:45 mrg Exp $ */
/*
* Copyright 2014 Advanced Micro Devices, Inc.
@ -24,7 +24,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: amdgpu_vi.c,v 1.3 2021/12/19 12:21:29 riastradh Exp $");
__KERNEL_RCSID(0, "$NetBSD: amdgpu_vi.c,v 1.4 2023/09/30 10:46:45 mrg Exp $");
#include <linux/pci.h>
#include <linux/slab.h>
@ -914,7 +914,6 @@ static int vi_set_vce_clocks(struct amdgpu_device *adev, u32 evclk, u32 ecclk)
static void vi_pcie_gen3_enable(struct amdgpu_device *adev)
{
#ifndef __NetBSD__ /* XXX amdgpu pcie */
if (pci_is_root_bus(adev->pdev->bus))
return;
@ -929,7 +928,6 @@ static void vi_pcie_gen3_enable(struct amdgpu_device *adev)
return;
/* todo */
#endif
}
static void vi_program_aspm(struct amdgpu_device *adev)

View File

@ -1,4 +1,4 @@
/* $NetBSD: nouveau_nvkm_subdev_pci_pcie.c,v 1.4 2023/09/30 10:38:31 mrg Exp $ */
/* $NetBSD: nouveau_nvkm_subdev_pci_pcie.c,v 1.5 2023/09/30 10:46:45 mrg Exp $ */
/*
* Copyright 2015 Karol Herbst <nouveau@karolherbst.de>
@ -24,7 +24,7 @@
* Authors: Karol Herbst <git@karolherbst.de>
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nouveau_nvkm_subdev_pci_pcie.c,v 1.4 2023/09/30 10:38:31 mrg Exp $");
__KERNEL_RCSID(0, "$NetBSD: nouveau_nvkm_subdev_pci_pcie.c,v 1.5 2023/09/30 10:46:45 mrg Exp $");
#include "priv.h"
@ -138,13 +138,6 @@ nvkm_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width)
return -ENODEV;
}
#ifdef __NetBSD__ /* XXX pcie speed */
__USE(cur_speed);
__USE(max_speed);
__USE(pbus);
__USE(nvkm_pcie_speed);
ret = 0;
#else
cur_speed = pci->func->pcie.cur_speed(pci);
max_speed = min(nvkm_pcie_speed(pbus->max_bus_speed),
pci->func->pcie.max_speed(pci));
@ -172,7 +165,6 @@ nvkm_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width)
ret = pci->func->pcie.set_link(pci, speed, width);
if (ret < 0)
nvkm_error(subdev, "setting link failed: %i\n", ret);
#endif
return ret;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: radeon_ci_dpm.c,v 1.6 2021/12/19 12:40:43 riastradh Exp $ */
/* $NetBSD: radeon_ci_dpm.c,v 1.7 2023/09/30 10:46:45 mrg Exp $ */
/*
* Copyright 2013 Advanced Micro Devices, Inc.
@ -24,7 +24,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: radeon_ci_dpm.c,v 1.6 2021/12/19 12:40:43 riastradh Exp $");
__KERNEL_RCSID(0, "$NetBSD: radeon_ci_dpm.c,v 1.7 2023/09/30 10:46:45 mrg Exp $");
#include <linux/firmware.h>
#include <linux/pci.h>
@ -5687,9 +5687,7 @@ int ci_dpm_init(struct radeon_device *rdev)
u8 frev, crev;
struct ci_power_info *pi;
enum pci_bus_speed speed_cap = PCI_SPEED_UNKNOWN;
#ifndef __NetBSD__ /* XXX radeon pcie */
struct pci_dev *root = rdev->pdev->bus->self;
#endif
int ret;
pi = kzalloc(sizeof(struct ci_power_info), GFP_KERNEL);
@ -5697,10 +5695,8 @@ int ci_dpm_init(struct radeon_device *rdev)
return -ENOMEM;
rdev->pm.dpm.priv = pi;
#ifndef __NetBSD__ /* XXX radeon pcie */
if (!pci_is_root_bus(rdev->pdev->bus))
speed_cap = pcie_get_speed_cap(root);
#endif
if (speed_cap == PCI_SPEED_UNKNOWN) {
pi->sys_pcie_mask = 0;
} else {

View File

@ -1,4 +1,4 @@
/* $NetBSD: radeon_cik.c,v 1.7 2022/10/17 03:05:32 mrg Exp $ */
/* $NetBSD: radeon_cik.c,v 1.8 2023/09/30 10:46:45 mrg Exp $ */
/*
* Copyright 2012 Advanced Micro Devices, Inc.
@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: radeon_cik.c,v 1.7 2022/10/17 03:05:32 mrg Exp $");
__KERNEL_RCSID(0, "$NetBSD: radeon_cik.c,v 1.8 2023/09/30 10:46:45 mrg Exp $");
#include <linux/firmware.h>
#include <linux/module.h>
@ -9827,17 +9827,13 @@ static void cik_program_aspm(struct radeon_device *rdev)
if (!disable_clkreq &&
!pci_is_root_bus(rdev->pdev->bus)) {
#ifndef __NetBSD__ /* XXX radeon pcie */
struct pci_dev *root = rdev->pdev->bus->self;
u32 lnkcap;
#endif
clk_req_support = false;
#ifndef __NetBSD__ /* XXX radeon pcie */
pcie_capability_read_dword(root, PCI_EXP_LNKCAP, &lnkcap);
if (lnkcap & PCI_EXP_LNKCAP_CLKPM)
clk_req_support = true;
#endif
} else {
clk_req_support = false;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: radeon_evergreen.c,v 1.5 2021/12/18 23:45:43 riastradh Exp $ */
/* $NetBSD: radeon_evergreen.c,v 1.6 2023/09/30 10:46:45 mrg Exp $ */
/*
* Copyright 2010 Advanced Micro Devices, Inc.
@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: radeon_evergreen.c,v 1.5 2021/12/18 23:45:43 riastradh Exp $");
__KERNEL_RCSID(0, "$NetBSD: radeon_evergreen.c,v 1.6 2023/09/30 10:46:45 mrg Exp $");
#include <linux/firmware.h>
#include <linux/pci.h>
@ -1285,7 +1285,6 @@ int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
{
#ifndef __NetBSD__ /* XXX radeon pcie */
int readrq;
u16 v;
@ -1296,7 +1295,6 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
*/
if ((v == 0) || (v == 6) || (v == 7))
pcie_set_readrq(rdev->pdev, 512);
#endif
}
void dce4_program_fmt(struct drm_encoder *encoder)
@ -5338,7 +5336,6 @@ void evergreen_fini(struct radeon_device *rdev)
void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
{
#ifndef __NetBSD__ /* XXX radeon pcie */
u32 link_width_cntl, speed_cntl;
if (radeon_pcie_gen2 == 0)
@ -5398,7 +5395,6 @@ void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
link_width_cntl &= ~LC_UPCONFIGURE_DIS;
WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
}
#endif
}
void evergreen_program_aspm(struct radeon_device *rdev)

View File

@ -1,4 +1,4 @@
/* $NetBSD: radeon_r600.c,v 1.6 2021/12/18 23:45:43 riastradh Exp $ */
/* $NetBSD: radeon_r600.c,v 1.7 2023/09/30 10:46:45 mrg Exp $ */
/*
* Copyright 2008 Advanced Micro Devices, Inc.
@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: radeon_r600.c,v 1.6 2021/12/18 23:45:43 riastradh Exp $");
__KERNEL_RCSID(0, "$NetBSD: radeon_r600.c,v 1.7 2023/09/30 10:46:45 mrg Exp $");
#include <linux/firmware.h>
#include <linux/module.h>
@ -4546,7 +4546,6 @@ int r600_get_pcie_lanes(struct radeon_device *rdev)
static void r600_pcie_gen2_enable(struct radeon_device *rdev)
{
#ifndef __NetBSD__ /* XXX radeon pcie */
u32 link_width_cntl, lanes, speed_cntl, training_cntl, tmp;
u16 link_cntl2;
@ -4657,7 +4656,6 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev)
link_width_cntl &= ~LC_UPCONFIGURE_DIS;
WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
}
#endif
}
/**

View File

@ -1,4 +1,4 @@
/* $NetBSD: radeon_rv770.c,v 1.2 2021/12/18 23:45:43 riastradh Exp $ */
/* $NetBSD: radeon_rv770.c,v 1.3 2023/09/30 10:46:45 mrg Exp $ */
/*
* Copyright 2008 Advanced Micro Devices, Inc.
@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: radeon_rv770.c,v 1.2 2021/12/18 23:45:43 riastradh Exp $");
__KERNEL_RCSID(0, "$NetBSD: radeon_rv770.c,v 1.3 2023/09/30 10:46:45 mrg Exp $");
#include <linux/firmware.h>
#include <linux/pci.h>
@ -2029,7 +2029,6 @@ void rv770_fini(struct radeon_device *rdev)
static void rv770_pcie_gen2_enable(struct radeon_device *rdev)
{
#ifndef __NetBSD__ /* XXX radeon pcie */
u32 link_width_cntl, lanes, speed_cntl, tmp;
u16 link_cntl2;
@ -2107,5 +2106,4 @@ static void rv770_pcie_gen2_enable(struct radeon_device *rdev)
link_width_cntl &= ~LC_UPCONFIGURE_DIS;
WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
}
#endif
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: radeon_si.c,v 1.5 2022/10/17 03:05:32 mrg Exp $ */
/* $NetBSD: radeon_si.c,v 1.6 2023/09/30 10:46:45 mrg Exp $ */
/*
* Copyright 2011 Advanced Micro Devices, Inc.
@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: radeon_si.c,v 1.5 2022/10/17 03:05:32 mrg Exp $");
__KERNEL_RCSID(0, "$NetBSD: radeon_si.c,v 1.6 2023/09/30 10:46:45 mrg Exp $");
#include <linux/firmware.h>
#include <linux/module.h>
@ -7414,17 +7414,13 @@ static void si_program_aspm(struct radeon_device *rdev)
if (!disable_clkreq &&
!pci_is_root_bus(rdev->pdev->bus)) {
#ifndef __NetBSD__ /* XXX radeon pcie */
struct pci_dev *root = rdev->pdev->bus->self;
u32 lnkcap;
#endif
clk_req_support = false;
#ifndef __NetBSD__ /* XXX radeon pcie */
pcie_capability_read_dword(root, PCI_EXP_LNKCAP, &lnkcap);
if (lnkcap & PCI_EXP_LNKCAP_CLKPM)
clk_req_support = true;
#endif
} else {
clk_req_support = false;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: radeon_si_dpm.c,v 1.8 2021/12/19 12:40:43 riastradh Exp $ */
/* $NetBSD: radeon_si_dpm.c,v 1.9 2023/09/30 10:46:45 mrg Exp $ */
/*
* Copyright 2013 Advanced Micro Devices, Inc.
@ -24,7 +24,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: radeon_si_dpm.c,v 1.8 2021/12/19 12:40:43 riastradh Exp $");
__KERNEL_RCSID(0, "$NetBSD: radeon_si_dpm.c,v 1.9 2023/09/30 10:46:45 mrg Exp $");
#include <linux/math64.h>
#include <linux/pci.h>
@ -6908,9 +6908,7 @@ int si_dpm_init(struct radeon_device *rdev)
struct si_power_info *si_pi;
struct atom_clock_dividers dividers;
enum pci_bus_speed speed_cap = PCI_SPEED_UNKNOWN;
#ifndef __NetBSD__ /* XXX radeon pcie */
struct pci_dev *root = rdev->pdev->bus->self;
#endif
int ret;
si_pi = kzalloc(sizeof(struct si_power_info), GFP_KERNEL);
@ -6921,10 +6919,8 @@ int si_dpm_init(struct radeon_device *rdev)
eg_pi = &ni_pi->eg;
pi = &eg_pi->rv7xx;
#ifndef __NetBSD__ /* XXX radeon pcie */
if (!pci_is_root_bus(rdev->pdev->bus))
speed_cap = pcie_get_speed_cap(root);
#endif
if (speed_cap == PCI_SPEED_UNKNOWN) {
si_pi->sys_pcie_mask = 0;
} else {

View File

@ -1,4 +1,4 @@
/* $NetBSD: pci.h,v 1.56 2022/10/25 23:37:06 riastradh Exp $ */
/* $NetBSD: pci.h,v 1.57 2023/09/30 10:46:46 mrg Exp $ */
/*-
* Copyright (c) 2013 The NetBSD Foundation, Inc.
@ -62,17 +62,7 @@
struct acpi_devnode;
struct pci_driver;
struct pci_dev;
struct pci_bus {
/* NetBSD private members */
pci_chipset_tag_t pb_pc;
device_t pb_dev;
/* Linux API */
u_int number;
struct pci_dev *self;
};
struct pci_bus;
struct pci_device_id {
uint32_t vendor;
@ -150,6 +140,8 @@ CTASSERT(PCI_CLASS_BRIDGE_ISA == 0x0601);
#define PCI_EXP_LNKCTL2_TLS_8_0GT PCIE_LCSR2_TGT_LSPEED_8G
#define PCI_EXP_LNKCAP PCIE_LCAP
#define PCI_EXP_LNKCAP_CLKPM PCIE_LCAP_CLOCK_PM
#define PCI_EXP_DEVCAP2_ATOMIC_COMP32 PCIE_DCAP2_32ATOM
#define PCI_EXP_DEVCAP2_ATOMIC_COMP64 PCIE_DCAP2_64ATOM
typedef int pci_power_t;
@ -233,6 +225,18 @@ enum pcie_link_width {
#define __pci_rom_iomem
struct pci_bus {
/* NetBSD private members */
pci_chipset_tag_t pb_pc;
device_t pb_dev;
/* Linux API */
u_int number;
enum pci_bus_speed max_bus_speed;
struct pci_dev *self;
};
/* Namespace. */
#define pci_bus_alloc_resource linux_pci_bus_alloc_resource
#define pci_bus_read_config_byte linux_pci_bus_read_config_byte
@ -289,6 +293,7 @@ enum pcie_link_width {
#define pcie_read_config_word linux_pcie_capability_read_word
#define pcie_write_config_dword linux_pcie_capability_write_dword
#define pcie_write_config_word linux_pcie_capability_write_word
#define pci_enable_atomic_ops_to_root linux_pci_enable_atomic_ops_to_root
/* NetBSD local additions. */
void linux_pci_dev_init(struct pci_dev *, device_t, device_t,
@ -397,4 +402,11 @@ dev_is_pci(struct device *dev)
return parent && device_is_a(parent, "pci");
}
static inline int
pci_enable_atomic_ops_to_root(struct pci_dev *dev, uint32_t cap_mask)
{
return -EINVAL;
}
#endif /* _LINUX_PCI_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: linux_pci.c,v 1.26 2023/09/04 21:31:58 mrg Exp $ */
/* $NetBSD: linux_pci.c,v 1.27 2023/09/30 10:46:46 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.26 2023/09/04 21:31:58 mrg Exp $");
__KERNEL_RCSID(0, "$NetBSD: linux_pci.c,v 1.27 2023/09/30 10:46:46 mrg Exp $");
#if NACPICA > 0
#include <dev/acpi/acpivar.h>
@ -169,6 +169,17 @@ linux_pci_dev_init(struct pci_dev *pdev, device_t dev, device_t parent,
pdev->bus->pb_pc = pa->pa_pc;
pdev->bus->pb_dev = parent;
pdev->bus->number = pa->pa_bus;
/*
* NetBSD doesn't have an easy "am I PCIe" or "give me PCIe speed
* from capability" function, but we already emulate the Linux
* versions that do.
*/
if (pci_is_pcie(pdev)) {
pdev->bus->max_bus_speed = pcie_get_speed_cap(pdev);
} else {
/* XXX: Do AGP/PCI-X, etc.? */
pdev->bus->max_bus_speed = PCI_SPEED_UNKNOWN;
}
pdev->bus->self = alloc_fake_parent_device(parent, pa);
pdev->devfn = PCI_DEVFN(pa->pa_device, pa->pa_function);
pdev->vendor = PCI_VENDOR(pa->pa_id);