On A+A the VF has no usable FB BAR, so the VBIOS copy cannot be read
through BAR 0. It lives in HBM, which the SRAT describes as
specific-purpose memory reachable at a system physical address.

Add a dedicated amdgpu_read_bios_from_spm() path that resolves the HBM
range from SRAT and maps it as write-back system memory. Keep the
existing SR-IOV dynamic critical region path when it is enabled,
matching the VRAM reader.

v2:
- Use a separate amdgpu_read_bios_from_spm() helper and leave
  amdgpu_read_bios_from_vram() unchanged.
- Keep the SR-IOV dynamic critical region path for SPM-backed VBIOS.
- Fetch VBIOS after the COMMON block and make it optional for
  SPM-backed SR-IOV VF and passthrough configurations.

v3:
- Keep the SRAT range local to the VBIOS path; GMC owns aper_base and
  aper_size.
- Map SPM with memremap(), memcpy(), and memunmap().
- Rely on amdgpu_virt_vram_is_spm() without redundant VF/passthrough
  checks.

Signed-off-by: Zhigang Luo <[email protected]>
Signed-off-by: Fangsheng Huang <[email protected]>
Signed-off-by: YuBiao Wang <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c   | 55 ++++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c |  3 ++
 2 files changed, 58 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
index 08ed1eb69558..f9315e0472fe 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -152,6 +152,56 @@ static bool amdgpu_read_bios_from_vram(struct 
amdgpu_device *adev)
        return true;
 }
 
+static bool amdgpu_read_bios_from_spm(struct amdgpu_device *adev)
+{
+       u64 spm_base, spm_size;
+       void *bios = NULL;
+       u32 size = 256U * 1024U; /* ??? */
+       int r;
+
+       if (!amdgpu_virt_vram_is_spm(adev))
+               return false;
+
+       r = amdgpu_acpi_find_gpu_memory_in_srat(adev, &spm_base, &spm_size);
+       if (r)
+               return false;
+
+       adev->bios = kmalloc(size, GFP_KERNEL);
+       if (!adev->bios)
+               return false;
+
+       /* For SRIOV with dynamic critical region is enabled,
+        * the vbios image is put at a dynamic offset of VRAM in the VF.
+        * If dynamic critical region is disabled, read it from SPM.
+        */
+       if (amdgpu_sriov_vf(adev) && adev->virt.is_dynamic_crit_regn_enabled) {
+               if (amdgpu_virt_get_dynamic_data_info(adev,
+                                                     
AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID,
+                                                     adev->bios, &size)) {
+                       amdgpu_bios_release(adev);
+                       return false;
+               }
+       } else {
+               bios = memremap(spm_base, size, MEMREMAP_WB);
+               if (!bios) {
+                       amdgpu_bios_release(adev);
+                       return false;
+               }
+
+               memcpy(adev->bios, bios, size);
+               memunmap(bios);
+       }
+
+       adev->bios_size = size;
+
+       if (!check_atom_bios(adev, size)) {
+               amdgpu_bios_release(adev);
+               return false;
+       }
+
+       return true;
+}
+
 bool amdgpu_read_bios(struct amdgpu_device *adev)
 {
        uint8_t __iomem *bios;
@@ -530,6 +580,11 @@ static bool amdgpu_get_bios_dgpu(struct amdgpu_device 
*adev)
                goto success;
        }
 
+       if (amdgpu_read_bios_from_spm(adev)) {
+               dev_info(adev->dev, "Fetched VBIOS from SPM\n");
+               goto success;
+       }
+
        /* this is required for SR-IOV */
        if (amdgpu_read_bios_from_vram(adev)) {
                dev_info(adev->dev, "Fetched VBIOS from VRAM BAR\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 96165b1b3e6d..4b43c80a30af 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -944,6 +944,9 @@ u32 amdgpu_device_get_rev_id(struct amdgpu_device *adev)
 
 static uint32_t amdgpu_device_get_vbios_flags(struct amdgpu_device *adev)
 {
+       if (amdgpu_virt_vram_is_spm(adev))
+               return AMDGPU_VBIOS_OPTIONAL;
+
        if (hweight32(adev->aid_mask) && (adev->flags & AMD_IS_APU))
                return AMDGPU_VBIOS_SKIP;
 
-- 
2.43.0

Reply via email to