diff options
| author | Zhigang Luo <Zhigang.Luo@amd.com> | 2026-08-31 15:30:35 -0400 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2026-10-07 12:02:29 -0400 |
| commit | 16c306d53d27fe102a1a54bbd0e57eb36900655d (patch) | |
| tree | 67425ef29e6f53ef4b3bf9d0045f28e8ba162cd0 /drivers/gpu/drm/amd/amdgpu | |
| parent | 9a403dc60f4c54cb81eb60fa8d639c59805fb38f (diff) | |
drm/amdgpu: fetch the A+A VF VBIOS from the SRAT HBM range
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 <zhigang.luo@amd.com>
Signed-off-by: Fangsheng Huang <Fangsheng.Huang@amd.com>
Signed-off-by: YuBiao Wang <YuBiao.Wang@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 55 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 |
2 files changed, 58 insertions, 0 deletions
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 e7b0b2e1cd73..2daea1980c28 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -949,6 +949,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; |
