From 3a1e6b396ba97a25e01ecd8ffd932e4f0276608f Mon Sep 17 00:00:00 2001 From: Shridhar Rasal Date: Mon, 16 Jan 2017 13:55:39 +0530 Subject: [PATCH] video: tegra: host: dla: remove dynamic kernel task mem alloc - nvhost_queue_task_pool_alloc() also allocates kcalloc based memory. Use this memory to keep kernel copy of task and get this memory assigned during task submission. Release memory during task cleanup along with dma alloc. - Memory pool free'd while freeing queue on device close. - Using preallocated memory should help to improve performance of job submission. - memset for dma and kernel memory done from queue common code, so removing memset for task descriptor memory. - Fix releasing queue refcnt and release it after free task memory. DLA-271 Change-Id: I711b3181e742c05e934f1c621b3dc6e5cf94b67c Signed-off-by: Shridhar Rasal Reviewed-on: http://git-master/r/1285892 Reviewed-by: Prashant Gaikwad GVS: Gerrit_Virtual_Submit --- drivers/video/tegra/host/nvdla/nvdla.h | 4 ++ drivers/video/tegra/host/nvdla/nvdla_ioctl.c | 27 ++++----- drivers/video/tegra/host/nvdla/nvdla_queue.c | 63 +++++++++----------- 3 files changed, 41 insertions(+), 53 deletions(-) diff --git a/drivers/video/tegra/host/nvdla/nvdla.h b/drivers/video/tegra/host/nvdla/nvdla.h index 0ac45a3c..f34c04e0 100644 --- a/drivers/video/tegra/host/nvdla/nvdla.h +++ b/drivers/video/tegra/host/nvdla/nvdla.h @@ -281,5 +281,9 @@ int nvdla_get_cmd_memory(struct platform_device *pdev, struct nvdla_cmd_mem_info *cmd_mem_info); int nvdla_put_cmd_memory(struct platform_device *pdev, int index); int nvdla_set_queue_state(struct nvhost_queue *queue, int cmd); +int nvdla_get_task_mem(struct nvhost_queue *queue, + struct nvdla_task **task); +void nvdla_put_task_mem(struct nvdla_task *task); +size_t nvdla_get_max_task_size(void); #endif /* End of __NVHOST_NVDLA_H__ */ diff --git a/drivers/video/tegra/host/nvdla/nvdla_ioctl.c b/drivers/video/tegra/host/nvdla/nvdla_ioctl.c index cb30d644..b2de9a02 100644 --- a/drivers/video/tegra/host/nvdla/nvdla_ioctl.c +++ b/drivers/video/tegra/host/nvdla/nvdla_ioctl.c @@ -346,7 +346,7 @@ fail: return err; } -static inline int nvdla_get_max_task_size(void) +size_t nvdla_get_max_task_size(void) { return (sizeof(struct nvdla_task) + ((MAX_NUM_NVDLA_PREFENCES + MAX_NUM_NVDLA_POSTFENCES) * @@ -359,23 +359,14 @@ static inline int nvdla_get_max_task_size(void) static int nvdla_fill_task(struct nvhost_queue *queue, struct nvhost_buffers *buffers, struct nvdla_ioctl_submit_task *local_task, - struct nvdla_task **ptask) + struct nvdla_task *task) { void *mem; int err = 0; - struct nvdla_task *task = NULL; struct platform_device *pdev = queue->pool->pdev; nvdla_dbg_fn(pdev, ""); - /* allocate task resource */ - task = kzalloc(nvdla_get_max_task_size(), GFP_KERNEL); - if (!task) { - err = -ENOMEM; - nvdla_dbg_err(pdev, "KMD task allocation failed"); - goto fail_to_alloc_task; - } - /* initialize task parameters */ kref_init(&task->ref); task->queue = queue; @@ -417,17 +408,12 @@ static int nvdla_fill_task(struct nvhost_queue *queue, task->num_addresses = local_task->num_addresses; task->address_list = local_task->address_list; - *ptask = task; - nvdla_dbg_info(pdev, "local task %p param filled with args", task); return 0; fail_to_get_actions: fail_to_get_val_args: - kfree(task); -fail_to_alloc_task: - *ptask = NULL; return err; } @@ -480,8 +466,14 @@ static int nvdla_submit(struct nvdla_private *priv, void *arg) nvdla_dbg_info(pdev, "submit [%d]th task", i + 1); + err = nvdla_get_task_mem(queue, &task); + if (err) { + nvdla_dbg_err(pdev, "failed to get task[%d] mem", i + 1); + goto fail_to_get_task_mem; + } + /* fill local task param from user args */ - err = nvdla_fill_task(queue, buffers, local_tasks + i, &task); + err = nvdla_fill_task(queue, buffers, local_tasks + i, task); if (err) { nvdla_dbg_err(pdev, "failed to fill task[%d]", i + 1); goto fail_to_fill_task; @@ -519,6 +511,7 @@ fail_to_submit_task: fail_to_fill_task_desc: fail_to_fill_task: /*TODO: traverse list in reverse and delete jobs */ +fail_to_get_task_mem: fail_to_copy_task: kfree(local_tasks); local_tasks = NULL; diff --git a/drivers/video/tegra/host/nvdla/nvdla_queue.c b/drivers/video/tegra/host/nvdla/nvdla_queue.c index d6066a47..7011a44e 100644 --- a/drivers/video/tegra/host/nvdla/nvdla_queue.c +++ b/drivers/video/tegra/host/nvdla/nvdla_queue.c @@ -45,39 +45,42 @@ #define NVDLA_QUEUE_ABORT_RETRY_PERIOD 500 /* 500 ms */ /* task management API's */ -static int nvdla_assign_task_desc_mem(struct nvdla_task *task) +int nvdla_get_task_mem(struct nvhost_queue *queue, + struct nvdla_task **ptask) { int err; - struct nvhost_queue_task_mem_info task_desc_mem; + struct nvdla_task *task = NULL; + struct nvhost_queue_task_mem_info task_mem_info; - /* assign mem task descriptor from task pool memory */ - err = nvhost_queue_alloc_task_memory(task->queue, &task_desc_mem); - if (err) + /* get mem task descriptor and task mem from task_mem_pool */ + err = nvhost_queue_alloc_task_memory(queue, &task_mem_info); + task = task_mem_info.kmem_addr; + if ((err < 0) || !task) goto fail_to_assign_pool; /* check if IOVA is correctly aligned */ - if (task_desc_mem.dma_addr & 0xff) { + if (task_mem_info.dma_addr & 0xff) { err = -EFAULT; goto fail_to_aligned_dma; } - task->task_desc = task_desc_mem.va; - task->task_desc_pa = task_desc_mem.dma_addr; - task->pool_index = task_desc_mem.pool_index; + task->task_desc = task_mem_info.va; + task->task_desc_pa = task_mem_info.dma_addr; + task->pool_index = task_mem_info.pool_index; + + *ptask = task; fail_to_aligned_dma: fail_to_assign_pool: return err; } -static void nvdla_release_task_desc_mem(struct nvdla_task *task) +void nvdla_put_task_mem(struct nvdla_task *task) { - /* release allocated task desc mem */ + /* release allocated task desc and task mem */ nvhost_queue_free_task_memory(task->queue, task->pool_index); - task->task_desc = NULL; - task->task_desc_pa = 0; - task->pool_index = 0; + task = NULL; } static void task_free(struct kref *ref) @@ -86,30 +89,30 @@ static void task_free(struct kref *ref) struct platform_device *pdev = task->queue->pool->pdev; nvdla_dbg_info(pdev, "freeing task[%p]", task); - nvdla_release_task_desc_mem(task); /* free operation descriptor handle */ if (task->memory_handles) kfree(task->memory_handles); - /* finally free task */ - kfree(task); + nvdla_put_task_mem(task); } void nvdla_task_put(struct nvdla_task *task) { - /* release queue refcnt */ - nvhost_queue_put(task->queue); + struct nvhost_queue *queue = task->queue; kref_put(&task->ref, task_free); + + /* Queue should be last to update */ + nvhost_queue_put(queue); } void nvdla_task_get(struct nvdla_task *task) { - kref_get(&task->ref); - /* update queue refcnt */ nvhost_queue_get(task->queue); + + kref_get(&task->ref); } static void nvdla_task_free_locked(struct nvdla_task *task) @@ -395,7 +398,7 @@ static size_t nvdla_get_task_desc_size(void) static void nvdla_get_task_desc_memsize(size_t *dma_size, size_t *kmem_size) { *dma_size = nvdla_get_task_desc_size(); - *kmem_size = 0; + *kmem_size = nvdla_get_max_task_size(); } static inline u8 *add_opcode(u8 *mem, uint8_t op) @@ -676,28 +679,17 @@ static int nvdla_fill_preactions(struct nvdla_task *task) int nvdla_fill_task_desc(struct nvdla_task *task) { int err; - size_t task_desc_size; struct dla_task_descriptor *task_desc; struct nvhost_queue *queue = task->queue; struct platform_device *pdev = queue->pool->pdev; nvdla_dbg_fn(pdev, ""); - /* assign mem task descriptor*/ - err = nvdla_assign_task_desc_mem(task); - if (err) { - nvdla_dbg_err(pdev, "fail to get mem for task desc"); - goto fail_assign_task_desc; - } - - task_desc_size = nvdla_get_task_desc_size(); - memset(task->task_desc, 0, task_desc_size); - /* update task desc fields */ task_desc = task->task_desc; task_desc->version = DLA_DESCRIPTOR_VERSION; task_desc->engine_id = DLA_ENGINE_ID; - task_desc->size = task_desc_size; + task_desc->size = nvdla_get_task_desc_size(); /* update current task sequeue, make sure wrap around condition */ queue->sequence = queue->sequence + 1; @@ -741,9 +733,8 @@ int nvdla_fill_task_desc(struct nvdla_task *task) nvdla_dbg_info(pdev, "task[%p] initialized", task); return 0; + fail_to_map_mem: - nvdla_release_task_desc_mem(task); -fail_assign_task_desc: return err; }