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;