diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 561 | 
1 files changed, 540 insertions, 21 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index c027e5e7713e..e1b8d8daeafc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -32,6 +32,9 @@  #include "psp_v3_1.h"  #include "psp_v10_0.h"  #include "psp_v11_0.h" +#include "psp_v12_0.h" + +#include "amdgpu_ras.h"  static void psp_set_funcs(struct amdgpu_device *adev); @@ -53,13 +56,19 @@ static int psp_early_init(void *handle)  		psp->autoload_supported = false;  		break;  	case CHIP_VEGA20: +	case CHIP_ARCTURUS:  		psp_v11_0_set_psp_funcs(psp);  		psp->autoload_supported = false;  		break;  	case CHIP_NAVI10: +	case CHIP_NAVI14: +	case CHIP_NAVI12:  		psp_v11_0_set_psp_funcs(psp);  		psp->autoload_supported = true;  		break; +	case CHIP_RENOIR: +		psp_v12_0_set_psp_funcs(psp); +		break;  	default:  		return -EINVAL;  	} @@ -81,6 +90,17 @@ static int psp_sw_init(void *handle)  		return ret;  	} +	ret = psp_mem_training_init(psp); +	if (ret) { +		DRM_ERROR("Failed to initialize memory training!\n"); +		return ret; +	} +	ret = psp_mem_training(psp, PSP_MEM_TRAIN_COLD_BOOT); +	if (ret) { +		DRM_ERROR("Failed to process memory training!\n"); +		return ret; +	} +  	return 0;  } @@ -88,6 +108,7 @@ static int psp_sw_fini(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; +	psp_mem_training_fini(&adev->psp);  	release_firmware(adev->psp.sos_fw);  	adev->psp.sos_fw = NULL;  	release_firmware(adev->psp.asd_fw); @@ -137,18 +158,26 @@ psp_cmd_submit_buf(struct psp_context *psp,  	memcpy(psp->cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp));  	index = atomic_inc_return(&psp->fence_value); -	ret = psp_cmd_submit(psp, ucode, psp->cmd_buf_mc_addr, -			     fence_mc_addr, index); +	ret = psp_cmd_submit(psp, psp->cmd_buf_mc_addr, fence_mc_addr, index);  	if (ret) {  		atomic_dec(&psp->fence_value);  		mutex_unlock(&psp->mutex);  		return ret;  	} +	amdgpu_asic_invalidate_hdp(psp->adev, NULL);  	while (*((unsigned int *)psp->fence_buf) != index) {  		if (--timeout == 0)  			break; +		/* +		 * Shouldn't wait for timeout when err_event_athub occurs, +		 * because gpu reset thread triggered and lock resource should +		 * be released for psp resume sequence. +		 */ +		if (amdgpu_ras_intr_triggered()) +			break;  		msleep(1); +		amdgpu_asic_invalidate_hdp(psp->adev, NULL);  	}  	/* In some cases, psp response status is not 0 even there is no @@ -162,8 +191,9 @@ psp_cmd_submit_buf(struct psp_context *psp,  		if (ucode)  			DRM_WARN("failed to load ucode id (%d) ",  				  ucode->ucode_id); -		DRM_WARN("psp command failed and response status is (%d)\n", -			  psp->cmd_buf_mem->resp.status); +		DRM_DEBUG_DRIVER("psp command (0x%X) failed and response status is (0x%X)\n", +			 psp->cmd_buf_mem->cmd_id, +			 psp->cmd_buf_mem->resp.status & GFX_CMD_STATUS_MASK);  		if (!timeout) {  			mutex_unlock(&psp->mutex);  			return -EINVAL; @@ -233,6 +263,8 @@ static int psp_tmr_init(struct psp_context *psp)  {  	int ret;  	int tmr_size; +	void *tmr_buf; +	void **pptr;  	/*  	 * According to HW engineer, they prefer the TMR address be "naturally @@ -245,7 +277,8 @@ static int psp_tmr_init(struct psp_context *psp)  	/* For ASICs support RLC autoload, psp will parse the toc  	 * and calculate the total size of TMR needed */ -	if (psp->toc_start_addr && +	if (!amdgpu_sriov_vf(psp->adev) && +	    psp->toc_start_addr &&  	    psp->toc_bin_size &&  	    psp->fw_pri_buf) {  		ret = psp_load_toc(psp, &tmr_size); @@ -255,9 +288,10 @@ static int psp_tmr_init(struct psp_context *psp)  		}  	} +	pptr = amdgpu_sriov_vf(psp->adev) ? &tmr_buf : NULL;  	ret = amdgpu_bo_create_kernel(psp->adev, tmr_size, PSP_TMR_SIZE,  				      AMDGPU_GEM_DOMAIN_VRAM, -				      &psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf); +				      &psp->tmr_bo, &psp->tmr_mc_addr, pptr);  	return ret;  } @@ -278,15 +312,9 @@ static int psp_tmr_load(struct psp_context *psp)  	ret = psp_cmd_submit_buf(psp, NULL, cmd,  				 psp->fence_buf_mc_addr); -	if (ret) -		goto failed;  	kfree(cmd); -	return 0; - -failed: -	kfree(cmd);  	return ret;  } @@ -539,7 +567,9 @@ static int psp_xgmi_initialize(struct psp_context *psp)  	struct ta_xgmi_shared_memory *xgmi_cmd;  	int ret; -	if (!psp->adev->psp.ta_fw) +	if (!psp->adev->psp.ta_fw || +	    !psp->adev->psp.ta_xgmi_ucode_size || +	    !psp->adev->psp.ta_xgmi_start_addr)  		return -ENOENT;  	if (!psp->xgmi_context.initialized) { @@ -728,6 +758,12 @@ static int psp_ras_terminate(struct psp_context *psp)  {  	int ret; +	/* +	 * TODO: bypass the terminate in sriov for now +	 */ +	if (amdgpu_sriov_vf(psp->adev)) +		return 0; +  	if (!psp->ras.ras_initialized)  		return 0; @@ -749,6 +785,18 @@ static int psp_ras_initialize(struct psp_context *psp)  {  	int ret; +	/* +	 * TODO: bypass the initialize in sriov for now +	 */ +	if (amdgpu_sriov_vf(psp->adev)) +		return 0; + +	if (!psp->adev->psp.ta_ras_ucode_size || +	    !psp->adev->psp.ta_ras_start_addr) { +		dev_warn(psp->adev->dev, "RAS: ras ta ucode is not available\n"); +		return 0; +	} +  	if (!psp->ras.ras_initialized) {  		ret = psp_ras_init_shared_buf(psp);  		if (ret) @@ -763,6 +811,360 @@ static int psp_ras_initialize(struct psp_context *psp)  }  // ras end +// HDCP start +static void psp_prep_hdcp_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, +					  uint64_t hdcp_ta_mc, +					  uint64_t hdcp_mc_shared, +					  uint32_t hdcp_ta_size, +					  uint32_t shared_size) +{ +	cmd->cmd_id = GFX_CMD_ID_LOAD_TA; +	cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(hdcp_ta_mc); +	cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(hdcp_ta_mc); +	cmd->cmd.cmd_load_ta.app_len = hdcp_ta_size; + +	cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = +		lower_32_bits(hdcp_mc_shared); +	cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = +		upper_32_bits(hdcp_mc_shared); +	cmd->cmd.cmd_load_ta.cmd_buf_len = shared_size; +} + +static int psp_hdcp_init_shared_buf(struct psp_context *psp) +{ +	int ret; + +	/* +	 * Allocate 16k memory aligned to 4k from Frame Buffer (local +	 * physical) for hdcp ta <-> Driver +	 */ +	ret = amdgpu_bo_create_kernel(psp->adev, PSP_HDCP_SHARED_MEM_SIZE, +				      PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, +				      &psp->hdcp_context.hdcp_shared_bo, +				      &psp->hdcp_context.hdcp_shared_mc_addr, +				      &psp->hdcp_context.hdcp_shared_buf); + +	return ret; +} + +static int psp_hdcp_load(struct psp_context *psp) +{ +	int ret; +	struct psp_gfx_cmd_resp *cmd; + +	/* +	 * TODO: bypass the loading in sriov for now +	 */ +	if (amdgpu_sriov_vf(psp->adev)) +		return 0; + +	cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); +	if (!cmd) +		return -ENOMEM; + +	memset(psp->fw_pri_buf, 0, PSP_1_MEG); +	memcpy(psp->fw_pri_buf, psp->ta_hdcp_start_addr, +	       psp->ta_hdcp_ucode_size); + +	psp_prep_hdcp_ta_load_cmd_buf(cmd, psp->fw_pri_mc_addr, +				      psp->hdcp_context.hdcp_shared_mc_addr, +				      psp->ta_hdcp_ucode_size, +				      PSP_HDCP_SHARED_MEM_SIZE); + +	ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); + +	if (!ret) { +		psp->hdcp_context.hdcp_initialized = 1; +		psp->hdcp_context.session_id = cmd->resp.session_id; +	} + +	kfree(cmd); + +	return ret; +} +static int psp_hdcp_initialize(struct psp_context *psp) +{ +	int ret; + +	/* +	 * TODO: bypass the initialize in sriov for now +	 */ +	if (amdgpu_sriov_vf(psp->adev)) +		return 0; + +	if (!psp->adev->psp.ta_hdcp_ucode_size || +	    !psp->adev->psp.ta_hdcp_start_addr) { +		dev_warn(psp->adev->dev, "HDCP: hdcp ta ucode is not available\n"); +		return 0; +	} + +	if (!psp->hdcp_context.hdcp_initialized) { +		ret = psp_hdcp_init_shared_buf(psp); +		if (ret) +			return ret; +	} + +	ret = psp_hdcp_load(psp); +	if (ret) +		return ret; + +	return 0; +} +static void psp_prep_hdcp_ta_unload_cmd_buf(struct psp_gfx_cmd_resp *cmd, +					    uint32_t hdcp_session_id) +{ +	cmd->cmd_id = GFX_CMD_ID_UNLOAD_TA; +	cmd->cmd.cmd_unload_ta.session_id = hdcp_session_id; +} + +static int psp_hdcp_unload(struct psp_context *psp) +{ +	int ret; +	struct psp_gfx_cmd_resp *cmd; + +	/* +	 * TODO: bypass the unloading in sriov for now +	 */ +	if (amdgpu_sriov_vf(psp->adev)) +		return 0; + +	cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); +	if (!cmd) +		return -ENOMEM; + +	psp_prep_hdcp_ta_unload_cmd_buf(cmd, psp->hdcp_context.session_id); + +	ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); + +	kfree(cmd); + +	return ret; +} + +static void psp_prep_hdcp_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd, +					    uint32_t ta_cmd_id, +					    uint32_t hdcp_session_id) +{ +	cmd->cmd_id = GFX_CMD_ID_INVOKE_CMD; +	cmd->cmd.cmd_invoke_cmd.session_id = hdcp_session_id; +	cmd->cmd.cmd_invoke_cmd.ta_cmd_id = ta_cmd_id; +	/* Note: cmd_invoke_cmd.buf is not used for now */ +} + +int psp_hdcp_invoke(struct psp_context *psp, uint32_t ta_cmd_id) +{ +	int ret; +	struct psp_gfx_cmd_resp *cmd; + +	/* +	 * TODO: bypass the loading in sriov for now +	 */ +	if (amdgpu_sriov_vf(psp->adev)) +		return 0; + +	cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); +	if (!cmd) +		return -ENOMEM; + +	psp_prep_hdcp_ta_invoke_cmd_buf(cmd, ta_cmd_id, +					psp->hdcp_context.session_id); + +	ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); + +	kfree(cmd); + +	return ret; +} + +static int psp_hdcp_terminate(struct psp_context *psp) +{ +	int ret; + +	/* +	 * TODO: bypass the terminate in sriov for now +	 */ +	if (amdgpu_sriov_vf(psp->adev)) +		return 0; + +	if (!psp->hdcp_context.hdcp_initialized) +		return 0; + +	ret = psp_hdcp_unload(psp); +	if (ret) +		return ret; + +	psp->hdcp_context.hdcp_initialized = 0; + +	/* free hdcp shared memory */ +	amdgpu_bo_free_kernel(&psp->hdcp_context.hdcp_shared_bo, +			      &psp->hdcp_context.hdcp_shared_mc_addr, +			      &psp->hdcp_context.hdcp_shared_buf); + +	return 0; +} +// HDCP end + +// DTM start +static void psp_prep_dtm_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, +					 uint64_t dtm_ta_mc, +					 uint64_t dtm_mc_shared, +					 uint32_t dtm_ta_size, +					 uint32_t shared_size) +{ +	cmd->cmd_id = GFX_CMD_ID_LOAD_TA; +	cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(dtm_ta_mc); +	cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(dtm_ta_mc); +	cmd->cmd.cmd_load_ta.app_len = dtm_ta_size; + +	cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = lower_32_bits(dtm_mc_shared); +	cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = upper_32_bits(dtm_mc_shared); +	cmd->cmd.cmd_load_ta.cmd_buf_len = shared_size; +} + +static int psp_dtm_init_shared_buf(struct psp_context *psp) +{ +	int ret; + +	/* +	 * Allocate 16k memory aligned to 4k from Frame Buffer (local +	 * physical) for dtm ta <-> Driver +	 */ +	ret = amdgpu_bo_create_kernel(psp->adev, PSP_DTM_SHARED_MEM_SIZE, +				      PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, +				      &psp->dtm_context.dtm_shared_bo, +				      &psp->dtm_context.dtm_shared_mc_addr, +				      &psp->dtm_context.dtm_shared_buf); + +	return ret; +} + +static int psp_dtm_load(struct psp_context *psp) +{ +	int ret; +	struct psp_gfx_cmd_resp *cmd; + +	/* +	 * TODO: bypass the loading in sriov for now +	 */ +	if (amdgpu_sriov_vf(psp->adev)) +		return 0; + +	cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); +	if (!cmd) +		return -ENOMEM; + +	memset(psp->fw_pri_buf, 0, PSP_1_MEG); +	memcpy(psp->fw_pri_buf, psp->ta_dtm_start_addr, psp->ta_dtm_ucode_size); + +	psp_prep_dtm_ta_load_cmd_buf(cmd, psp->fw_pri_mc_addr, +				     psp->dtm_context.dtm_shared_mc_addr, +				     psp->ta_dtm_ucode_size, +				     PSP_DTM_SHARED_MEM_SIZE); + +	ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); + +	if (!ret) { +		psp->dtm_context.dtm_initialized = 1; +		psp->dtm_context.session_id = cmd->resp.session_id; +	} + +	kfree(cmd); + +	return ret; +} + +static int psp_dtm_initialize(struct psp_context *psp) +{ +	int ret; + +	/* +	 * TODO: bypass the initialize in sriov for now +	 */ +	if (amdgpu_sriov_vf(psp->adev)) +		return 0; + +	if (!psp->adev->psp.ta_dtm_ucode_size || +	    !psp->adev->psp.ta_dtm_start_addr) { +		dev_warn(psp->adev->dev, "DTM: dtm ta ucode is not available\n"); +		return 0; +	} + +	if (!psp->dtm_context.dtm_initialized) { +		ret = psp_dtm_init_shared_buf(psp); +		if (ret) +			return ret; +	} + +	ret = psp_dtm_load(psp); +	if (ret) +		return ret; + +	return 0; +} + +static void psp_prep_dtm_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd, +					   uint32_t ta_cmd_id, +					   uint32_t dtm_session_id) +{ +	cmd->cmd_id = GFX_CMD_ID_INVOKE_CMD; +	cmd->cmd.cmd_invoke_cmd.session_id = dtm_session_id; +	cmd->cmd.cmd_invoke_cmd.ta_cmd_id = ta_cmd_id; +	/* Note: cmd_invoke_cmd.buf is not used for now */ +} + +int psp_dtm_invoke(struct psp_context *psp, uint32_t ta_cmd_id) +{ +	int ret; +	struct psp_gfx_cmd_resp *cmd; + +	/* +	 * TODO: bypass the loading in sriov for now +	 */ +	if (amdgpu_sriov_vf(psp->adev)) +		return 0; + +	cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); +	if (!cmd) +		return -ENOMEM; + +	psp_prep_dtm_ta_invoke_cmd_buf(cmd, ta_cmd_id, +				       psp->dtm_context.session_id); + +	ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); + +	kfree(cmd); + +	return ret; +} + +static int psp_dtm_terminate(struct psp_context *psp) +{ +	int ret; + +	/* +	 * TODO: bypass the terminate in sriov for now +	 */ +	if (amdgpu_sriov_vf(psp->adev)) +		return 0; + +	if (!psp->dtm_context.dtm_initialized) +		return 0; + +	ret = psp_hdcp_unload(psp); +	if (ret) +		return ret; + +	psp->dtm_context.dtm_initialized = 0; + +	/* free hdcp shared memory */ +	amdgpu_bo_free_kernel(&psp->dtm_context.dtm_shared_bo, +			      &psp->dtm_context.dtm_shared_mc_addr, +			      &psp->dtm_context.dtm_shared_buf); + +	return 0; +} +// DTM end +  static int psp_hw_start(struct psp_context *psp)  {  	struct amdgpu_device *adev = psp->adev; @@ -831,12 +1233,21 @@ static int psp_hw_start(struct psp_context *psp)  				"XGMI: Failed to initialize XGMI session\n");  	} -  	if (psp->adev->psp.ta_fw) {  		ret = psp_ras_initialize(psp);  		if (ret)  			dev_err(psp->adev->dev,  					"RAS: Failed to initialize RAS\n"); + +		ret = psp_hdcp_initialize(psp); +		if (ret) +			dev_err(psp->adev->dev, +				"HDCP: Failed to initialize HDCP\n"); + +		ret = psp_dtm_initialize(psp); +		if (ret) +			dev_err(psp->adev->dev, +				"DTM: Failed to initialize DTM\n");  	}  	return 0; @@ -852,6 +1263,24 @@ static int psp_get_fw_type(struct amdgpu_firmware_info *ucode,  	case AMDGPU_UCODE_ID_SDMA1:  		*type = GFX_FW_TYPE_SDMA1;  		break; +	case AMDGPU_UCODE_ID_SDMA2: +		*type = GFX_FW_TYPE_SDMA2; +		break; +	case AMDGPU_UCODE_ID_SDMA3: +		*type = GFX_FW_TYPE_SDMA3; +		break; +	case AMDGPU_UCODE_ID_SDMA4: +		*type = GFX_FW_TYPE_SDMA4; +		break; +	case AMDGPU_UCODE_ID_SDMA5: +		*type = GFX_FW_TYPE_SDMA5; +		break; +	case AMDGPU_UCODE_ID_SDMA6: +		*type = GFX_FW_TYPE_SDMA6; +		break; +	case AMDGPU_UCODE_ID_SDMA7: +		*type = GFX_FW_TYPE_SDMA7; +		break;  	case AMDGPU_UCODE_ID_CP_CE:  		*type = GFX_FW_TYPE_CP_CE;  		break; @@ -920,6 +1349,54 @@ static int psp_get_fw_type(struct amdgpu_firmware_info *ucode,  	return 0;  } +static void psp_print_fw_hdr(struct psp_context *psp, +			     struct amdgpu_firmware_info *ucode) +{ +	struct amdgpu_device *adev = psp->adev; +	struct common_firmware_header *hdr; + +	switch (ucode->ucode_id) { +	case AMDGPU_UCODE_ID_SDMA0: +	case AMDGPU_UCODE_ID_SDMA1: +	case AMDGPU_UCODE_ID_SDMA2: +	case AMDGPU_UCODE_ID_SDMA3: +	case AMDGPU_UCODE_ID_SDMA4: +	case AMDGPU_UCODE_ID_SDMA5: +	case AMDGPU_UCODE_ID_SDMA6: +	case AMDGPU_UCODE_ID_SDMA7: +		hdr = (struct common_firmware_header *) +			adev->sdma.instance[ucode->ucode_id - AMDGPU_UCODE_ID_SDMA0].fw->data; +		amdgpu_ucode_print_sdma_hdr(hdr); +		break; +	case AMDGPU_UCODE_ID_CP_CE: +		hdr = (struct common_firmware_header *)adev->gfx.ce_fw->data; +		amdgpu_ucode_print_gfx_hdr(hdr); +		break; +	case AMDGPU_UCODE_ID_CP_PFP: +		hdr = (struct common_firmware_header *)adev->gfx.pfp_fw->data; +		amdgpu_ucode_print_gfx_hdr(hdr); +		break; +	case AMDGPU_UCODE_ID_CP_ME: +		hdr = (struct common_firmware_header *)adev->gfx.me_fw->data; +		amdgpu_ucode_print_gfx_hdr(hdr); +		break; +	case AMDGPU_UCODE_ID_CP_MEC1: +		hdr = (struct common_firmware_header *)adev->gfx.mec_fw->data; +		amdgpu_ucode_print_gfx_hdr(hdr); +		break; +	case AMDGPU_UCODE_ID_RLC_G: +		hdr = (struct common_firmware_header *)adev->gfx.rlc_fw->data; +		amdgpu_ucode_print_rlc_hdr(hdr); +		break; +	case AMDGPU_UCODE_ID_SMC: +		hdr = (struct common_firmware_header *)adev->pm.fw->data; +		amdgpu_ucode_print_smc_hdr(hdr); +		break; +	default: +		break; +	} +} +  static int psp_prep_load_ip_fw_cmd_buf(struct amdgpu_firmware_info *ucode,  				       struct psp_gfx_cmd_resp *cmd)  { @@ -980,24 +1457,38 @@ out:  		if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC &&  		    (psp_smu_reload_quirk(psp) || psp->autoload_supported))  			continue; +  		if (amdgpu_sriov_vf(adev) &&  		   (ucode->ucode_id == AMDGPU_UCODE_ID_SDMA0  		    || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA1 -		    || ucode->ucode_id == AMDGPU_UCODE_ID_RLC_G)) +		    || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA2 +		    || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA3 +		    || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA4 +		    || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA5 +		    || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA6 +		    || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA7 +                    || ucode->ucode_id == AMDGPU_UCODE_ID_RLC_G +	            || ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL +	            || ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM +	            || ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM))  			/*skip ucode loading in SRIOV VF */  			continue; +  		if (psp->autoload_supported &&  		    (ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC1_JT ||  		     ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC2_JT))  			/* skip mec JT when autoload is enabled */  			continue; +		psp_print_fw_hdr(psp, ucode); +  		ret = psp_execute_np_fw_load(psp, ucode);  		if (ret)  			return ret;  		/* Start rlc autoload after psp recieved all the gfx firmware */ -		if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM) { +		if (psp->autoload_supported && ucode->ucode_id == (amdgpu_sriov_vf(adev) ? +		    AMDGPU_UCODE_ID_CP_MEC2 : AMDGPU_UCODE_ID_RLC_G)) {  			ret = psp_rlc_autoload(psp);  			if (ret) {  				DRM_ERROR("Failed to start rlc autoload\n"); @@ -1115,17 +1606,23 @@ static int psp_hw_fini(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	struct psp_context *psp = &adev->psp; +	void *tmr_buf; +	void **pptr;  	if (adev->gmc.xgmi.num_physical_nodes > 1 &&  	    psp->xgmi_context.initialized == 1)                  psp_xgmi_terminate(psp); -	if (psp->adev->psp.ta_fw) +	if (psp->adev->psp.ta_fw) {  		psp_ras_terminate(psp); +		psp_dtm_terminate(psp); +		psp_hdcp_terminate(psp); +	}  	psp_ring_destroy(psp, PSP_RING_TYPE__KM); -	amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf); +	pptr = amdgpu_sriov_vf(psp->adev) ? &tmr_buf : NULL; +	amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, pptr);  	amdgpu_bo_free_kernel(&psp->fw_pri_bo,  			      &psp->fw_pri_mc_addr, &psp->fw_pri_buf);  	amdgpu_bo_free_kernel(&psp->fence_buf_bo, @@ -1162,6 +1659,16 @@ static int psp_suspend(void *handle)  			DRM_ERROR("Failed to terminate ras ta\n");  			return ret;  		} +		ret = psp_hdcp_terminate(psp); +		if (ret) { +			DRM_ERROR("Failed to terminate hdcp ta\n"); +			return ret; +		} +		ret = psp_dtm_terminate(psp); +		if (ret) { +			DRM_ERROR("Failed to terminate dtm ta\n"); +			return ret; +		}  	}  	ret = psp_ring_stop(psp, PSP_RING_TYPE__KM); @@ -1181,6 +1688,12 @@ static int psp_resume(void *handle)  	DRM_INFO("PSP is resuming...\n"); +	ret = psp_mem_training(psp, PSP_MEM_TRAIN_RESUME); +	if (ret) { +		DRM_ERROR("Failed to process memory training!\n"); +		return ret; +	} +  	mutex_lock(&adev->firmware.mutex);  	ret = psp_hw_start(psp); @@ -1220,9 +1733,6 @@ int psp_rlc_autoload_start(struct psp_context *psp)  	int ret;  	struct psp_gfx_cmd_resp *cmd; -	if (amdgpu_sriov_vf(psp->adev)) -		return 0; -  	cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);  	if (!cmd)  		return -ENOMEM; @@ -1329,3 +1839,12 @@ const struct amdgpu_ip_block_version psp_v11_0_ip_block =  	.rev = 0,  	.funcs = &psp_ip_funcs,  }; + +const struct amdgpu_ip_block_version psp_v12_0_ip_block = +{ +	.type = AMD_IP_BLOCK_TYPE_PSP, +	.major = 12, +	.minor = 0, +	.rev = 0, +	.funcs = &psp_ip_funcs, +}; | 
