Commit 8602692b authored by Wenhui Sheng's avatar Wenhui Sheng Committed by Alex Deucher
Browse files

drm/amdgpu: enable RAP TA load



Enable the RAP TA loading path and add RAP test
trigger interface.

v2: fix potential mem leak issue

Signed-off-by: default avatarWenhui Sheng <Wenhui.Sheng@amd.com>
Reviewed-by: default avatarGuchun Chen <Guchun.Chen@amd.com>
Reviewed-by: default avatarHawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent a189d0ae
Loading
Loading
Loading
Loading
+183 −0
Original line number Diff line number Diff line
@@ -1430,6 +1430,168 @@ static int psp_dtm_terminate(struct psp_context *psp)
}
// DTM end

// RAP start
static int psp_rap_init_shared_buf(struct psp_context *psp)
{
	int ret;

	/*
	 * Allocate 16k memory aligned to 4k from Frame Buffer (local
	 * physical) for rap ta <-> Driver
	 */
	ret = amdgpu_bo_create_kernel(psp->adev, PSP_RAP_SHARED_MEM_SIZE,
				      PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
				      &psp->rap_context.rap_shared_bo,
				      &psp->rap_context.rap_shared_mc_addr,
				      &psp->rap_context.rap_shared_buf);

	return ret;
}

static int psp_rap_load(struct psp_context *psp)
{
	int ret;
	struct psp_gfx_cmd_resp *cmd;

	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_rap_start_addr, psp->ta_rap_ucode_size);

	psp_prep_ta_load_cmd_buf(cmd,
				 psp->fw_pri_mc_addr,
				 psp->ta_rap_ucode_size,
				 psp->rap_context.rap_shared_mc_addr,
				 PSP_RAP_SHARED_MEM_SIZE);

	ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);

	if (!ret) {
		psp->rap_context.rap_initialized = true;
		psp->rap_context.session_id = cmd->resp.session_id;
		mutex_init(&psp->rap_context.mutex);
	}

	kfree(cmd);

	return ret;
}

static int psp_rap_unload(struct psp_context *psp)
{
	int ret;
	struct psp_gfx_cmd_resp *cmd;

	cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
	if (!cmd)
		return -ENOMEM;

	psp_prep_ta_unload_cmd_buf(cmd, psp->rap_context.session_id);

	ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);

	kfree(cmd);

	return ret;
}

static int psp_rap_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_rap_ucode_size ||
	    !psp->adev->psp.ta_rap_start_addr) {
		dev_info(psp->adev->dev, "RAP: optional rap ta ucode is not available\n");
		return 0;
	}

	if (!psp->rap_context.rap_initialized) {
		ret = psp_rap_init_shared_buf(psp);
		if (ret)
			return ret;
	}

	ret = psp_rap_load(psp);
	if (ret)
		return ret;

	ret = psp_rap_invoke(psp, TA_CMD_RAP__INITIALIZE);
	if (ret != TA_RAP_STATUS__SUCCESS) {
		psp_rap_unload(psp);

		amdgpu_bo_free_kernel(&psp->rap_context.rap_shared_bo,
			      &psp->rap_context.rap_shared_mc_addr,
			      &psp->rap_context.rap_shared_buf);

		psp->rap_context.rap_initialized = false;

		dev_warn(psp->adev->dev, "RAP TA initialize fail.\n");
		return -EINVAL;
	}

	return 0;
}

static int psp_rap_terminate(struct psp_context *psp)
{
	int ret;

	if (!psp->rap_context.rap_initialized)
		return 0;

	ret = psp_rap_unload(psp);

	psp->rap_context.rap_initialized = false;

	/* free rap shared memory */
	amdgpu_bo_free_kernel(&psp->rap_context.rap_shared_bo,
			      &psp->rap_context.rap_shared_mc_addr,
			      &psp->rap_context.rap_shared_buf);

	return ret;
}

int psp_rap_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
{
	struct ta_rap_shared_memory *rap_cmd;
	int ret;

	if (!psp->rap_context.rap_initialized)
		return -EINVAL;

	if (ta_cmd_id != TA_CMD_RAP__INITIALIZE &&
	    ta_cmd_id != TA_CMD_RAP__VALIDATE_L0)
		return -EINVAL;

	mutex_lock(&psp->rap_context.mutex);

	rap_cmd = (struct ta_rap_shared_memory *)
		  psp->rap_context.rap_shared_buf;
	memset(rap_cmd, 0, sizeof(struct ta_rap_shared_memory));

	rap_cmd->cmd_id = ta_cmd_id;
	rap_cmd->validation_method_id = METHOD_A;

	ret = psp_ta_invoke(psp, rap_cmd->cmd_id, psp->rap_context.session_id);
	if (ret) {
		mutex_unlock(&psp->rap_context.mutex);
		return ret;
	}

	mutex_unlock(&psp->rap_context.mutex);

	return rap_cmd->rap_status;
}
// RAP end

