@@ -372,19 +372,59 @@ static bool amdgpu_read_disabled_bios(struct amdgpu_device *adev)
372372}
373373
374374#ifdef CONFIG_ACPI
375+ /**
376+ * amdgpu_acpi_vfct_match() - Check if a VFCT entry matches the device
377+ * @adev: AMDGPU device
378+ * @vhdr: VFCT image header to check
379+ *
380+ * VFCT entries contain the PCI bus number as recorded during BIOS POST.
381+ * On systems where the kernel renumbers PCI buses (e.g. pci=realloc or
382+ * resource conflicts), the runtime bus number may differ from the POST
383+ * value. Match by device identity (vendor + device + function) and use
384+ * the bus number as a preference: exact bus match is preferred, but when
385+ * the bus numbers disagree we accept the entry if the device identity
386+ * matches.
387+ *
388+ * Returns: 0 on match, -ENODEV on no match
389+ */
390+ static int amdgpu_acpi_vfct_match (struct amdgpu_device * adev ,
391+ VFCT_IMAGE_HEADER * vhdr )
392+ {
393+ /* Vendor and device IDs must always match */
394+ if (vhdr -> VendorID != adev -> pdev -> vendor ||
395+ vhdr -> DeviceID != adev -> pdev -> device )
396+ return - ENODEV ;
397+
398+ if (vhdr -> PCIDevice != PCI_SLOT (adev -> pdev -> devfn ) ||
399+ vhdr -> PCIFunction != PCI_FUNC (adev -> pdev -> devfn ))
400+ return - ENODEV ;
401+
402+ /* Exact bus number match - preferred */
403+ if (vhdr -> PCIBus == adev -> pdev -> bus -> number )
404+ return 0 ;
405+
406+ /* Bus mismatch but device identity matches (PCI renumbering case) */
407+ dev_notice (adev -> dev ,
408+ "VFCT bus number mismatch: table %u != runtime %u, matching by device identity (vendor 0x%04x device 0x%04x)\n" ,
409+ vhdr -> PCIBus , adev -> pdev -> bus -> number ,
410+ adev -> pdev -> vendor , adev -> pdev -> device );
411+ return 0 ;
412+ }
413+
375414static bool amdgpu_acpi_vfct_bios (struct amdgpu_device * adev )
376415{
377416 struct acpi_table_header * hdr ;
378417 acpi_size tbl_size ;
379418 UEFI_ACPI_VFCT * vfct ;
380419 unsigned int offset ;
420+ bool r = false;
381421
382422 if (!ACPI_SUCCESS (acpi_get_table ("VFCT" , 1 , & hdr )))
383423 return false;
384424 tbl_size = hdr -> length ;
385425 if (tbl_size < sizeof (UEFI_ACPI_VFCT )) {
386426 dev_info (adev -> dev , "ACPI VFCT table present but broken (too short #1),skipping\n" );
387- return false ;
427+ goto out ;
388428 }
389429
390430 vfct = (UEFI_ACPI_VFCT * )hdr ;
@@ -397,36 +437,36 @@ static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
397437 offset += sizeof (VFCT_IMAGE_HEADER );
398438 if (offset > tbl_size ) {
399439 dev_info (adev -> dev , "ACPI VFCT image header truncated,skipping\n" );
400- return false ;
440+ goto out ;
401441 }
402442
403443 offset += vhdr -> ImageLength ;
404444 if (offset > tbl_size ) {
405445 dev_info (adev -> dev , "ACPI VFCT image truncated,skipping\n" );
406- return false ;
446+ goto out ;
407447 }
408448
409449 if (vhdr -> ImageLength &&
410- vhdr -> PCIBus == adev -> pdev -> bus -> number &&
411- vhdr -> PCIDevice == PCI_SLOT (adev -> pdev -> devfn ) &&
412- vhdr -> PCIFunction == PCI_FUNC (adev -> pdev -> devfn ) &&
413- vhdr -> VendorID == adev -> pdev -> vendor &&
414- vhdr -> DeviceID == adev -> pdev -> device ) {
450+ !amdgpu_acpi_vfct_match (adev , vhdr )) {
415451 adev -> bios = kmemdup (& vbios -> VbiosContent ,
416452 vhdr -> ImageLength ,
417453 GFP_KERNEL );
418454
419455 if (!check_atom_bios (adev , vhdr -> ImageLength )) {
420456 amdgpu_bios_release (adev );
421- return false ;
457+ goto out ;
422458 }
423459 adev -> bios_size = vhdr -> ImageLength ;
424- return true;
460+ r = true;
461+ goto out ;
425462 }
426463 }
427464
428465 dev_info (adev -> dev , "ACPI VFCT table present but broken (too short #2),skipping\n" );
429- return false;
466+
467+ out :
468+ acpi_put_table (hdr );
469+ return r ;
430470}
431471#else
432472static inline bool amdgpu_acpi_vfct_bios (struct amdgpu_device * adev )
0 commit comments