mirror of
https://github.com/torvalds/linux.git
synced 2026-04-24 01:25:49 -04:00
drm/amd: Load MES microcode during early_init
Add an early_init phase to MES for fetching and validating microcode from the filesystem. If MES microcode is required but not available during early init, the firmware framebuffer will have already been released and the screen will freeze. Move the request for MES microcode into the early_init phase so that if it's not available, early_init will fail. Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Lijo Lazar <lijo.lazar@amd.com> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
committed by
Alex Deucher
parent
0b8f42ab22
commit
cc42e76e7d
@@ -21,6 +21,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include "amdgpu_mes.h"
|
||||
#include "amdgpu.h"
|
||||
#include "soc15_common.h"
|
||||
@@ -1423,3 +1425,66 @@ error_pasid:
|
||||
kfree(vm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe)
|
||||
{
|
||||
const struct mes_firmware_header_v1_0 *mes_hdr;
|
||||
struct amdgpu_firmware_info *info;
|
||||
char ucode_prefix[30];
|
||||
char fw_name[40];
|
||||
int r;
|
||||
|
||||
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes%s.bin",
|
||||
ucode_prefix,
|
||||
pipe == AMDGPU_MES_SCHED_PIPE ? "" : "1");
|
||||
r = request_firmware(&adev->mes.fw[pipe], fw_name, adev->dev);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
r = amdgpu_ucode_validate(adev->mes.fw[pipe]);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
mes_hdr = (const struct mes_firmware_header_v1_0 *)
|
||||
adev->mes.fw[pipe]->data;
|
||||
adev->mes.uc_start_addr[pipe] =
|
||||
le32_to_cpu(mes_hdr->mes_uc_start_addr_lo) |
|
||||
((uint64_t)(le32_to_cpu(mes_hdr->mes_uc_start_addr_hi)) << 32);
|
||||
adev->mes.data_start_addr[pipe] =
|
||||
le32_to_cpu(mes_hdr->mes_data_start_addr_lo) |
|
||||
((uint64_t)(le32_to_cpu(mes_hdr->mes_data_start_addr_hi)) << 32);
|
||||
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
|
||||
int ucode, ucode_data;
|
||||
|
||||
if (pipe == AMDGPU_MES_SCHED_PIPE) {
|
||||
ucode = AMDGPU_UCODE_ID_CP_MES;
|
||||
ucode_data = AMDGPU_UCODE_ID_CP_MES_DATA;
|
||||
} else {
|
||||
ucode = AMDGPU_UCODE_ID_CP_MES1;
|
||||
ucode_data = AMDGPU_UCODE_ID_CP_MES1_DATA;
|
||||
}
|
||||
|
||||
info = &adev->firmware.ucode[ucode];
|
||||
info->ucode_id = ucode;
|
||||
info->fw = adev->mes.fw[pipe];
|
||||
adev->firmware.fw_size +=
|
||||
ALIGN(le32_to_cpu(mes_hdr->mes_ucode_size_bytes),
|
||||
PAGE_SIZE);
|
||||
|
||||
info = &adev->firmware.ucode[ucode_data];
|
||||
info->ucode_id = ucode_data;
|
||||
info->fw = adev->mes.fw[pipe];
|
||||
adev->firmware.fw_size +=
|
||||
ALIGN(le32_to_cpu(mes_hdr->mes_ucode_data_size_bytes),
|
||||
PAGE_SIZE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
release_firmware(adev->mes.fw[pipe]);
|
||||
adev->mes.fw[pipe] = NULL;
|
||||
return r;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user