On systems where PCI bus renumbering occurs (e.g. pci=realloc, resource conflicts), the runtime bus number may differ from the BIOS POST bus number recorded in the VFCT table. This causes radeon_acpi_vfct_bios() to fail finding the VBIOS even though the correct device entry exists.
Introduce radeon_acpi_vfct_match() which treats the bus number as a soft filter: vendor/device/function identity is the hard requirement, while exact bus match is the preferred path. When bus numbers disagree but device identity matches, accept the VFCT entry and log a dev_notice for diagnostics. This mirrors the equivalent amdgpu change. Signed-off-by: Mario Limonciello <[email protected]> --- Cc: Oz Tiram <[email protected]> drivers/gpu/drm/radeon/radeon_bios.c | 45 ++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index c6df799c3cf4a..cc10880af096b 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -596,6 +596,45 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev) return legacy_read_disabled_bios(rdev); } +/** + * radeon_acpi_vfct_match() - Check if a VFCT entry matches the device + * @rdev: Radeon device + * @vhdr: VFCT image header to check + * + * VFCT entries contain the PCI bus number as recorded during BIOS POST. + * On systems where the kernel renumbers PCI buses (e.g. pci=realloc or + * resource conflicts), the runtime bus number may differ from the POST + * value. Match by device identity (vendor + device + function) and use + * the bus number as a preference: exact bus match is preferred, but when + * the bus numbers disagree we accept the entry if the device identity + * matches. + * + * Returns: 0 on match, -ENODEV on no match + */ +static int radeon_acpi_vfct_match(struct radeon_device *rdev, + VFCT_IMAGE_HEADER *vhdr) +{ + /* Vendor and device IDs must always match */ + if (vhdr->VendorID != rdev->pdev->vendor || + vhdr->DeviceID != rdev->pdev->device) + return -ENODEV; + + if (vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn)) + return -ENODEV; + + /* Exact bus number match - preferred */ + if (vhdr->PCIBus == rdev->pdev->bus->number) + return 0; + + /* Bus mismatch but device identity matches (PCI renumbering case) */ + dev_notice(&rdev->pdev->dev, + "VFCT bus number mismatch: table %u != runtime %u, matching by device identity (vendor 0x%04x device 0x%04x)\n", + vhdr->PCIBus, rdev->pdev->bus->number, + rdev->pdev->vendor, rdev->pdev->device); + return 0; +} + #ifdef CONFIG_ACPI static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) { @@ -633,11 +672,7 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) } if (vhdr->ImageLength && - vhdr->PCIBus == rdev->pdev->bus->number && - vhdr->PCIDevice == PCI_SLOT(rdev->pdev->devfn) && - vhdr->PCIFunction == PCI_FUNC(rdev->pdev->devfn) && - vhdr->VendorID == rdev->pdev->vendor && - vhdr->DeviceID == rdev->pdev->device) { + !radeon_acpi_vfct_match(rdev, vhdr)) { rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); -- 2.43.0
