mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-24 02:01:36 +03:00
nvdla: kmd: cleanup error propagation in submit
[1] Prior to this commit,
- Errors during nvdla_fill_preactions/postactions are ignored and continued.
- Resources (task memory, references) are not cleaned up leading to resource
leak.
[3] This commit fixes the issue by handling resource cleanup and errors
propagations.
Bug 200680501
Change-Id: I34d96d24e669f79cca09e38ba9ecb0ccb0c7d726
Signed-off-by: Arvind M <am@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2517596
Reviewed-by: Ken Adams <kadams@nvidia.com>
Reviewed-by: Anup Mahindre <amahindre@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
This commit is contained in:
committed by
Laxman Dewangan
parent
6242fdd281
commit
da00f99aa3
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* NVDLA IOCTL for T194
|
||||
*
|
||||
* Copyright (c) 2016-2020, NVIDIA Corporation. All rights reserved.
|
||||
* Copyright (c) 2016-2021, NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -638,6 +638,10 @@ static int nvdla_update_signal_fences(struct nvdla_task *task,
|
||||
nvdla_dbg_info(dla_pdev, "postfences copied for user");
|
||||
|
||||
fail:
|
||||
/**
|
||||
* TODO: Unmap task memory in event of failure.
|
||||
* Defering the fix since this is rare failure to encounter.
|
||||
**/
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -715,7 +719,6 @@ static int nvdla_fill_task(struct nvdla_queue *queue,
|
||||
nvdla_dbg_fn(pdev, "");
|
||||
|
||||
/* initialize task parameters */
|
||||
kref_init(&task->ref);
|
||||
task->queue = queue;
|
||||
task->buffers = buffers;
|
||||
task->sp = &nvhost_get_host(pdev)->syncpt;
|
||||
@@ -1024,7 +1027,7 @@ static int nvdla_submit(struct nvdla_private *priv, void *arg)
|
||||
struct nvdla_queue *queue;
|
||||
struct nvdla_buffers *buffers;
|
||||
u32 num_tasks;
|
||||
struct nvdla_task *task;
|
||||
struct nvdla_task *task = NULL; // task under submission
|
||||
int err = 0, i = 0;
|
||||
|
||||
if (!args || !priv)
|
||||
@@ -1058,7 +1061,6 @@ static int nvdla_submit(struct nvdla_private *priv, void *arg)
|
||||
nvdla_dbg_info(pdev, "copy of user tasks done");
|
||||
|
||||
for (i = 0; i < num_tasks; i++) {
|
||||
|
||||
nvdla_dbg_info(pdev, "submit [%d]th task", i + 1);
|
||||
|
||||
err = nvdla_get_task_mem(queue, &task);
|
||||
@@ -1068,11 +1070,13 @@ static int nvdla_submit(struct nvdla_private *priv, void *arg)
|
||||
}
|
||||
nvdla_dbg_info(pdev, "task[%d] mem allocate done", i + 1);
|
||||
|
||||
/* Initialize ref for task submit preparation */
|
||||
kref_init(&task->ref);
|
||||
|
||||
/* fill local task param from user args */
|
||||
err = nvdla_fill_task(queue, buffers, local_tasks + i, task);
|
||||
if (err) {
|
||||
nvdla_dbg_err(pdev, "failed to fill task[%d]", i + 1);
|
||||
kref_put(&task->ref, task_free);
|
||||
goto fail_to_fill_task;
|
||||
}
|
||||
nvdla_dbg_info(pdev, "local task[%d] filled", i + 1);
|
||||
@@ -1118,11 +1122,22 @@ static int nvdla_submit(struct nvdla_private *priv, void *arg)
|
||||
|
||||
return 0;
|
||||
|
||||
/**
|
||||
* Note:
|
||||
* Any failures during a task submit preparation,
|
||||
* 1. shall not affect previous tasks within this submit that has been
|
||||
* successfully submitted.
|
||||
* 2. shall abandon consecutive tasks within this submit.
|
||||
**/
|
||||
fail_to_submit_task:
|
||||
fail_to_update_postfences:
|
||||
fail_to_get_fences:
|
||||
fail_to_fill_task_desc:
|
||||
fail_to_fill_task:
|
||||
/* Remove ref corresponding task submit preparation */
|
||||
if (task != NULL)
|
||||
kref_put(&task->ref, task_free);
|
||||
|
||||
/*TODO: traverse list in reverse and delete jobs */
|
||||
fail_to_get_task_mem:
|
||||
fail_to_copy_task:
|
||||
|
||||
@@ -1269,14 +1269,22 @@ int nvdla_fill_task_desc(struct nvdla_task *task)
|
||||
task->fence_counter = 0;
|
||||
|
||||
/* fill pre actions */
|
||||
nvdla_fill_preactions(task);
|
||||
err = nvdla_fill_preactions(task);
|
||||
if (err != 0) {
|
||||
nvdla_dbg_err(pdev, "fail to fill preactions");
|
||||
goto fail_to_map_mem;
|
||||
}
|
||||
|
||||
/* fill post actions */
|
||||
nvdla_fill_postactions(task);
|
||||
err = nvdla_fill_postactions(task);
|
||||
if (err != 0) {
|
||||
nvdla_dbg_err(pdev, "fail to fill postactions");
|
||||
goto fail_to_map_mem;
|
||||
}
|
||||
|
||||
/* ping user memory before submit to engine */
|
||||
err = nvdla_map_task_memory(task);
|
||||
if (err) {
|
||||
if (err != 0) {
|
||||
nvdla_dbg_err(pdev, "fail to pin mem");
|
||||
goto fail_to_map_mem;
|
||||
}
|
||||
@@ -1286,6 +1294,7 @@ int nvdla_fill_task_desc(struct nvdla_task *task)
|
||||
return 0;
|
||||
|
||||
fail_to_map_mem:
|
||||
(void) nvdla_unmap_task_memory(task);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1479,9 +1488,6 @@ int nvdla_get_signal_fences(struct nvdla_queue *queue, void *in_task)
|
||||
|
||||
nvdla_dbg_fn(pdev, "");
|
||||
|
||||
/* get task ref */
|
||||
nvdla_task_get(task);
|
||||
|
||||
if (task->fence_counter == 0)
|
||||
task->fence_counter = 1;
|
||||
|
||||
@@ -1549,6 +1555,9 @@ static int nvdla_queue_submit_op(struct nvdla_queue *queue, void *in_task)
|
||||
|
||||
mutex_lock(&queue->list_lock);
|
||||
|
||||
/* Get a reference before registration or submission */
|
||||
nvdla_task_get(task);
|
||||
|
||||
/* get fence from nvhost for MMIO mode*/
|
||||
if (nvdla_dev->submit_mode == NVDLA_SUBMIT_MODE_MMIO) {
|
||||
task->fence = nvhost_syncpt_incr_max(task->sp,
|
||||
@@ -1617,8 +1626,10 @@ static int nvdla_queue_submit_op(struct nvdla_queue *queue, void *in_task)
|
||||
err = nvdla_send_cmd(pdev, &cmd_data);
|
||||
if (err) {
|
||||
nvdla_dbg_err(pdev, "task[%p] submit failed", task);
|
||||
nvdla_task_syncpt_reset(task->sp, queue->syncpt_id,
|
||||
task->fence);
|
||||
/* deletes invalid task from queue, puts refs */
|
||||
nvdla_task_syncpt_reset(task->sp,
|
||||
queue->syncpt_id,
|
||||
task->fence);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1645,6 +1656,7 @@ fail_to_register:
|
||||
fail_to_channel_submit:
|
||||
nvhost_module_idle(pdev);
|
||||
fail_to_poweron:
|
||||
nvdla_task_free_locked(task);
|
||||
mutex_unlock(&queue->list_lock);
|
||||
|
||||
return err;
|
||||
|
||||
Reference in New Issue
Block a user