--- /dev/null
+From 2210af50ae7f4104269dfde7bafbbfbacdbe1a2b Mon Sep 17 00:00:00 2001
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Tue, 3 Jan 2023 13:18:19 -0600
+Subject: drm/amd: Add a new helper for loading/validating microcode
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+commit 2210af50ae7f4104269dfde7bafbbfbacdbe1a2b upstream.
+
+All microcode runs a basic validation after it's been loaded. Each
+IP block as part of init will run both.
+
+Introduce a wrapper for request_firmware and amdgpu_ucode_validate.
+This wrapper will also remap any error codes from request_firmware
+to -ENODEV. This is so that early_init will fail if firmware couldn't
+be loaded instead of the IP block being disabled.
+
+Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@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_ucode.c | 36 ++++++++++++++++++++++++++++++
+ drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 3 ++
+ 2 files changed, 39 insertions(+)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+@@ -1091,3 +1091,39 @@ void amdgpu_ucode_ip_version_decode(stru
+
+ snprintf(ucode_prefix, len, "%s_%d_%d_%d", ip_name, maj, min, rev);
+ }
++
++/*
++ * amdgpu_ucode_request - Fetch and validate amdgpu microcode
++ *
++ * @adev: amdgpu device
++ * @fw: pointer to load firmware to
++ * @fw_name: firmware to load
++ *
++ * This is a helper that will use request_firmware and amdgpu_ucode_validate
++ * to load and run basic validation on firmware. If the load fails, remap
++ * the error code to -ENODEV, so that early_init functions will fail to load.
++ */
++int amdgpu_ucode_request(struct amdgpu_device *adev, const struct firmware **fw,
++ const char *fw_name)
++{
++ int err = request_firmware(fw, fw_name, adev->dev);
++
++ if (err)
++ return -ENODEV;
++ err = amdgpu_ucode_validate(*fw);
++ if (err)
++ dev_dbg(adev->dev, "\"%s\" failed to validate\n", fw_name);
++
++ return err;
++}
++
++/*
++ * amdgpu_ucode_release - Release firmware microcode
++ *
++ * @fw: pointer to firmware to release
++ */
++void amdgpu_ucode_release(const struct firmware **fw)
++{
++ release_firmware(*fw);
++ *fw = NULL;
++}
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+@@ -544,6 +544,9 @@ void amdgpu_ucode_print_sdma_hdr(const s
+ void amdgpu_ucode_print_psp_hdr(const struct common_firmware_header *hdr);
+ void amdgpu_ucode_print_gpu_info_hdr(const struct common_firmware_header *hdr);
+ int amdgpu_ucode_validate(const struct firmware *fw);
++int amdgpu_ucode_request(struct amdgpu_device *adev, const struct firmware **fw,
++ const char *fw_name);
++void amdgpu_ucode_release(const struct firmware **fw);
+ bool amdgpu_ucode_hdr_version(union amdgpu_firmware_header *hdr,
+ uint16_t hdr_major, uint16_t hdr_minor);
+
--- /dev/null
+From cc42e76e7de5190a7da5dac9d7b2bbb458e050bf Mon Sep 17 00:00:00 2001
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Wed, 28 Dec 2022 01:28:40 -0600
+Subject: drm/amd: Load MES microcode during early_init
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+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 | 65 +++++++++++++++++++++
+ drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h | 1
+ drivers/gpu/drm/amd/amdgpu/mes_v10_1.c | 97 +++++---------------------------
+ drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 88 +++++------------------------
+ 4 files changed, 100 insertions(+), 151 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
+@@ -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;
++}
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
+@@ -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);
+
+--- a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
++++ b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
+@@ -379,82 +379,6 @@ static const struct amdgpu_mes_funcs mes
+ .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 *handl
+ 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 *han
+
+ 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,
+--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+@@ -460,73 +460,6 @@ static const struct amdgpu_mes_funcs mes
+ .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 *handl
+ 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 *han
+
+ 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,
--- /dev/null
+From 11e0b0067ec0707e8e598a5f9a547ab618ae7982 Mon Sep 17 00:00:00 2001
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Tue, 3 Jan 2023 14:12:37 -0600
+Subject: drm/amd: Use `amdgpu_ucode_*` helpers for MES
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+commit 11e0b0067ec0707e8e598a5f9a547ab618ae7982 upstream.
+
+The `amdgpu_ucode_request` helper will ensure that the return code for
+missing firmware is -ENODEV so that early_init can fail.
+
+The `amdgpu_ucode_release` helper provides symmetry for releasing firmware.
+
+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 | 10 ++--------
+ drivers/gpu/drm/amd/amdgpu/mes_v10_1.c | 10 +---------
+ drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 10 +---------
+ 3 files changed, 4 insertions(+), 26 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
+@@ -1438,11 +1438,7 @@ int amdgpu_mes_init_microcode(struct amd
+ 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]);
++ r = amdgpu_ucode_request(adev, &adev->mes.fw[pipe], fw_name);
+ if (r)
+ goto out;
+
+@@ -1482,9 +1478,7 @@ int amdgpu_mes_init_microcode(struct amd
+ }
+
+ return 0;
+-
+ out:
+- release_firmware(adev->mes.fw[pipe]);
+- adev->mes.fw[pipe] = NULL;
++ amdgpu_ucode_release(&adev->mes.fw[pipe]);
+ return r;
+ }
+--- a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
++++ b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
+@@ -379,13 +379,6 @@ static const struct amdgpu_mes_funcs mes
+ .resume_gang = mes_v10_1_resume_gang,
+ };
+
+-static void mes_v10_1_free_microcode(struct amdgpu_device *adev,
+- enum admgpu_mes_pipe pipe)
+-{
+- release_firmware(adev->mes.fw[pipe]);
+- adev->mes.fw[pipe] = NULL;
+-}
+-
+ static int mes_v10_1_allocate_ucode_buffer(struct amdgpu_device *adev,
+ enum admgpu_mes_pipe pipe)
+ {
+@@ -979,8 +972,7 @@ static int mes_v10_1_sw_fini(void *handl
+ amdgpu_bo_free_kernel(&adev->mes.eop_gpu_obj[pipe],
+ &adev->mes.eop_gpu_addr[pipe],
+ NULL);
+-
+- mes_v10_1_free_microcode(adev, pipe);
++ amdgpu_ucode_release(&adev->mes.fw[pipe]);
+ }
+
+ amdgpu_bo_free_kernel(&adev->gfx.kiq.ring.mqd_obj,
+--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+@@ -460,13 +460,6 @@ static const struct amdgpu_mes_funcs mes
+ .misc_op = mes_v11_0_misc_op,
+ };
+
+-static void mes_v11_0_free_microcode(struct amdgpu_device *adev,
+- enum admgpu_mes_pipe pipe)
+-{
+- release_firmware(adev->mes.fw[pipe]);
+- adev->mes.fw[pipe] = NULL;
+-}
+-
+ static int mes_v11_0_allocate_ucode_buffer(struct amdgpu_device *adev,
+ enum admgpu_mes_pipe pipe)
+ {
+@@ -1070,8 +1063,7 @@ static int mes_v11_0_sw_fini(void *handl
+ amdgpu_bo_free_kernel(&adev->mes.eop_gpu_obj[pipe],
+ &adev->mes.eop_gpu_addr[pipe],
+ NULL);
+-
+- mes_v11_0_free_microcode(adev, pipe);
++ amdgpu_ucode_release(&adev->mes.fw[pipe]);
+ }
+
+ amdgpu_bo_free_kernel(&adev->gfx.kiq.ring.mqd_obj,