mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 22:14:03 +02:00
drm/amdgpu: Fix GPU PCIe link capability reporting
Commiteb53125a7a("drm/amd: Add dedicated helper for amdgpu_device_find_parent()") made amdgpu_device_gpu_bandwidth() query the first device outside the dGPU. That is the host side of the physical link, not the GPU side. As a result, the ASIC and platform capability masks can both be based on the host port. drm_amdgpu_info_device then exposes the host capabilities to userspace, such as Gen5 x16 for a Gen4 x8 GPU. Cache both ends of the physical link during device initialization. Use link_dev for the GPU capability and link_partner for the platform capability and _PR3 detection. Reported-by: "Marek Olšák" <maraeo@gmail.com> Closes: https://lore.kernel.org/amd-gfx/CAAxE2A4VhsAzzO1QjBjUg+NgnbD04ZzMyN6xsUJxjKJHH6hxiw@mail.gmail.com/ Suggested-by: Lijo Lazar <lijo.lazar@amd.com> Fixes:eb53125a7a("drm/amd: Add dedicated helper for amdgpu_device_find_parent()") Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> (cherry picked from commit 7ea6a47224e2c6e89a3a682d7fbaace4817a55aa) Cc: stable@vger.kernel.org
This commit is contained in:
parent
723d4dc628
commit
04de4007d3
|
|
@ -621,6 +621,9 @@ enum amdgpu_enforce_isolation_mode {
|
|||
struct amdgpu_device {
|
||||
struct device *dev;
|
||||
struct pci_dev *pdev;
|
||||
/* The two ends of the physical PCIe link outside the device. */
|
||||
struct pci_dev *link_dev;
|
||||
struct pci_dev *link_partner;
|
||||
struct drm_device ddev;
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_ACP
|
||||
|
|
|
|||
|
|
@ -1954,18 +1954,17 @@ static void amdgpu_uid_fini(struct amdgpu_device *adev)
|
|||
adev->uid_info = NULL;
|
||||
}
|
||||
|
||||
static struct pci_dev *amdgpu_device_find_parent(struct amdgpu_device *adev)
|
||||
static void amdgpu_device_init_pcie_links(struct amdgpu_device *adev)
|
||||
{
|
||||
struct pci_dev *parent = adev->pdev;
|
||||
adev->link_dev = adev->pdev;
|
||||
adev->link_partner = pci_upstream_bridge(adev->link_dev);
|
||||
|
||||
/* skip upstream/downstream switches internal to dGPU */
|
||||
while ((parent = pci_upstream_bridge(parent))) {
|
||||
if (parent->vendor == PCI_VENDOR_ID_ATI)
|
||||
continue;
|
||||
break;
|
||||
/* Skip upstream/downstream switches internal to the dGPU. */
|
||||
while (adev->link_partner &&
|
||||
adev->link_partner->vendor == PCI_VENDOR_ID_ATI) {
|
||||
adev->link_dev = adev->link_partner;
|
||||
adev->link_partner = pci_upstream_bridge(adev->link_dev);
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1981,7 +1980,6 @@ static struct pci_dev *amdgpu_device_find_parent(struct amdgpu_device *adev)
|
|||
static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ip_block *ip_block;
|
||||
struct pci_dev *parent;
|
||||
bool total, skip_bios, early_full_gpu_access = false;
|
||||
uint32_t bios_flags;
|
||||
int i, r;
|
||||
|
|
@ -2077,10 +2075,9 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
|||
!dev_is_removable(&adev->pdev->dev))
|
||||
adev->flags |= AMD_IS_PX;
|
||||
|
||||
if (!(adev->flags & AMD_IS_APU)) {
|
||||
parent = amdgpu_device_find_parent(adev);
|
||||
adev->has_pr3 = parent ? pci_pr3_present(parent) : false;
|
||||
}
|
||||
if (!(adev->flags & AMD_IS_APU))
|
||||
adev->has_pr3 = adev->link_partner &&
|
||||
pci_pr3_present(adev->link_partner);
|
||||
|
||||
adev->pm.pp_feature = amdgpu_pp_feature_mask;
|
||||
if (amdgpu_sriov_vf(adev) || sched_policy == KFD_SCHED_POLICY_NO_HWS)
|
||||
|
|
@ -3776,6 +3773,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||
|
||||
adev->shutdown = false;
|
||||
adev->flags = flags;
|
||||
amdgpu_device_init_pcie_links(adev);
|
||||
|
||||
if (amdgpu_force_asic_type >= 0 && amdgpu_force_asic_type < CHIP_LAST)
|
||||
adev->asic_type = amdgpu_force_asic_type;
|
||||
|
|
@ -5872,11 +5870,9 @@ static void amdgpu_device_partner_bandwidth(struct amdgpu_device *adev,
|
|||
*width = PCIE_LNK_WIDTH_UNKNOWN;
|
||||
|
||||
if (amdgpu_device_pcie_dynamic_switching_supported(adev)) {
|
||||
struct pci_dev *parent = amdgpu_device_find_parent(adev);
|
||||
|
||||
if (parent) {
|
||||
*speed = pcie_get_speed_cap(parent);
|
||||
*width = pcie_get_width_cap(parent);
|
||||
if (adev->link_partner) {
|
||||
*speed = pcie_get_speed_cap(adev->link_partner);
|
||||
*width = pcie_get_width_cap(adev->link_partner);
|
||||
}
|
||||
} else {
|
||||
/* use the current speeds rather than max if switching is not supported */
|
||||
|
|
@ -5898,21 +5894,11 @@ static void amdgpu_device_gpu_bandwidth(struct amdgpu_device *adev,
|
|||
enum pci_bus_speed *speed,
|
||||
enum pcie_link_width *width)
|
||||
{
|
||||
struct pci_dev *parent = adev->pdev;
|
||||
|
||||
if (!speed || !width)
|
||||
return;
|
||||
|
||||
/* use the device itself */
|
||||
*speed = pcie_get_speed_cap(adev->pdev);
|
||||
*width = pcie_get_width_cap(adev->pdev);
|
||||
|
||||
/* use the link outside the device */
|
||||
parent = amdgpu_device_find_parent(adev);
|
||||
if (parent) {
|
||||
*speed = pcie_get_speed_cap(parent);
|
||||
*width = pcie_get_width_cap(parent);
|
||||
}
|
||||
*speed = pcie_get_speed_cap(adev->link_dev);
|
||||
*width = pcie_get_width_cap(adev->link_dev);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user