Commit 896b7add authored by Candice Li's avatar Candice Li Committed by Alex Deucher

drm/amdgpu: Optimize TA load/unload/invoke debugfs interfaces

1. Add a function pointer structure ta_funcs to psp context
2. Make the interfaces generic to all TAs
3. Leverage exisitng TA context and remove unused functions
4. Fix return code bugs

v2: Add comments for ta funcs macros and correct typo
Reviewed-by: default avatarHawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: default avatarCandice Li <candice.li@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent bf7d7772
...@@ -1071,42 +1071,6 @@ int psp_ta_init_shared_buf(struct psp_context *psp, ...@@ -1071,42 +1071,6 @@ int psp_ta_init_shared_buf(struct psp_context *psp,
&mem_ctx->shared_buf); &mem_ctx->shared_buf);
} }
static void psp_prep_ta_invoke_indirect_cmd_buf(struct psp_gfx_cmd_resp *cmd,
uint32_t ta_cmd_id,
struct ta_context *context)
{
cmd->cmd_id = GFX_CMD_ID_INVOKE_CMD;
cmd->cmd.cmd_invoke_cmd.session_id = context->session_id;
cmd->cmd.cmd_invoke_cmd.ta_cmd_id = ta_cmd_id;
cmd->cmd.cmd_invoke_cmd.buf.num_desc = 1;
cmd->cmd.cmd_invoke_cmd.buf.total_size = context->mem_context.shared_mem_size;
cmd->cmd.cmd_invoke_cmd.buf.buf_desc[0].buf_size = context->mem_context.shared_mem_size;
cmd->cmd.cmd_invoke_cmd.buf.buf_desc[0].buf_phy_addr_lo =
lower_32_bits(context->mem_context.shared_mc_addr);
cmd->cmd.cmd_invoke_cmd.buf.buf_desc[0].buf_phy_addr_hi =
upper_32_bits(context->mem_context.shared_mc_addr);
}
int psp_ta_invoke_indirect(struct psp_context *psp,
uint32_t ta_cmd_id,
struct ta_context *context)
{
int ret;
struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_invoke_indirect_cmd_buf(cmd, ta_cmd_id, context);
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
context->resp_status = cmd->resp.status;
release_psp_cmd_buf(psp);
return ret;
}
static void psp_prep_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd, static void psp_prep_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd,
uint32_t ta_cmd_id, uint32_t ta_cmd_id,
uint32_t session_id) uint32_t session_id)
...@@ -1549,7 +1513,7 @@ int psp_ras_terminate(struct psp_context *psp) ...@@ -1549,7 +1513,7 @@ int psp_ras_terminate(struct psp_context *psp)
return ret; return ret;
} }
static int psp_ras_initialize(struct psp_context *psp) int psp_ras_initialize(struct psp_context *psp)
{ {
int ret; int ret;
uint32_t boot_cfg = 0xFF; uint32_t boot_cfg = 0xFF;
......
...@@ -136,6 +136,12 @@ struct psp_funcs ...@@ -136,6 +136,12 @@ struct psp_funcs
int (*vbflash_stat)(struct psp_context *psp); int (*vbflash_stat)(struct psp_context *psp);
}; };
struct ta_funcs {
int (*fn_ta_initialize)(struct psp_context *psp);
int (*fn_ta_invoke)(struct psp_context *psp, uint32_t ta_cmd_id);
int (*fn_ta_terminate)(struct psp_context *psp);
};
#define AMDGPU_XGMI_MAX_CONNECTED_NODES 64 #define AMDGPU_XGMI_MAX_CONNECTED_NODES 64
struct psp_xgmi_node_info { struct psp_xgmi_node_info {
uint64_t node_id; uint64_t node_id;
...@@ -309,6 +315,7 @@ struct psp_context ...@@ -309,6 +315,7 @@ struct psp_context
struct psp_gfx_cmd_resp *cmd; struct psp_gfx_cmd_resp *cmd;
const struct psp_funcs *funcs; const struct psp_funcs *funcs;
const struct ta_funcs *ta_funcs;
/* firmware buffer */ /* firmware buffer */
struct amdgpu_bo *fw_pri_bo; struct amdgpu_bo *fw_pri_bo;
...@@ -463,9 +470,6 @@ int psp_ta_load(struct psp_context *psp, struct ta_context *context); ...@@ -463,9 +470,6 @@ int psp_ta_load(struct psp_context *psp, struct ta_context *context);
int psp_ta_invoke(struct psp_context *psp, int psp_ta_invoke(struct psp_context *psp,
uint32_t ta_cmd_id, uint32_t ta_cmd_id,
struct ta_context *context); struct ta_context *context);
int psp_ta_invoke_indirect(struct psp_context *psp,
uint32_t ta_cmd_id,
struct ta_context *context);
int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool load_ta); int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool load_ta);
int psp_xgmi_terminate(struct psp_context *psp); int psp_xgmi_terminate(struct psp_context *psp);
...@@ -479,7 +483,7 @@ int psp_xgmi_get_topology_info(struct psp_context *psp, ...@@ -479,7 +483,7 @@ int psp_xgmi_get_topology_info(struct psp_context *psp,
int psp_xgmi_set_topology_info(struct psp_context *psp, int psp_xgmi_set_topology_info(struct psp_context *psp,
int number_devices, int number_devices,
struct psp_xgmi_topology_info *topology); struct psp_xgmi_topology_info *topology);
int psp_ras_initialize(struct psp_context *psp);
int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id); int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id);
int psp_ras_enable_features(struct psp_context *psp, int psp_ras_enable_features(struct psp_context *psp,
union ta_ras_cmd_input *info, bool enable); union ta_ras_cmd_input *info, bool enable);
......
...@@ -41,30 +41,46 @@ static uint32_t get_bin_version(const uint8_t *bin) ...@@ -41,30 +41,46 @@ static uint32_t get_bin_version(const uint8_t *bin)
return hdr->ucode_version; return hdr->ucode_version;
} }
static void prep_ta_mem_context(struct psp_context *psp, static int prep_ta_mem_context(struct ta_mem_context *mem_context,
struct ta_context *context,
uint8_t *shared_buf, uint8_t *shared_buf,
uint32_t shared_buf_len) uint32_t shared_buf_len)
{ {
context->mem_context.shared_mem_size = PAGE_ALIGN(shared_buf_len); if (mem_context->shared_mem_size < shared_buf_len)
psp_ta_init_shared_buf(psp, &context->mem_context); return -EINVAL;
memset(mem_context->shared_buf, 0, mem_context->shared_mem_size);
memcpy((void *)mem_context->shared_buf, shared_buf, shared_buf_len);
memcpy((void *)context->mem_context.shared_buf, shared_buf, shared_buf_len); return 0;
} }
static bool is_ta_type_valid(enum ta_type_id ta_type) static bool is_ta_type_valid(enum ta_type_id ta_type)
{ {
bool ret = false; switch (ta_type) {
case TA_TYPE_RAS:
return true;
default:
return false;
}
}
static const struct ta_funcs ras_ta_funcs = {
.fn_ta_initialize = psp_ras_initialize,
.fn_ta_invoke = psp_ras_invoke,
.fn_ta_terminate = psp_ras_terminate
};
static void set_ta_context_funcs(struct psp_context *psp,
enum ta_type_id ta_type,
struct ta_context **pcontext)
{
switch (ta_type) { switch (ta_type) {
case TA_TYPE_RAS: case TA_TYPE_RAS:
ret = true; *pcontext = &psp->ras_context.context;
psp->ta_funcs = &ras_ta_funcs;
break; break;
default: default:
break; break;
} }
return ret;
} }
static const struct file_operations ta_load_debugfs_fops = { static const struct file_operations ta_load_debugfs_fops = {
...@@ -85,8 +101,7 @@ static const struct file_operations ta_invoke_debugfs_fops = { ...@@ -85,8 +101,7 @@ static const struct file_operations ta_invoke_debugfs_fops = {
.owner = THIS_MODULE .owner = THIS_MODULE
}; };
/*
/**
* DOC: AMDGPU TA debugfs interfaces * DOC: AMDGPU TA debugfs interfaces
* *
* Three debugfs interfaces can be opened by a program to * Three debugfs interfaces can be opened by a program to
...@@ -111,15 +126,18 @@ static const struct file_operations ta_invoke_debugfs_fops = { ...@@ -111,15 +126,18 @@ static const struct file_operations ta_invoke_debugfs_fops = {
* *
* - For TA invoke debugfs interface: * - For TA invoke debugfs interface:
* Transmit buffer: * Transmit buffer:
* - TA type (4bytes)
* - TA ID (4bytes) * - TA ID (4bytes)
* - TA CMD ID (4bytes) * - TA CMD ID (4bytes)
* - TA shard buf length (4bytes) * - TA shard buf length
* (4bytes, value not beyond TA shared memory size)
* - TA shared buf * - TA shared buf
* Receive buffer: * Receive buffer:
* - TA shared buf * - TA shared buf
* *
* - For TA unload debugfs interface: * - For TA unload debugfs interface:
* Transmit buffer: * Transmit buffer:
* - TA type (4bytes)
* - TA ID (4bytes) * - TA ID (4bytes)
*/ */
...@@ -133,57 +151,90 @@ static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, size_t ...@@ -133,57 +151,90 @@ static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, size_t
struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private;
struct psp_context *psp = &adev->psp; struct psp_context *psp = &adev->psp;
struct ta_context context = {0}; struct ta_context *context = NULL;
if (!buf) if (!buf)
return -EINVAL; return -EINVAL;
ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t)); ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t));
if (ret || (!is_ta_type_valid(ta_type))) if (ret || (!is_ta_type_valid(ta_type)))
return -EINVAL; return -EFAULT;
copy_pos += sizeof(uint32_t); copy_pos += sizeof(uint32_t);
ret = copy_from_user((void *)&ta_bin_len, &buf[copy_pos], sizeof(uint32_t)); ret = copy_from_user((void *)&ta_bin_len, &buf[copy_pos], sizeof(uint32_t));
if (ret) if (ret)
return -EINVAL; return -EFAULT;
copy_pos += sizeof(uint32_t); copy_pos += sizeof(uint32_t);
ta_bin = kzalloc(ta_bin_len, GFP_KERNEL); ta_bin = kzalloc(ta_bin_len, GFP_KERNEL);
if (!ta_bin) if (!ta_bin)
ret = -ENOMEM; return -ENOMEM;
if (copy_from_user((void *)ta_bin, &buf[copy_pos], ta_bin_len)) { if (copy_from_user((void *)ta_bin, &buf[copy_pos], ta_bin_len)) {
ret = -EFAULT; ret = -EFAULT;
goto err_free_bin; goto err_free_bin;
} }
ret = psp_ras_terminate(psp); /* Set TA context and functions */
set_ta_context_funcs(psp, ta_type, &context);
if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_terminate) {
dev_err(adev->dev, "Unsupported function to terminate TA\n");
ret = -EOPNOTSUPP;
goto err_free_bin;
}
/*
* Allocate TA shared buf in case shared buf was freed
* due to loading TA failed before.
*/
if (!context->mem_context.shared_buf) {
ret = psp_ta_init_shared_buf(psp, &context->mem_context);
if (ret) { if (ret) {
dev_err(adev->dev, "Failed to unload embedded RAS TA\n"); ret = -ENOMEM;
goto err_free_bin; goto err_free_bin;
} }
}
ret = psp_fn_ta_terminate(psp);
if (ret || context->resp_status) {
dev_err(adev->dev,
"Failed to unload embedded TA (%d) and status (0x%X)\n",
ret, context->resp_status);
if (!ret)
ret = -EINVAL;
goto err_free_ta_shared_buf;
}
context.ta_type = ta_type; /* Prepare TA context for TA initialization */
context.ta_load_type = GFX_CMD_ID_LOAD_TA; context->ta_type = ta_type;
context.bin_desc.fw_version = get_bin_version(ta_bin); context->bin_desc.fw_version = get_bin_version(ta_bin);
context.bin_desc.size_bytes = ta_bin_len; context->bin_desc.size_bytes = ta_bin_len;
context.bin_desc.start_addr = ta_bin; context->bin_desc.start_addr = ta_bin;
ret = psp_ta_load(psp, &context); if (!psp->ta_funcs->fn_ta_initialize) {
dev_err(adev->dev, "Unsupported function to initialize TA\n");
ret = -EOPNOTSUPP;
goto err_free_ta_shared_buf;
}
if (ret || context.resp_status) { ret = psp_fn_ta_initialize(psp);
dev_err(adev->dev, "TA load via debugfs failed (%d) status %d\n", if (ret || context->resp_status) {
ret, context.resp_status); dev_err(adev->dev, "Failed to load TA via debugfs (%d) and status (0x%X)\n",
ret, context->resp_status);
if (!ret) if (!ret)
ret = -EINVAL; ret = -EINVAL;
goto err_free_bin; goto err_free_ta_shared_buf;
} }
context.initialized = true; if (copy_to_user((char *)buf, (void *)&context->session_id, sizeof(uint32_t)))
if (copy_to_user((char *)buf, (void *)&context.session_id, sizeof(uint32_t)))
ret = -EFAULT; ret = -EFAULT;
err_free_ta_shared_buf:
/* Only free TA shared buf when returns error code */
if (ret && context->mem_context.shared_buf)
psp_ta_free_shared_buf(&context->mem_context);
err_free_bin: err_free_bin:
kfree(ta_bin); kfree(ta_bin);
...@@ -192,31 +243,53 @@ static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, size_t ...@@ -192,31 +243,53 @@ static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, size_t
static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off) static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
{ {
uint32_t ta_type = 0;
uint32_t ta_id = 0; uint32_t ta_id = 0;
uint32_t copy_pos = 0;
int ret = 0; int ret = 0;
struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private;
struct psp_context *psp = &adev->psp; struct psp_context *psp = &adev->psp;
struct ta_context context = {0}; struct ta_context *context = NULL;
if (!buf) if (!buf)
return -EINVAL; return -EINVAL;
ret = copy_from_user((void *)&ta_id, buf, sizeof(uint32_t)); ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t));
if (ret || (!is_ta_type_valid(ta_type)))
return -EFAULT;
copy_pos += sizeof(uint32_t);
ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t));
if (ret) if (ret)
return -EINVAL; return -EFAULT;
set_ta_context_funcs(psp, ta_type, &context);
context->session_id = ta_id;
context.session_id = ta_id; if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_terminate) {
dev_err(adev->dev, "Unsupported function to terminate TA\n");
return -EOPNOTSUPP;
}
ret = psp_ta_unload(psp, &context); ret = psp_fn_ta_terminate(psp);
if (ret || context->resp_status) {
dev_err(adev->dev, "Failed to unload TA via debugfs (%d) and status (0x%X)\n",
ret, context->resp_status);
if (!ret) if (!ret)
context.initialized = false; ret = -EINVAL;
}
if (context->mem_context.shared_buf)
psp_ta_free_shared_buf(&context->mem_context);
return ret; return ret;
} }
static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off) static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
{ {
uint32_t ta_type = 0;
uint32_t ta_id = 0; uint32_t ta_id = 0;
uint32_t cmd_id = 0; uint32_t cmd_id = 0;
uint32_t shared_buf_len = 0; uint32_t shared_buf_len = 0;
...@@ -226,24 +299,29 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size ...@@ -226,24 +299,29 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private;
struct psp_context *psp = &adev->psp; struct psp_context *psp = &adev->psp;
struct ta_context context = {0}; struct ta_context *context = NULL;
if (!buf) if (!buf)
return -EINVAL; return -EINVAL;
ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t));
if (ret)
return -EFAULT;
copy_pos += sizeof(uint32_t);
ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t)); ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t));
if (ret) if (ret)
return -EINVAL; return -EFAULT;
copy_pos += sizeof(uint32_t); copy_pos += sizeof(uint32_t);
ret = copy_from_user((void *)&cmd_id, &buf[copy_pos], sizeof(uint32_t)); ret = copy_from_user((void *)&cmd_id, &buf[copy_pos], sizeof(uint32_t));
if (ret) if (ret)
return -EINVAL; return -EFAULT;
copy_pos += sizeof(uint32_t); copy_pos += sizeof(uint32_t);
ret = copy_from_user((void *)&shared_buf_len, &buf[copy_pos], sizeof(uint32_t)); ret = copy_from_user((void *)&shared_buf_len, &buf[copy_pos], sizeof(uint32_t));
if (ret) if (ret)
return -EINVAL; return -EFAULT;
copy_pos += sizeof(uint32_t); copy_pos += sizeof(uint32_t);
shared_buf = kzalloc(shared_buf_len, GFP_KERNEL); shared_buf = kzalloc(shared_buf_len, GFP_KERNEL);
...@@ -254,26 +332,39 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size ...@@ -254,26 +332,39 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
goto err_free_shared_buf; goto err_free_shared_buf;
} }
context.session_id = ta_id; set_ta_context_funcs(psp, ta_type, &context);
prep_ta_mem_context(psp, &context, shared_buf, shared_buf_len); if (!context->initialized) {
dev_err(adev->dev, "TA is not initialized\n");
ret = -EINVAL;
goto err_free_shared_buf;
}
ret = psp_ta_invoke_indirect(psp, cmd_id, &context); if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_invoke) {
dev_err(adev->dev, "Unsupported function to invoke TA\n");
ret = -EOPNOTSUPP;
goto err_free_shared_buf;
}
if (ret || context.resp_status) { context->session_id = ta_id;
dev_err(adev->dev, "TA invoke via debugfs failed (%d) status %d\n",
ret, context.resp_status); ret = prep_ta_mem_context(&context->mem_context, shared_buf, shared_buf_len);
if (!ret) if (ret)
goto err_free_shared_buf;
ret = psp_fn_ta_invoke(psp, cmd_id);
if (ret || context->resp_status) {
dev_err(adev->dev, "Failed to invoke TA via debugfs (%d) and status (0x%X)\n",
ret, context->resp_status);
if (!ret) {
ret = -EINVAL; ret = -EINVAL;
goto err_free_ta_shared_buf; goto err_free_shared_buf;
}
} }
if (copy_to_user((char *)buf, context.mem_context.shared_buf, shared_buf_len)) if (copy_to_user((char *)buf, context->mem_context.shared_buf, shared_buf_len))
ret = -EFAULT; ret = -EFAULT;
err_free_ta_shared_buf:
psp_ta_free_shared_buf(&context.mem_context);
err_free_shared_buf: err_free_shared_buf:
kfree(shared_buf); kfree(shared_buf);
......
...@@ -24,6 +24,11 @@ ...@@ -24,6 +24,11 @@
#ifndef __AMDGPU_PSP_TA_H__ #ifndef __AMDGPU_PSP_TA_H__
#define __AMDGPU_PSP_TA_H__ #define __AMDGPU_PSP_TA_H__
/* Calling set_ta_context_funcs is required before using the following macros */
#define psp_fn_ta_initialize(psp) ((psp)->ta_funcs->fn_ta_initialize((psp)))
#define psp_fn_ta_invoke(psp, ta_cmd_id) ((psp)->ta_funcs->fn_ta_invoke((psp), (ta_cmd_id)))
#define psp_fn_ta_terminate(psp) ((psp)->ta_funcs->fn_ta_terminate((psp)))
void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev); void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment