summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorWenhui Sheng <Wenhui.Sheng@amd.com>2020-07-17 16:55:20 +0800
committerAlex Deucher <alexander.deucher@amd.com>2020-08-14 16:22:39 -0400
commit8602692b6f73d2ea0312cccea5416b270d0f7247 (patch)
tree13dfdd533c09ed2c63b3f13a7de662b4e4187ea6 /drivers
parenta189d0ae0cd68643204cbe9b11e824414b2b06c9 (diff)
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: Wenhui Sheng <Wenhui.Sheng@amd.com> Reviewed-by: Guchun Chen <Guchun.Chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c183
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h1
3 files changed, 201 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index c68369731b20..116a89990f39 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -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 @@ skip_memalloc:
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;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
index 623888bf30cb..919d2fb7427b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
@@ -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);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index 12a8bc8fca0b..3c23c6293ff9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -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 {