Commit 29e2501f authored by Zhigang Luo's avatar Zhigang Luo Committed by Alex Deucher
Browse files

drm/amdgpu: add CAP fw loading



The CAP fw is for enabling driver compatibility. Currently, it only
enabled for vega10 VF.

Signed-off-by: default avatarZhigang Luo <zhigang.luo@amd.com>
Reviewed-by: default avatarShaoyun Liu <Shaoyun.Liu@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 8e025615
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -159,6 +159,10 @@ static int psp_sw_fini(void *handle)
	adev->psp.sos_fw = NULL;
	release_firmware(adev->psp.asd_fw);
	adev->psp.asd_fw = NULL;
	if (adev->psp.cap_fw) {
		release_firmware(adev->psp.cap_fw);
		adev->psp.cap_fw = NULL;
	}
	if (adev->psp.ta_fw) {
		release_firmware(adev->psp.ta_fw);
		adev->psp.ta_fw = NULL;
@@ -246,7 +250,7 @@ psp_cmd_submit_buf(struct psp_context *psp,
		DRM_WARN("psp command (0x%X) failed and response status is (0x%X)\n",
			 psp->cmd_buf_mem->cmd_id,
			 psp->cmd_buf_mem->resp.status);
		if (!timeout) {
		if ((ucode->ucode_id == AMDGPU_UCODE_ID_CAP) || !timeout) {
			mutex_unlock(&psp->mutex);
			return -EINVAL;
		}
@@ -1188,6 +1192,9 @@ static int psp_get_fw_type(struct amdgpu_firmware_info *ucode,
			   enum psp_gfx_fw_type *type)
{
	switch (ucode->ucode_id) {
	case AMDGPU_UCODE_ID_CAP:
		*type = GFX_FW_TYPE_CAP;
		break;
	case AMDGPU_UCODE_ID_SDMA0:
		*type = GFX_FW_TYPE_SDMA0;
		break;
+3 −0
Original line number Diff line number Diff line
@@ -252,6 +252,9 @@ struct psp_context
	uint32_t			asd_ucode_size;
	uint8_t				*asd_start_addr;

	/* cap firmware */
	const struct firmware		*cap_fw;

	/* fence buffer */
	struct amdgpu_bo		*fence_buf_bo;
	uint64_t			fence_buf_mc_addr;
+2 −1
Original line number Diff line number Diff line
@@ -283,7 +283,8 @@ union amdgpu_firmware_header {
 * fw loading support
 */
enum AMDGPU_UCODE_ID {
	AMDGPU_UCODE_ID_SDMA0 = 0,
	AMDGPU_UCODE_ID_CAP = 0, /* CAP must be the 1st fw to be loaded */
	AMDGPU_UCODE_ID_SDMA0,
	AMDGPU_UCODE_ID_SDMA1,
	AMDGPU_UCODE_ID_SDMA2,
	AMDGPU_UCODE_ID_SDMA3,
+1 −0
Original line number Diff line number Diff line
@@ -246,6 +246,7 @@ enum psp_gfx_fw_type {
	GFX_FW_TYPE_SDMA6                           = 56,   /* SDMA6                    MI      */
	GFX_FW_TYPE_SDMA7                           = 57,   /* SDMA7                    MI      */
	GFX_FW_TYPE_VCN1                            = 58,   /* VCN1                     MI      */
	GFX_FW_TYPE_CAP                             = 62,   /* CAP_FW                   VG      */
	GFX_FW_TYPE_MAX
};

+24 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@

MODULE_FIRMWARE("amdgpu/vega10_sos.bin");
MODULE_FIRMWARE("amdgpu/vega10_asd.bin");
MODULE_FIRMWARE("amdgpu/vega10_cap.bin");
MODULE_FIRMWARE("amdgpu/vega12_sos.bin");
MODULE_FIRMWARE("amdgpu/vega12_asd.bin");

@@ -63,6 +64,7 @@ static int psp_v3_1_init_microcode(struct psp_context *psp)
	char fw_name[30];
	int err = 0;
	const struct psp_firmware_header_v1_0 *hdr;
	struct amdgpu_firmware_info *info = NULL;

	DRM_DEBUG("\n");

@@ -112,6 +114,26 @@ static int psp_v3_1_init_microcode(struct psp_context *psp)
	adev->psp.asd_start_addr = (uint8_t *)hdr +
				le32_to_cpu(hdr->header.ucode_array_offset_bytes);

	if (amdgpu_sriov_vf(adev) && adev->asic_type == CHIP_VEGA10) {
		snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_cap.bin",
			 chip_name);
		err = request_firmware(&adev->psp.cap_fw, fw_name, adev->dev);
		if (err)
			goto out;

		err = amdgpu_ucode_validate(adev->psp.cap_fw);
		if (err)
			goto out;

		info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CAP];
		info->ucode_id = AMDGPU_UCODE_ID_CAP;
		info->fw = adev->psp.cap_fw;
		hdr = (const struct psp_firmware_header_v1_0 *)
			      adev->psp.cap_fw->data;
		adev->firmware.fw_size += ALIGN(
			le32_to_cpu(hdr->header.ucode_size_bytes), PAGE_SIZE);
	}

	return 0;
out:
	if (err) {
@@ -122,6 +144,8 @@ out:
		adev->psp.sos_fw = NULL;
		release_firmware(adev->psp.asd_fw);
		adev->psp.asd_fw = NULL;
		release_firmware(adev->psp.cap_fw);
		adev->psp.cap_fw = NULL;
	}

	return err;