]> git.itanic.dy.fi Git - linux-stable/commitdiff
drm/amd: Load MES microcode during early_init
authorMario Limonciello <mario.limonciello@amd.com>
Wed, 28 Dec 2022 07:28:40 +0000 (01:28 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 May 2023 11:59:07 +0000 (13:59 +0200)
commit cc42e76e7de5190a7da5dac9d7b2bbb458e050bf upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
drivers/gpu/drm/amd/amdgpu/mes_v11_0.c

index 0c546245793b9c292851db1098ce14c2f27fe734..dd8f3523450719d1b25e92b671723095bede049a 100644 (file)
@@ -21,6 +21,8 @@
  *
  */
 
+#include <linux/firmware.h>
+
 #include "amdgpu_mes.h"
 #include "amdgpu.h"
 #include "soc15_common.h"
@@ -1423,3 +1425,66 @@ int amdgpu_mes_self_test(struct amdgpu_device *adev)
        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;
+}
index 97c05d08a551a3a06d2d3c185267700aa6a817d9..547ec35691fac633e2e7f0256cfdbdadc583d5c8 100644 (file)
@@ -306,6 +306,7 @@ struct amdgpu_mes_funcs {
 
 int amdgpu_mes_ctx_get_offs(struct amdgpu_ring *ring, unsigned int id_offs);
 
+int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe);
 int amdgpu_mes_init(struct amdgpu_device *adev);
 void amdgpu_mes_fini(struct amdgpu_device *adev);
 
index 614394118a53e25ca8afbeb41ff505f738bcd264..9c5ff8b7c202dc7de60654d0e732fde4267d20eb 100644 (file)
@@ -379,82 +379,6 @@ static const struct amdgpu_mes_funcs mes_v10_1_funcs = {
        .resume_gang = mes_v10_1_resume_gang,
 };
 
-static int mes_v10_1_init_microcode(struct amdgpu_device *adev,
-                                   enum admgpu_mes_pipe pipe)
-{
-       const char *chip_name;
-       char fw_name[30];
-       int err;
-       const struct mes_firmware_header_v1_0 *mes_hdr;
-       struct amdgpu_firmware_info *info;
-
-       switch (adev->ip_versions[GC_HWIP][0]) {
-       case IP_VERSION(10, 1, 10):
-               chip_name = "navi10";
-               break;
-       case IP_VERSION(10, 3, 0):
-               chip_name = "sienna_cichlid";
-               break;
-       default:
-               BUG();
-       }
-
-       if (pipe == AMDGPU_MES_SCHED_PIPE)
-               snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes.bin",
-                        chip_name);
-       else
-               snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes1.bin",
-                        chip_name);
-
-       err = request_firmware(&adev->mes.fw[pipe], fw_name, adev->dev);
-       if (err)
-               return err;
-
-       err = amdgpu_ucode_validate(adev->mes.fw[pipe]);
-       if (err) {
-               release_firmware(adev->mes.fw[pipe]);
-               adev->mes.fw[pipe] = NULL;
-               return err;
-       }
-
-       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;
-}
-
 static void mes_v10_1_free_microcode(struct amdgpu_device *adev,
                                     enum admgpu_mes_pipe pipe)
 {
@@ -1019,10 +943,6 @@ static int mes_v10_1_sw_init(void *handle)
                if (!adev->enable_mes_kiq && pipe == AMDGPU_MES_KIQ_PIPE)
                        continue;
 
-               r = mes_v10_1_init_microcode(adev, pipe);
-               if (r)
-                       return r;
-
                r = mes_v10_1_allocate_eop_buf(adev, pipe);
                if (r)
                        return r;
@@ -1229,6 +1149,22 @@ static int mes_v10_1_resume(void *handle)
        return amdgpu_mes_resume(adev);
 }
 
+static int mes_v10_0_early_init(void *handle)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       int pipe, r;
+
+       for (pipe = 0; pipe < AMDGPU_MAX_MES_PIPES; pipe++) {
+               if (!adev->enable_mes_kiq && pipe == AMDGPU_MES_KIQ_PIPE)
+                       continue;
+               r = amdgpu_mes_init_microcode(adev, pipe);
+               if (r)
+                       return r;
+       }
+
+       return 0;
+}
+
 static int mes_v10_0_late_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -1241,6 +1177,7 @@ static int mes_v10_0_late_init(void *handle)
 
 static const struct amd_ip_funcs mes_v10_1_ip_funcs = {
        .name = "mes_v10_1",
+       .early_init = mes_v10_0_early_init,
        .late_init = mes_v10_0_late_init,
        .sw_init = mes_v10_1_sw_init,
        .sw_fini = mes_v10_1_sw_fini,
index 1c4787000a5f392e08018e9ac5d27d363cc7dc85..ffc7e3ca51e31aec32c9ed8f237f275c84d3e111 100644 (file)
@@ -460,73 +460,6 @@ static const struct amdgpu_mes_funcs mes_v11_0_funcs = {
        .misc_op = mes_v11_0_misc_op,
 };
 
-static int mes_v11_0_init_microcode(struct amdgpu_device *adev,
-                                   enum admgpu_mes_pipe pipe)
-{
-       char fw_name[30];
-       char ucode_prefix[30];
-       int err;
-       const struct mes_firmware_header_v1_0 *mes_hdr;
-       struct amdgpu_firmware_info *info;
-
-       amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
-
-       if (pipe == AMDGPU_MES_SCHED_PIPE)
-               snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes.bin",
-                        ucode_prefix);
-       else
-               snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes1.bin",
-                        ucode_prefix);
-
-       err = request_firmware(&adev->mes.fw[pipe], fw_name, adev->dev);
-       if (err)
-               return err;
-
-       err = amdgpu_ucode_validate(adev->mes.fw[pipe]);
-       if (err) {
-               release_firmware(adev->mes.fw[pipe]);
-               adev->mes.fw[pipe] = NULL;
-               return err;
-       }
-
-       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;
-}
-
 static void mes_v11_0_free_microcode(struct amdgpu_device *adev,
                                     enum admgpu_mes_pipe pipe)
 {
@@ -1101,10 +1034,6 @@ static int mes_v11_0_sw_init(void *handle)
                if (!adev->enable_mes_kiq && pipe == AMDGPU_MES_KIQ_PIPE)
                        continue;
 
-               r = mes_v11_0_init_microcode(adev, pipe);
-               if (r)
-                       return r;
-
                r = mes_v11_0_allocate_eop_buf(adev, pipe);
                if (r)
                        return r;
@@ -1339,6 +1268,22 @@ static int mes_v11_0_resume(void *handle)
        return amdgpu_mes_resume(adev);
 }
 
+static int mes_v11_0_early_init(void *handle)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       int pipe, r;
+
+       for (pipe = 0; pipe < AMDGPU_MAX_MES_PIPES; pipe++) {
+               if (!adev->enable_mes_kiq && pipe == AMDGPU_MES_KIQ_PIPE)
+                       continue;
+               r = amdgpu_mes_init_microcode(adev, pipe);
+               if (r)
+                       return r;
+       }
+
+       return 0;
+}
+
 static int mes_v11_0_late_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -1353,6 +1298,7 @@ static int mes_v11_0_late_init(void *handle)
 
 static const struct amd_ip_funcs mes_v11_0_ip_funcs = {
        .name = "mes_v11_0",
+       .early_init = mes_v11_0_early_init,
        .late_init = mes_v11_0_late_init,
        .sw_init = mes_v11_0_sw_init,
        .sw_fini = mes_v11_0_sw_fini,