⬢ DragonFlyBSD Kernel Audit
DF-4785 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/amd/amdgpu/psp_v11_0.c
+++ b/sys/dev/drm/amd/amdgpu/psp_v11_0.c
@@ -34,6 +34,7 @@
 #include "nbio/nbio_7_4_offset.h"
 
 MODULE_FIRMWARE("amdgpufw_vega20_sos");
+MODULE_FIRMWARE("amdgpufw_vega20_asd");
 
 /* address block */
 #define smnMP1_FIRMWARE_FLAGS		0x3010024
@@ -129,6 +130,30 @@
 				le32_to_cpu(hdr->header.ucode_array_offset_bytes);
 	adev->psp.sos_start_addr = (uint8_t *)adev->psp.sys_start_addr +
 				le32_to_cpu(hdr->sos_offset_bytes);
+
+	/* psp_hw_start() -> psp_asd_load() consumes asd_start_addr and
+	 * asd_ucode_size unconditionally; without this block they stay
+	 * NULL/0 for Vega20 and the generic code memcpy()s from NULL and
+	 * submits a zero-length LOAD_ASD whose PSP rejection is then
+	 * swallowed (psp_cmd_submit_buf ignores resp.status for
+	 * ucode == NULL).  Mirror psp_v3_1_init_microcode().
+	 */
+	snprintf(fw_name, sizeof(fw_name), "amdgpufw_%s_asd", chip_name);
+	err = request_firmware(&adev->psp.asd_fw, fw_name, adev->dev);
+	if (err)
+		goto out;
+
+	err = amdgpu_ucode_validate(adev->psp.asd_fw);
+	if (err)
+		goto out;
+
+	hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.asd_fw->data;
+	adev->psp.asd_fw_version = le32_to_cpu(hdr->header.ucode_version);
+	adev->psp.asd_feature_version = le32_to_cpu(hdr->ucode_feature_version);
+	adev->psp.asd_ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
+	adev->psp.asd_start_addr = (uint8_t *)hdr +
+				le32_to_cpu(hdr->header.ucode_array_offset_bytes);
+
 	return 0;
 out:
 	if (err) {
@@ -137,6 +162,8 @@
 			fw_name);
 		release_firmware(adev->psp.sos_fw);
 		adev->psp.sos_fw = NULL;
+		release_firmware(adev->psp.asd_fw);
+		adev->psp.asd_fw = NULL;
 	}
 
 	return err;