static int psp_hw_start(struct psp_context *psp)
{
	struct amdgpu_device *adev = psp->adev;
@@ -1892,6 +2054,11 @@ static int psp_load_fw(struct amdgpu_device *adev)
		if (ret)
			dev_err(psp->adev->dev,
				"DTM: Failed to initialize DTM\n");

		ret = psp_rap_initialize(psp);
		if (ret)
			dev_err(psp->adev->dev,
				"RAP: Failed to initialize RAP\n");
	}

	return 0;
@@ -1942,6 +2109,7 @@ static int psp_hw_fini(void *handle)

	if (psp->adev->psp.ta_fw) {
		psp_ras_terminate(psp);
		psp_rap_terminate(psp);
		psp_dtm_terminate(psp);
		psp_hdcp_terminate(psp);
	}
@@ -2000,6 +2168,11 @@ static int psp_suspend(void *handle)
			DRM_ERROR("Failed to terminate dtm ta\n");
			return ret;
		}
		ret = psp_rap_terminate(psp);
		if (ret) {
			DRM_ERROR("Failed to terminate rap ta\n");
			return ret;
		}
	}

	ret = psp_asd_unload(psp);
@@ -2078,6 +2251,11 @@ static int psp_resume(void *handle)
		if (ret)
			dev_err(psp->adev->dev,
				"DTM: Failed to initialize DTM\n");

		ret = psp_rap_initialize(psp);
		if (ret)
			dev_err(psp->adev->dev,
				"RAP: Failed to initialize RAP\n");
	}

	mutex_unlock(&adev->firmware.mutex);
@@ -2343,6 +2521,11 @@ int parse_ta_bin_descriptor(struct psp_context *psp,
		psp->ta_dtm_ucode_size     = le32_to_cpu(desc->size_bytes);
		psp->ta_dtm_start_addr     = ucode_start_addr;
		break;
	case TA_FW_TYPE_PSP_RAP:
		psp->ta_rap_ucode_version  = le32_to_cpu(desc->fw_version);
		psp->ta_rap_ucode_size     = le32_to_cpu(desc->size_bytes);
		psp->ta_rap_start_addr     = ucode_start_addr;
		break;
	default:
		dev_warn(psp->adev->dev, "Unsupported TA type: %d\n", desc->fw_type);
		break;
+17 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include "psp_gfx_if.h"
#include "ta_xgmi_if.h"
#include "ta_ras_if.h"
#include "ta_rap_if.h"

#define PSP_FENCE_BUFFER_SIZE	0x1000
#define PSP_CMD_BUFFER_SIZE	0x1000
@@ -38,6 +39,7 @@
#define PSP_TMR_SIZE	0x400000
#define PSP_HDCP_SHARED_MEM_SIZE	0x4000
#define PSP_DTM_SHARED_MEM_SIZE	0x4000
#define PSP_RAP_SHARED_MEM_SIZE	0x4000
#define PSP_SHARED_MEM_SIZE		0x4000

struct psp_context;
@@ -159,6 +161,15 @@ struct psp_dtm_context {
	struct mutex		mutex;
};

struct psp_rap_context {
	bool			rap_initialized;
	uint32_t		session_id;
	struct amdgpu_bo	*rap_shared_bo;
	uint64_t		rap_shared_mc_addr;
	void			*rap_shared_buf;
	struct mutex		mutex;
};

#define MEM_TRAIN_SYSTEM_SIGNATURE		0x54534942
#define GDDR6_MEM_TRAINING_DATA_SIZE_IN_BYTES	0x1000
#define GDDR6_MEM_TRAINING_OFFSET		0x8000
@@ -277,11 +288,16 @@ struct psp_context
	uint32_t			ta_dtm_ucode_size;
	uint8_t				*ta_dtm_start_addr;

	uint32_t			ta_rap_ucode_version;
	uint32_t			ta_rap_ucode_size;
	uint8_t				*ta_rap_start_addr;

	struct psp_asd_context		asd_context;
	struct psp_xgmi_context		xgmi_context;
	struct psp_ras_context		ras;
	struct psp_hdcp_context 	hdcp_context;
	struct psp_dtm_context		dtm_context;
	struct psp_rap_context		rap_context;
	struct mutex			mutex;
	struct psp_memory_training_context mem_train_ctx;
};
@@ -357,6 +373,7 @@ int psp_ras_trigger_error(struct psp_context *psp,

int psp_hdcp_invoke(struct psp_context *psp, uint32_t ta_cmd_id);
int psp_dtm_invoke(struct psp_context *psp, uint32_t ta_cmd_id);
int psp_rap_invoke(struct psp_context *psp, uint32_t ta_cmd_id);

int psp_rlc_autoload_start(struct psp_context *psp);

+1 −0
Original line number Diff line number Diff line
@@ -131,6 +131,7 @@ enum ta_fw_type {
	TA_FW_TYPE_PSP_RAS,
	TA_FW_TYPE_PSP_HDCP,
	TA_FW_TYPE_PSP_DTM,
	TA_FW_TYPE_PSP_RAP,
};

struct ta_fw_bin_desc {