drm/amdgpu: enable RAP TA load
authorWenhui Sheng <Wenhui.Sheng@amd.com>
Fri, 17 Jul 2020 08:55:20 +0000 (16:55 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 14 Aug 2020 20:22:39 +0000 (16:22 -0400)
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>
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h

index c68369731b20aa083063865a623e5b3390c0cac1..116a89990f39e0cedf2e0c6f9577b79495fcc15b 100644 (file)
@@ -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;
index 623888bf30cb7b2097833204186c400a4970b0a5..919d2fb7427b151358e4aea2be1c33a5e41355c5 100644 (file)
@@ -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);
 
index 12a8bc8fca0b0a1f81051a7777c5aba234858098..3c23c6293ff9472b64e1a9553c73ce96776b3aca 100644 (file)
@@ -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 {