mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-24 10:11:26 +03:00
video: tegra: host: expect more than one postfence
- postfence completion routine triggers clean up of task data and inform UMD of completion of task, so expect minimum one postfence for task submit. - add more debug message. - validate task data after copying user data - use local task pointer for copying postfences - dump input task parameters Jira DLA-251 Bug 200088648 Change-Id: I3980e095586112d50381057aa7e19991d77fdf32 Signed-off-by: Shridhar Rasal <srasal@nvidia.com> Reviewed-on: http://git-master/r/1311386 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
Laxman Dewangan
parent
d1587acdc0
commit
94b372e4e0
@@ -306,7 +306,7 @@ int nvdla_fill_task_desc(struct nvdla_task *task);
|
||||
* This function send post fences back to UMD after task submit
|
||||
*/
|
||||
int nvdla_send_postfences(struct nvdla_task *task,
|
||||
struct nvdla_ioctl_submit_task usr_task);
|
||||
struct nvdla_ioctl_submit_task *usr_task);
|
||||
|
||||
int nvdla_get_cmd_memory(struct platform_device *pdev,
|
||||
struct nvdla_cmd_mem_info *cmd_mem_info);
|
||||
|
||||
@@ -59,6 +59,8 @@ static int nvdla_set_queue(struct nvdla_private *priv, void *args)
|
||||
int status = queue_arg->status;
|
||||
int err = 0;
|
||||
|
||||
nvdla_dbg_fn(pdev, "");
|
||||
|
||||
if (!queue) {
|
||||
nvdla_dbg_err(pdev, "invalid queue\n");
|
||||
err = -EINVAL;
|
||||
@@ -81,6 +83,7 @@ static int nvdla_set_queue(struct nvdla_private *priv, void *args)
|
||||
err = -EINVAL;
|
||||
goto inval_cmd;
|
||||
}
|
||||
nvdla_dbg_fn(pdev, "done");
|
||||
|
||||
inval_queue:
|
||||
inval_input:
|
||||
@@ -97,6 +100,8 @@ static int nvdla_pin(struct nvdla_private *priv, void *arg)
|
||||
u32 count;
|
||||
struct platform_device *pdev = priv->pdev;
|
||||
|
||||
nvdla_dbg_fn(pdev, "");
|
||||
|
||||
if (!buf_list) {
|
||||
nvdla_dbg_err(pdev, "Invalid argument ptr in pin\n");
|
||||
err = -EINVAL;
|
||||
@@ -119,6 +124,9 @@ static int nvdla_pin(struct nvdla_private *priv, void *arg)
|
||||
}
|
||||
|
||||
err = nvhost_buffer_pin(priv->buffers, handles, count);
|
||||
if (err)
|
||||
nvdla_dbg_err(pdev, "failed to pin handles\n");
|
||||
|
||||
|
||||
nvdla_buffer_cpy_err:
|
||||
fail_to_get_val_cnt:
|
||||
@@ -135,6 +143,8 @@ static int nvdla_unpin(struct nvdla_private *priv, void *arg)
|
||||
u32 count;
|
||||
struct platform_device *pdev = priv->pdev;
|
||||
|
||||
nvdla_dbg_fn(pdev, "");
|
||||
|
||||
if (!buf_list) {
|
||||
nvdla_dbg_err(pdev, "Invalid argument for pointer\n");
|
||||
err = -EINVAL;
|
||||
@@ -284,14 +294,14 @@ fail:
|
||||
}
|
||||
|
||||
int nvdla_send_postfences(struct nvdla_task *task,
|
||||
struct nvdla_ioctl_submit_task user_task)
|
||||
struct nvdla_ioctl_submit_task *user_task)
|
||||
{
|
||||
int err = 0, i;
|
||||
struct platform_device *dla_pdev = task->queue->pool->pdev;
|
||||
struct platform_device *host_pdev =
|
||||
to_platform_device(dla_pdev->dev.parent);
|
||||
struct nvdla_fence __user *postfences =
|
||||
(struct nvdla_fence __user *)(uintptr_t)user_task.postfences;
|
||||
(struct nvdla_fence __user *)(uintptr_t)user_task->postfences;
|
||||
char fence_name[32];
|
||||
|
||||
nvdla_dbg_fn(dla_pdev, "sending post fences");
|
||||
@@ -324,6 +334,7 @@ int nvdla_send_postfences(struct nvdla_task *task,
|
||||
}
|
||||
}
|
||||
|
||||
nvdla_dbg_fn(dla_pdev, "copy postfences to user");
|
||||
/* send post fences */
|
||||
if (copy_to_user(postfences, task->postfences,
|
||||
(task->num_postfences * sizeof(struct nvdla_fence)))) {
|
||||
@@ -347,16 +358,39 @@ size_t nvdla_get_max_task_size(void)
|
||||
|
||||
static int nvdla_val_task_submit_input(struct nvdla_ioctl_submit_task *in_task)
|
||||
{
|
||||
if (in_task->num_prefences > MAX_NUM_NVDLA_PREFENCES)
|
||||
if (in_task->num_prefences > MAX_NUM_NVDLA_PREFENCES) {
|
||||
pr_err("num_prefences[%u] crossing expected[%d]\n",
|
||||
in_task->num_prefences, MAX_NUM_NVDLA_PREFENCES);
|
||||
return -EINVAL;
|
||||
if (in_task->num_postfences > MAX_NUM_NVDLA_POSTFENCES)
|
||||
}
|
||||
if (in_task->num_postfences < 1) {
|
||||
pr_err("num postfences[%u] should be min one",
|
||||
in_task->num_postfences);
|
||||
return -EINVAL;
|
||||
if (in_task->num_input_task_status > MAX_NUM_NVDLA_IN_TASK_STATUS)
|
||||
}
|
||||
if (in_task->num_postfences > MAX_NUM_NVDLA_POSTFENCES) {
|
||||
pr_err("num_postfences[%u] crossing expected[%d]\n",
|
||||
in_task->num_postfences, MAX_NUM_NVDLA_POSTFENCES);
|
||||
return -EINVAL;
|
||||
if (in_task->num_output_task_status > MAX_NUM_NVDLA_OUT_TASK_STATUS)
|
||||
}
|
||||
if (in_task->num_input_task_status > MAX_NUM_NVDLA_IN_TASK_STATUS) {
|
||||
pr_err("in task status[%u] crossing expected[%d]\n",
|
||||
in_task->num_input_task_status,
|
||||
MAX_NUM_NVDLA_IN_TASK_STATUS);
|
||||
return -EINVAL;
|
||||
if (in_task->num_addresses > NVDLA_MAX_BUFFERS_PER_TASK)
|
||||
}
|
||||
if (in_task->num_output_task_status > MAX_NUM_NVDLA_OUT_TASK_STATUS) {
|
||||
pr_err("out task status[%u] crossing expected[%d]\n",
|
||||
in_task->num_output_task_status,
|
||||
MAX_NUM_NVDLA_OUT_TASK_STATUS);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (in_task->num_addresses > NVDLA_MAX_BUFFERS_PER_TASK) {
|
||||
pr_err("num addresses[%u] crossing expected[%d]\n",
|
||||
in_task->num_addresses,
|
||||
NVDLA_MAX_BUFFERS_PER_TASK);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -378,6 +412,12 @@ static int nvdla_fill_task(struct nvhost_queue *queue,
|
||||
task->buffers = buffers;
|
||||
task->sp = &nvhost_get_host(pdev)->syncpt;
|
||||
|
||||
err = nvdla_val_task_submit_input(local_task);
|
||||
if (err) {
|
||||
nvdla_dbg_err(pdev, "Invalid input arguments");
|
||||
goto fail_to_get_val_args;
|
||||
}
|
||||
|
||||
task->num_prefences = local_task->num_prefences;
|
||||
task->num_postfences = local_task->num_postfences;
|
||||
task->num_in_task_status = local_task->num_input_task_status;
|
||||
@@ -420,9 +460,73 @@ static int nvdla_fill_task(struct nvhost_queue *queue,
|
||||
|
||||
fail_to_get_addr_list:
|
||||
fail_to_get_actions:
|
||||
fail_to_get_val_args:
|
||||
return err;
|
||||
}
|
||||
|
||||
void nvdla_dump_task(struct nvdla_task *task)
|
||||
{
|
||||
int i;
|
||||
struct nvhost_queue *queue = task->queue;
|
||||
struct platform_device *pdev = queue->pool->pdev;
|
||||
|
||||
nvdla_dbg_info(pdev, "dumping input task [%p] parameters:", task);
|
||||
nvdla_dbg_info(pdev, "num_prefences[%u] num_postfences[%u]",
|
||||
task->num_postfences, task->num_postfences);
|
||||
nvdla_dbg_info(pdev, "num_in_status[%u] num_out_task_status[%u]",
|
||||
task->num_in_task_status, task->num_out_task_status);
|
||||
nvdla_dbg_info(pdev, "num_addresses[%u]", task->num_addresses);
|
||||
|
||||
for (i = 0; i < task->num_prefences; i++) {
|
||||
nvdla_dbg_info(pdev, "prefence[%d]: type[%u] syncpt_index[%u]"
|
||||
" syncpt_val[%u] sync_fd[%u] sem_handle[%u]"
|
||||
" sem_offset[%u] sem_val[%u]",
|
||||
i, task->prefences[i].type,
|
||||
task->prefences[i].syncpoint_index,
|
||||
task->prefences[i].syncpoint_value,
|
||||
task->prefences[i].sync_fd,
|
||||
task->prefences[i].sem_handle,
|
||||
task->prefences[i].sem_offset,
|
||||
task->prefences[i].sem_val);
|
||||
}
|
||||
|
||||
for (i = 0; i < task->num_postfences; i++) {
|
||||
nvdla_dbg_info(pdev, "postfence[%d]: type[%u] syncpt_index[%u]"
|
||||
" syncpt_val[%u] sync_fd[%u] sem_handle[%u]"
|
||||
" sem_offset[%u] sem_val[%u]",
|
||||
i, task->postfences[i].type,
|
||||
task->postfences[i].syncpoint_index,
|
||||
task->postfences[i].syncpoint_value,
|
||||
task->postfences[i].sync_fd,
|
||||
task->postfences[i].sem_handle,
|
||||
task->postfences[i].sem_offset,
|
||||
task->postfences[i].sem_val);
|
||||
}
|
||||
|
||||
for (i = 0; i < task->num_in_task_status; i++) {
|
||||
nvdla_dbg_info(pdev, "Input task status[%d]:"
|
||||
"handle[%u] offset[%u] status[%u]",
|
||||
i, task->in_task_status[i].handle,
|
||||
task->in_task_status[i].offset,
|
||||
task->in_task_status[i].status);
|
||||
}
|
||||
|
||||
for (i = 0; i < task->num_out_task_status; i++) {
|
||||
nvdla_dbg_info(pdev, "Output task status[%d]:"
|
||||
"handle[%u] offset[%u] status[%u]",
|
||||
i, task->out_task_status[i].handle,
|
||||
task->out_task_status[i].offset,
|
||||
task->out_task_status[i].status);
|
||||
}
|
||||
|
||||
for (i = 0; i < task->num_addresses; i++) {
|
||||
nvdla_dbg_info(pdev, "Memory Handles[%d]:"
|
||||
"handle[%u] offset[%u]",
|
||||
i, task->memory_handles[i].handle,
|
||||
task->memory_handles[i].offset);
|
||||
}
|
||||
}
|
||||
|
||||
static int nvdla_submit(struct nvdla_private *priv, void *arg)
|
||||
{
|
||||
struct nvdla_submit_args *args =
|
||||
@@ -441,10 +545,11 @@ static int nvdla_submit(struct nvdla_private *priv, void *arg)
|
||||
|
||||
pdev = priv->pdev;
|
||||
queue = priv->queue;
|
||||
if (!queue)
|
||||
buffers = priv->buffers;
|
||||
if (!(queue && pdev && buffers))
|
||||
return -EINVAL;
|
||||
|
||||
buffers = priv->buffers;
|
||||
nvdla_dbg_fn(pdev, "inside task submit");
|
||||
|
||||
user_tasks = (struct nvdla_ioctl_submit_task __user *)
|
||||
(uintptr_t)args->tasks;
|
||||
@@ -457,20 +562,13 @@ static int nvdla_submit(struct nvdla_private *priv, void *arg)
|
||||
|
||||
nvdla_dbg_info(pdev, "num of tasks [%d]", num_tasks);
|
||||
|
||||
for (i = 0; i < num_tasks; i++) {
|
||||
err = nvdla_val_task_submit_input(user_tasks + i);
|
||||
if (err) {
|
||||
nvdla_dbg_err(pdev, "Invalid input arguments");
|
||||
goto fail_to_val_args;
|
||||
}
|
||||
}
|
||||
|
||||
/* IOCTL copy descriptors*/
|
||||
if (copy_from_user(local_tasks, user_tasks,
|
||||
if (copy_from_user(local_tasks, (void __user *)user_tasks,
|
||||
(num_tasks * sizeof(*user_tasks)))) {
|
||||
err = -EFAULT;
|
||||
goto fail_to_copy_task;
|
||||
}
|
||||
nvdla_dbg_info(pdev, "copy of user tasks done");
|
||||
|
||||
for (i = 0; i < num_tasks; i++) {
|
||||
|
||||
@@ -481,6 +579,7 @@ static int nvdla_submit(struct nvdla_private *priv, void *arg)
|
||||
nvdla_dbg_err(pdev, "failed to get task[%d] mem", i + 1);
|
||||
goto fail_to_get_task_mem;
|
||||
}
|
||||
nvdla_dbg_info(pdev, "task[%d] mem allocate done", i + 1);
|
||||
|
||||
/* fill local task param from user args */
|
||||
err = nvdla_fill_task(queue, buffers, local_tasks + i, task);
|
||||
@@ -488,6 +587,11 @@ static int nvdla_submit(struct nvdla_private *priv, void *arg)
|
||||
nvdla_dbg_err(pdev, "failed to fill task[%d]", i + 1);
|
||||
goto fail_to_fill_task;
|
||||
}
|
||||
nvdla_dbg_info(pdev, "local task[%d] filled", i + 1);
|
||||
|
||||
/* dump task input parameters */
|
||||
nvdla_dump_task(task);
|
||||
nvdla_dbg_info(pdev, "dump task[%d] done", i + 1);
|
||||
|
||||
/* update task desc fields */
|
||||
err = nvdla_fill_task_desc(task);
|
||||
@@ -495,6 +599,7 @@ static int nvdla_submit(struct nvdla_private *priv, void *arg)
|
||||
nvdla_dbg_err(pdev, "fail to fill task desc%d", i + 1);
|
||||
goto fail_to_fill_task_desc;
|
||||
}
|
||||
nvdla_dbg_info(pdev, "task[%d] desc filled", i + 1);
|
||||
|
||||
/* send job to engine through queue framework */
|
||||
err = nvhost_queue_submit(queue, task);
|
||||
@@ -502,14 +607,18 @@ static int nvdla_submit(struct nvdla_private *priv, void *arg)
|
||||
nvdla_dbg_err(pdev, "fail to submit task: %d", i + 1);
|
||||
goto fail_to_submit_task;
|
||||
}
|
||||
nvdla_dbg_info(pdev, "task[%d] submitted", i + 1);
|
||||
|
||||
/* send fences to user */
|
||||
err = nvdla_send_postfences(task, user_tasks[i]);
|
||||
err = nvdla_send_postfences(task, local_tasks + i);
|
||||
if (err) {
|
||||
nvdla_dbg_err(pdev, "fail to send postfence%d", i + 1);
|
||||
goto fail_to_send_postfences;
|
||||
}
|
||||
nvdla_dbg_info(pdev, "postfences of task[%d] sent", i + 1);
|
||||
}
|
||||
nvdla_dbg_fn(pdev, "Task submitted, done!");
|
||||
|
||||
return 0;
|
||||
|
||||
fail_to_send_postfences:
|
||||
@@ -519,7 +628,6 @@ fail_to_fill_task:
|
||||
/*TODO: traverse list in reverse and delete jobs */
|
||||
fail_to_get_task_mem:
|
||||
fail_to_copy_task:
|
||||
fail_to_val_args:
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -567,6 +675,7 @@ static long nvdla_ioctl(struct file *file, unsigned int cmd,
|
||||
err = nvdla_set_queue(priv, (void *)buf);
|
||||
break;
|
||||
default:
|
||||
nvdla_dbg_err(pdev, "invalid IOCTL CMD");
|
||||
err = -ENOIOCTLCMD;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,9 @@ int nvdla_get_task_mem(struct nvhost_queue *queue,
|
||||
int err;
|
||||
struct nvdla_task *task = NULL;
|
||||
struct nvhost_queue_task_mem_info task_mem_info;
|
||||
struct platform_device *pdev = queue->pool->pdev;
|
||||
|
||||
nvdla_dbg_fn(pdev, "");
|
||||
|
||||
/* get mem task descriptor and task mem from task_mem_pool */
|
||||
err = nvhost_queue_alloc_task_memory(queue, &task_mem_info);
|
||||
@@ -96,6 +99,9 @@ static void task_free(struct kref *ref)
|
||||
void nvdla_task_put(struct nvdla_task *task)
|
||||
{
|
||||
struct nvhost_queue *queue = task->queue;
|
||||
struct platform_device *pdev = queue->pool->pdev;
|
||||
|
||||
nvdla_dbg_fn(pdev, "task:[%p]", task);
|
||||
|
||||
kref_put(&task->ref, task_free);
|
||||
|
||||
@@ -105,6 +111,11 @@ void nvdla_task_put(struct nvdla_task *task)
|
||||
|
||||
void nvdla_task_get(struct nvdla_task *task)
|
||||
{
|
||||
struct nvhost_queue *queue = task->queue;
|
||||
struct platform_device *pdev = queue->pool->pdev;
|
||||
|
||||
nvdla_dbg_fn(pdev, "task:[%p]", task);
|
||||
|
||||
/* update queue refcnt */
|
||||
nvhost_queue_get(task->queue);
|
||||
|
||||
@@ -114,6 +125,10 @@ void nvdla_task_get(struct nvdla_task *task)
|
||||
static int nvdla_unmap_task_memory(struct nvdla_task *task)
|
||||
{
|
||||
int ii;
|
||||
struct nvhost_queue *queue = task->queue;
|
||||
struct platform_device *pdev = queue->pool->pdev;
|
||||
|
||||
nvdla_dbg_fn(pdev, "task:[%p]", task);
|
||||
|
||||
/* unpin address list */
|
||||
for (ii = 0; ii < task->num_addresses; ii++) {
|
||||
@@ -121,6 +136,7 @@ static int nvdla_unmap_task_memory(struct nvdla_task *task)
|
||||
nvhost_buffer_submit_unpin(task->buffers,
|
||||
&task->memory_handles[ii].handle, 1);
|
||||
}
|
||||
nvdla_dbg_fn(pdev, "all mem handles unmaped");
|
||||
|
||||
/* unpin prefences memory */
|
||||
for (ii = 0; ii < task->num_prefences; ii++) {
|
||||
@@ -130,6 +146,7 @@ static int nvdla_unmap_task_memory(struct nvdla_task *task)
|
||||
&task->prefences[ii].sem_handle, 1);
|
||||
}
|
||||
}
|
||||
nvdla_dbg_fn(pdev, "all prefences unmaped");
|
||||
|
||||
/* unpin input task status memory */
|
||||
for (ii = 0; ii < task->num_in_task_status; ii++) {
|
||||
@@ -137,6 +154,7 @@ static int nvdla_unmap_task_memory(struct nvdla_task *task)
|
||||
nvhost_buffer_submit_unpin(task->buffers,
|
||||
&task->in_task_status[ii].handle, 1);
|
||||
}
|
||||
nvdla_dbg_fn(pdev, "all in task status unmaped");
|
||||
|
||||
/* unpin postfences memory */
|
||||
for (ii = 0; ii < task->num_postfences; ii++) {
|
||||
@@ -147,6 +165,7 @@ static int nvdla_unmap_task_memory(struct nvdla_task *task)
|
||||
&task->postfences[ii].sem_handle, 1);
|
||||
}
|
||||
}
|
||||
nvdla_dbg_fn(pdev, "all postfences unmaped");
|
||||
|
||||
/* unpin input task status memory */
|
||||
for (ii = 0; ii < task->num_out_task_status; ii++) {
|
||||
@@ -154,6 +173,7 @@ static int nvdla_unmap_task_memory(struct nvdla_task *task)
|
||||
nvhost_buffer_submit_unpin(task->buffers,
|
||||
&task->out_task_status[ii].handle, 1);
|
||||
}
|
||||
nvdla_dbg_fn(pdev, "all out task status unmaped");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -197,6 +217,8 @@ static void nvdla_queue_update(void *priv, int nr_completed)
|
||||
|
||||
mutex_lock(&queue->list_lock);
|
||||
|
||||
nvdla_dbg_fn(pdev, "");
|
||||
|
||||
/* check which task(s) finished */
|
||||
list_for_each_entry_safe(task, safe, &queue->tasklist, list) {
|
||||
|
||||
@@ -204,8 +226,11 @@ static void nvdla_queue_update(void *priv, int nr_completed)
|
||||
queue->syncpt_id, task->fence);
|
||||
|
||||
/* clean task and remove from list */
|
||||
if (task_complete)
|
||||
if (task_complete) {
|
||||
nvdla_dbg_fn(pdev, "task with syncpt[%d] val[%d] done",
|
||||
queue->syncpt_id, task->fence);
|
||||
nvdla_task_free_locked(task);
|
||||
}
|
||||
}
|
||||
/* put pm refcount */
|
||||
nvhost_module_idle_mult(pdev, nr_completed);
|
||||
@@ -325,6 +350,7 @@ static int nvdla_map_task_memory(struct nvdla_task *task)
|
||||
sizeof(struct dla_action_list) + nvdla_get_max_preaction_size() +
|
||||
sizeof(struct dla_action_list) + nvdla_get_max_postaction_size();
|
||||
offset = roundup(offset, 8);
|
||||
nvdla_dbg_fn(pdev, "addresslist offset is[%zu]", offset);
|
||||
|
||||
/* get task desc address list to update list from kernel */
|
||||
next = (u8 *)task_desc + offset;
|
||||
@@ -684,6 +710,10 @@ int nvdla_fill_task_desc(struct nvdla_task *task)
|
||||
task_desc->queue_id = queue->id;
|
||||
|
||||
nvdla_dbg_info(pdev, "Queue id[%d]", task_desc->queue_id);
|
||||
nvdla_dbg_info(pdev, "version[%d]", task_desc->version);
|
||||
nvdla_dbg_info(pdev, "engine_id[%d]", task_desc->engine_id);
|
||||
nvdla_dbg_info(pdev, "task desc size[%u]", task_desc->size);
|
||||
nvdla_dbg_info(pdev, "task desc sequence[%u]", task_desc->sequence);
|
||||
|
||||
/* get pre/post action list HEAD mem offset
|
||||
* - preactions list HEAD stored after dla_task_descriptor
|
||||
@@ -742,6 +772,9 @@ static int nvdla_queue_submit(struct nvhost_queue *queue, void *in_task)
|
||||
last_task = list_last_entry(&queue->tasklist,
|
||||
struct nvdla_task, list);
|
||||
last_task->task_desc->next = (uint64_t)task->task_desc_pa;
|
||||
|
||||
nvdla_dbg_info(pdev, "last task[%p] last_task_desc_pa[%llu]",
|
||||
last_task, task->task_desc_pa);
|
||||
}
|
||||
list_add_tail(&task->list, &queue->tasklist);
|
||||
|
||||
@@ -779,9 +812,11 @@ static int nvdla_queue_submit(struct nvhost_queue *queue, void *in_task)
|
||||
|
||||
/* submit task to engine */
|
||||
err = nvdla_send_cmd(pdev, &cmd_data);
|
||||
if (err)
|
||||
if (err) {
|
||||
nvdla_task_syncpt_reset(task->sp, queue->syncpt_id,
|
||||
task->fence);
|
||||
nvdla_dbg_err(pdev, "task[%p] submit failed", task);
|
||||
}
|
||||
|
||||
fail_to_register:
|
||||
mutex_unlock(&queue->list_lock);
|
||||
|
||||
Reference in New Issue
Block a user