summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/amdgpu
diff options
context:
space:
mode:
authorZhigang Luo <Zhigang.Luo@amd.com>2026-08-31 15:30:35 -0400
committerAlex Deucher <alexander.deucher@amd.com>2026-10-07 12:02:29 -0400
commit16c306d53d27fe102a1a54bbd0e57eb36900655d (patch)
tree67425ef29e6f53ef4b3bf9d0045f28e8ba162cd0 /drivers/gpu/drm/amd/amdgpu
parent9a403dc60f4c54cb81eb60fa8d639c59805fb38f (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.c55
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c3
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;