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
