diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 189 | 
1 files changed, 114 insertions, 75 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index a09483beb968..6046123d0562 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -25,6 +25,7 @@  #include <linux/firmware.h>  #include <linux/dma-mapping.h> +#include <drm/drm_drv.h>  #include "amdgpu.h"  #include "amdgpu_psp.h" @@ -38,6 +39,9 @@  #include "amdgpu_ras.h"  #include "amdgpu_securedisplay.h" +#include "amdgpu_atomfirmware.h" + +#include <drm/drm_drv.h>  static int psp_sysfs_init(struct amdgpu_device *adev);  static void psp_sysfs_fini(struct amdgpu_device *adev); @@ -104,6 +108,7 @@ static int psp_early_init(void *handle)  	case CHIP_NAVY_FLOUNDER:  	case CHIP_VANGOGH:  	case CHIP_DIMGREY_CAVEFISH: +	case CHIP_BEIGE_GOBY:  		psp_v11_0_set_psp_funcs(psp);  		psp->autoload_supported = true;  		break; @@ -113,6 +118,10 @@ static int psp_early_init(void *handle)  	case CHIP_ALDEBARAN:  		psp_v13_0_set_psp_funcs(psp);  		break; +	case CHIP_YELLOW_CARP: +		psp_v13_0_set_psp_funcs(psp); +		psp->autoload_supported = true; +		break;  	default:  		return -EINVAL;  	} @@ -174,6 +183,12 @@ static int psp_sw_init(void *handle)  			DRM_ERROR("Failed to load psp firmware!\n");  			return ret;  		} +	} else if (amdgpu_sriov_vf(adev) && adev->asic_type == CHIP_ALDEBARAN) { +		ret = psp_init_ta_microcode(psp, "aldebaran"); +		if (ret) { +			DRM_ERROR("Failed to initialize ta microcode!\n"); +			return ret; +		}  	}  	ret = psp_memory_training_init(psp); @@ -229,7 +244,7 @@ int psp_wait_for(struct psp_context *psp, uint32_t reg_index,  	int i;  	struct amdgpu_device *adev = psp->adev; -	if (psp->adev->in_pci_err_recovery) +	if (psp->adev->no_hw_access)  		return 0;  	for (i = 0; i < adev->usec_timeout; i++) { @@ -253,12 +268,15 @@ psp_cmd_submit_buf(struct psp_context *psp,  		   struct psp_gfx_cmd_resp *cmd, uint64_t fence_mc_addr)  {  	int ret; -	int index; +	int index, idx;  	int timeout = 20000;  	bool ras_intr = false;  	bool skip_unsupport = false; -	if (psp->adev->in_pci_err_recovery) +	if (psp->adev->no_hw_access) +		return 0; + +	if (!drm_dev_enter(&psp->adev->ddev, &idx))  		return 0;  	mutex_lock(&psp->mutex); @@ -271,11 +289,10 @@ psp_cmd_submit_buf(struct psp_context *psp,  	ret = psp_ring_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; +		goto exit;  	} -	amdgpu_asic_invalidate_hdp(psp->adev, NULL); +	amdgpu_device_invalidate_hdp(psp->adev, NULL);  	while (*((unsigned int *)psp->fence_buf) != index) {  		if (--timeout == 0)  			break; @@ -288,7 +305,7 @@ psp_cmd_submit_buf(struct psp_context *psp,  		if (ras_intr)  			break;  		usleep_range(10, 100); -		amdgpu_asic_invalidate_hdp(psp->adev, NULL); +		amdgpu_device_invalidate_hdp(psp->adev, NULL);  	}  	/* We allow TEE_ERROR_NOT_SUPPORTED for VMR command and PSP_ERR_UNKNOWN_COMMAND in SRIOV */ @@ -312,8 +329,8 @@ psp_cmd_submit_buf(struct psp_context *psp,  			 psp->cmd_buf_mem->cmd_id,  			 psp->cmd_buf_mem->resp.status);  		if (!timeout) { -			mutex_unlock(&psp->mutex); -			return -EINVAL; +			ret = -EINVAL; +			goto exit;  		}  	} @@ -321,8 +338,10 @@ psp_cmd_submit_buf(struct psp_context *psp,  		ucode->tmr_mc_addr_lo = psp->cmd_buf_mem->resp.fw_addr_lo;  		ucode->tmr_mc_addr_hi = psp->cmd_buf_mem->resp.fw_addr_hi;  	} -	mutex_unlock(&psp->mutex); +exit: +	mutex_unlock(&psp->mutex); +	drm_dev_exit(idx);  	return ret;  } @@ -366,8 +385,7 @@ static int psp_load_toc(struct psp_context *psp,  	if (!cmd)  		return -ENOMEM;  	/* Copy toc to psp firmware private buffer */ -	memset(psp->fw_pri_buf, 0, PSP_1_MEG); -	memcpy(psp->fw_pri_buf, psp->toc_start_addr, psp->toc_bin_size); +	psp_copy_fw(psp, psp->toc_start_addr, psp->toc_bin_size);  	psp_prep_load_toc_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->toc_bin_size); @@ -417,31 +435,12 @@ static int psp_tmr_init(struct psp_context *psp)  	return ret;  } -static int psp_clear_vf_fw(struct psp_context *psp) -{ -	int ret; -	struct psp_gfx_cmd_resp *cmd; - -	if (!amdgpu_sriov_vf(psp->adev) || psp->adev->asic_type != CHIP_NAVI12) -		return 0; - -	cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); -	if (!cmd) -		return -ENOMEM; - -	cmd->cmd_id = GFX_CMD_ID_CLEAR_VF_FW; - -	ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); -	kfree(cmd); - -	return ret; -} -  static bool psp_skip_tmr(struct psp_context *psp)  {  	switch (psp->adev->asic_type) {  	case CHIP_NAVI12:  	case CHIP_SIENNA_CICHLID: +	case CHIP_ALDEBARAN:  		return true;  	default:  		return false; @@ -557,7 +556,7 @@ static int psp_boot_config_set(struct amdgpu_device *adev)  	struct psp_context *psp = &adev->psp;  	struct psp_gfx_cmd_resp *cmd = psp->cmd; -	if (adev->asic_type != CHIP_SIENNA_CICHLID || amdgpu_sriov_vf(adev)) +	if (amdgpu_sriov_vf(adev))  		return 0;  	memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); @@ -621,8 +620,7 @@ static int psp_asd_load(struct psp_context *psp)  	if (!cmd)  		return -ENOMEM; -	memset(psp->fw_pri_buf, 0, PSP_1_MEG); -	memcpy(psp->fw_pri_buf, psp->asd_start_addr, psp->asd_ucode_size); +	psp_copy_fw(psp, psp->asd_start_addr, psp->asd_ucode_size);  	psp_prep_asd_load_cmd_buf(cmd, psp->fw_pri_mc_addr,  				  psp->asd_ucode_size); @@ -696,6 +694,8 @@ int psp_reg_program(struct psp_context *psp, enum psp_reg_prog_id reg,  	psp_prep_reg_prog_cmd_buf(cmd, reg, value);  	ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); +	if (ret) +		DRM_ERROR("PSP failed to program reg id %d", reg);  	kfree(cmd);  	return ret; @@ -777,8 +777,7 @@ static int psp_xgmi_load(struct psp_context *psp)  	if (!cmd)  		return -ENOMEM; -	memset(psp->fw_pri_buf, 0, PSP_1_MEG); -	memcpy(psp->fw_pri_buf, psp->ta_xgmi_start_addr, psp->ta_xgmi_ucode_size); +	psp_copy_fw(psp, psp->ta_xgmi_start_addr, psp->ta_xgmi_ucode_size);  	psp_prep_ta_load_cmd_buf(cmd,  				 psp->fw_pri_mc_addr, @@ -1034,8 +1033,14 @@ static int psp_ras_load(struct psp_context *psp)  	if (!cmd)  		return -ENOMEM; -	memset(psp->fw_pri_buf, 0, PSP_1_MEG); -	memcpy(psp->fw_pri_buf, psp->ta_ras_start_addr, psp->ta_ras_ucode_size); +	psp_copy_fw(psp, psp->ta_ras_start_addr, psp->ta_ras_ucode_size); + +	ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf; + +	if (psp->adev->gmc.xgmi.connected_to_cpu) +		ras_cmd->ras_in_message.init_flags.poison_mode_en = 1; +	else +		ras_cmd->ras_in_message.init_flags.dgpu_mode = 1;  	psp_prep_ta_load_cmd_buf(cmd,  				 psp->fw_pri_mc_addr, @@ -1046,8 +1051,6 @@ static int psp_ras_load(struct psp_context *psp)  	ret = psp_cmd_submit_buf(psp, NULL, cmd,  			psp->fence_buf_mc_addr); -	ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf; -  	if (!ret) {  		psp->ras.session_id = cmd->resp.session_id; @@ -1128,6 +1131,31 @@ int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id)  	return ret;  } +static int psp_ras_status_to_errno(struct amdgpu_device *adev, +					 enum ta_ras_status ras_status) +{ +	int ret = -EINVAL; + +	switch (ras_status) { +	case TA_RAS_STATUS__SUCCESS: +		ret = 0; +		break; +	case TA_RAS_STATUS__RESET_NEEDED: +		ret = -EAGAIN; +		break; +	case TA_RAS_STATUS__ERROR_RAS_NOT_AVAILABLE: +		dev_warn(adev->dev, "RAS WARN: ras function unavailable\n"); +		break; +	case TA_RAS_STATUS__ERROR_ASD_READ_WRITE: +		dev_warn(adev->dev, "RAS WARN: asd read or write failed\n"); +		break; +	default: +		dev_err(adev->dev, "RAS ERROR: ras function failed ret 0x%X\n", ret); +	} + +	return ret; +} +  int psp_ras_enable_features(struct psp_context *psp,  		union ta_ras_cmd_input *info, bool enable)  { @@ -1151,7 +1179,7 @@ int psp_ras_enable_features(struct psp_context *psp,  	if (ret)  		return -EINVAL; -	return ras_cmd->ras_status; +	return psp_ras_status_to_errno(psp->adev, ras_cmd->ras_status);  }  static int psp_ras_terminate(struct psp_context *psp) @@ -1234,7 +1262,7 @@ int psp_ras_trigger_error(struct psp_context *psp,  	if (amdgpu_ras_intr_triggered())  		return 0; -	return ras_cmd->ras_status; +	return psp_ras_status_to_errno(psp->adev, ras_cmd->ras_status);  }  // ras end @@ -1271,9 +1299,8 @@ static int psp_hdcp_load(struct psp_context *psp)  	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_copy_fw(psp, psp->ta_hdcp_start_addr, +		    psp->ta_hdcp_ucode_size);  	psp_prep_ta_load_cmd_buf(cmd,  				 psp->fw_pri_mc_addr, @@ -1423,8 +1450,7 @@ static int psp_dtm_load(struct psp_context *psp)  	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_copy_fw(psp, psp->ta_dtm_start_addr, psp->ta_dtm_ucode_size);  	psp_prep_ta_load_cmd_buf(cmd,  				 psp->fw_pri_mc_addr, @@ -1569,8 +1595,7 @@ static int psp_rap_load(struct psp_context *psp)  	if (!cmd)  		return -ENOMEM; -	memset(psp->fw_pri_buf, 0, PSP_1_MEG); -	memcpy(psp->fw_pri_buf, psp->ta_rap_start_addr, psp->ta_rap_ucode_size); +	psp_copy_fw(psp, psp->ta_rap_start_addr, psp->ta_rap_ucode_size);  	psp_prep_ta_load_cmd_buf(cmd,  				 psp->fw_pri_mc_addr, @@ -1920,15 +1945,10 @@ static int psp_hw_start(struct psp_context *psp)  		return ret;  	} -	ret = psp_clear_vf_fw(psp); -	if (ret) { -		DRM_ERROR("PSP clear vf fw!\n"); -		return ret; -	} - -	ret = psp_boot_config_set(adev); -	if (ret) { -		DRM_WARN("PSP set boot config@\n"); +	if (amdgpu_atomfirmware_dynamic_boot_config_supported(adev)) { +		ret = psp_boot_config_set(adev); +		if (ret) +			dev_warn(adev->dev, "PSP set boot config failed\n");  	}  	ret = psp_tmr_init(psp); @@ -2166,7 +2186,7 @@ static int psp_load_smu_fw(struct psp_context *psp)  		return 0;  	if ((amdgpu_in_reset(adev) && -	     ras && ras->supported && +	     ras && adev->ras_enabled &&  	     (adev->asic_type == CHIP_ARCTURUS ||  	      adev->asic_type == CHIP_VEGA20)) ||  	     (adev->in_runpm && @@ -2311,11 +2331,20 @@ static int psp_load_fw(struct amdgpu_device *adev)  	if (!psp->cmd)  		return -ENOMEM; -	ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG, -					AMDGPU_GEM_DOMAIN_GTT, -					&psp->fw_pri_bo, -					&psp->fw_pri_mc_addr, -					&psp->fw_pri_buf); +	if (amdgpu_sriov_vf(adev)) { +		ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG, +						AMDGPU_GEM_DOMAIN_VRAM, +						&psp->fw_pri_bo, +						&psp->fw_pri_mc_addr, +						&psp->fw_pri_buf); +	} else { +		ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG, +						AMDGPU_GEM_DOMAIN_GTT, +						&psp->fw_pri_bo, +						&psp->fw_pri_mc_addr, +						&psp->fw_pri_buf); +	} +  	if (ret)  		goto failed; @@ -2434,7 +2463,6 @@ static int psp_hw_fini(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	struct psp_context *psp = &adev->psp; -	int ret;  	if (psp->adev->psp.ta_fw) {  		psp_ras_terminate(psp); @@ -2445,11 +2473,6 @@ static int psp_hw_fini(void *handle)  	}  	psp_asd_unload(psp); -	ret = psp_clear_vf_fw(psp); -	if (ret) { -		DRM_ERROR("PSP clear vf fw!\n"); -		return ret; -	}  	psp_tmr_terminate(psp);  	psp_ring_destroy(psp, PSP_RING_TYPE__KM); @@ -2694,7 +2717,7 @@ int psp_ring_cmd_submit(struct psp_context *psp,  	write_frame->fence_addr_hi = upper_32_bits(fence_mc_addr);  	write_frame->fence_addr_lo = lower_32_bits(fence_mc_addr);  	write_frame->fence_value = index; -	amdgpu_asic_flush_hdp(adev, NULL); +	amdgpu_device_flush_hdp(adev, NULL);  	/* Update the write Pointer in DWORDs */  	psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw; @@ -3018,7 +3041,7 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,  	struct amdgpu_device *adev = drm_to_adev(ddev);  	void *cpu_addr;  	dma_addr_t dma_addr; -	int ret; +	int ret, idx;  	char fw_name[100];  	const struct firmware *usbc_pd_fw; @@ -3027,6 +3050,9 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,  		return -EBUSY;  	} +	if (!drm_dev_enter(ddev, &idx)) +		return -ENODEV; +  	snprintf(fw_name, sizeof(fw_name), "amdgpu/%s", buf);  	ret = request_firmware(&usbc_pd_fw, fw_name, adev->dev);  	if (ret) @@ -3058,16 +3084,29 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,  rel_buf:  	dma_free_coherent(adev->dev, usbc_pd_fw->size, cpu_addr, dma_addr);  	release_firmware(usbc_pd_fw); -  fail:  	if (ret) {  		DRM_ERROR("Failed to load USBC PD FW, err = %d", ret); -		return ret; +		count = ret;  	} +	drm_dev_exit(idx);  	return count;  } +void psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size) +{ +	int idx; + +	if (!drm_dev_enter(&psp->adev->ddev, &idx)) +		return; + +	memset(psp->fw_pri_buf, 0, PSP_1_MEG); +	memcpy(psp->fw_pri_buf, start_addr, bin_size); + +	drm_dev_exit(idx); +} +  static DEVICE_ATTR(usbc_pd_fw, S_IRUGO | S_IWUSR,  		   psp_usbc_pd_fw_sysfs_read,  		   psp_usbc_pd_fw_sysfs_write); |