summaryrefslogtreecommitdiffstats
path: root/drivers/video/tegra
diff options
context:
space:
mode:
authorArvind M <am@nvidia.com>2021-04-21 03:18:07 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2021-04-22 22:10:49 -0400
commitc852734bc80c8262f81a0ca666fe444c59d7189f (patch)
tree04bfc03eb003e66a18f79ddcd465d75654a3e2fb /drivers/video/tegra
parent31f770700e4b7fc80fae72a670d3d482727887f1 (diff)
nvdla: kmd: synchronize access to task pool memory
[1] In the absence of synchronization to access task pool, submission may happen at faster rate than cleanups. This shall lead to frequent out-of-memory error. [2] This commit fixes the issues through retries before throwing OOM. a. Sets up a communication between cleanup & submit. b. Retries for allocating task memory - Retry period: 1 ms - Total timeout: 10 ms Bug 200680501 Change-Id: Iea25fbe6e7891938f6318285d4824bc1c54ddb05 Signed-off-by: Arvind M <am@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2518666 Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@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
Diffstat (limited to 'drivers/video/tegra')
-rw-r--r--drivers/video/tegra/host/nvdla/dla_queue.c34
-rw-r--r--drivers/video/tegra/host/nvdla/dla_queue.h5
-rw-r--r--drivers/video/tegra/host/nvdla/nvdla_queue.c8
3 files changed, 40 insertions, 7 deletions
diff --git a/drivers/video/tegra/host/nvdla/dla_queue.c b/drivers/video/tegra/host/nvdla/dla_queue.c
index 33fa3aae4..ed3d685e1 100644
--- a/drivers/video/tegra/host/nvdla/dla_queue.c
+++ b/drivers/video/tegra/host/nvdla/dla_queue.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * NVDLA queue management 2 * NVDLA queue management
3 * 3 *
4 * Copyright (c) 2019-2020, NVIDIA Corporation. All rights reserved. 4 * Copyright (c) 2019-2021, NVIDIA Corporation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License, 7 * under the terms and conditions of the GNU General Public License,
@@ -46,8 +46,9 @@
46 * lock Mutex lock for the array access. 46 * lock Mutex lock for the array access.
47 * alloc_table Keep track of the index being assigned 47 * alloc_table Keep track of the index being assigned
48 * and freed for a task 48 * and freed for a task
49 * max_task_cnt Maximum task count that can be supported. 49 * max_task_cnt Maximum task count that can be supported.
50 * 50 * cleanup_done Completion status of cleanup wait.
51 * cleanup_wait Records wait for cleanup action.
51 */ 52 */
52 53
53struct nvdla_queue_task_pool { 54struct nvdla_queue_task_pool {
@@ -58,6 +59,9 @@ struct nvdla_queue_task_pool {
58 59
59 unsigned long alloc_table; 60 unsigned long alloc_table;
60 unsigned long max_task_cnt; 61 unsigned long max_task_cnt;
62
63 struct completion cleanup_done;
64 int cleanup_wait;
61}; 65};
62 66
63static int nvdla_queue_task_pool_alloc(struct platform_device *pdev, 67static int nvdla_queue_task_pool_alloc(struct platform_device *pdev,
@@ -96,6 +100,9 @@ static int nvdla_queue_task_pool_alloc(struct platform_device *pdev,
96 100
97 mutex_init(&task_pool->lock); 101 mutex_init(&task_pool->lock);
98 102
103 init_completion(&task_pool->cleanup_done);
104 task_pool->cleanup_wait = 0;
105
99 return err; 106 return err;
100 107
101err_alloc_task_pool: 108err_alloc_task_pool:
@@ -549,6 +556,18 @@ int nvdla_queue_alloc_task_memory(
549 struct nvdla_queue_task_pool *task_pool = 556 struct nvdla_queue_task_pool *task_pool =
550 (struct nvdla_queue_task_pool *)queue->task_pool; 557 (struct nvdla_queue_task_pool *)queue->task_pool;
551 558
559 if (task_pool->cleanup_wait == 1) {
560 unsigned long timeout =
561 msecs_to_jiffies(NVDLA_TASK_MEM_AVAIL_RETRY_PERIOD);
562
563 /**
564 * Error intentionally ignored to be catpured as part of
565 * out-of-range index during allocation.
566 **/
567 (void) wait_for_completion_timeout(&task_pool->cleanup_done,
568 timeout);
569 }
570
552 mutex_lock(&task_pool->lock); 571 mutex_lock(&task_pool->lock);
553 572
554 index = find_first_zero_bit(&task_pool->alloc_table, 573 index = find_first_zero_bit(&task_pool->alloc_table,
@@ -556,8 +575,8 @@ int nvdla_queue_alloc_task_memory(
556 575
557 /* quit if pre-allocated task array is not free */ 576 /* quit if pre-allocated task array is not free */
558 if (index >= task_pool->max_task_cnt) { 577 if (index >= task_pool->max_task_cnt) {
559 dev_err(&pdev->dev, 578 dev_warn(&pdev->dev, "failed to get Task Pool Memory\n");
560 "failed to get Task Pool Memory\n"); 579 task_pool->cleanup_wait = 1; // wait for cleanup
561 err = -EAGAIN; 580 err = -EAGAIN;
562 goto err_alloc_task_mem; 581 goto err_alloc_task_mem;
563 } 582 }
@@ -596,5 +615,10 @@ void nvdla_queue_free_task_memory(struct nvdla_queue *queue, int index)
596 615
597 mutex_lock(&task_pool->lock); 616 mutex_lock(&task_pool->lock);
598 clear_bit(index, &task_pool->alloc_table); 617 clear_bit(index, &task_pool->alloc_table);
618
619 if (task_pool->cleanup_wait == 1) {
620 task_pool->cleanup_wait = 0;
621 complete(&task_pool->cleanup_done);
622 }
599 mutex_unlock(&task_pool->lock); 623 mutex_unlock(&task_pool->lock);
600} 624}
diff --git a/drivers/video/tegra/host/nvdla/dla_queue.h b/drivers/video/tegra/host/nvdla/dla_queue.h
index 1f5801c66..8bded0f65 100644
--- a/drivers/video/tegra/host/nvdla/dla_queue.h
+++ b/drivers/video/tegra/host/nvdla/dla_queue.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * NVHOST Queue management header for T194 2 * NVHOST Queue management header for T194
3 * 3 *
4 * Copyright (c) 2016-2017, NVIDIA Corporation. All rights reserved. 4 * Copyright (c) 2016-2021, NVIDIA Corporation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License, 7 * under the terms and conditions of the GNU General Public License,
@@ -21,6 +21,9 @@
21 21
22#include <linux/kref.h> 22#include <linux/kref.h>
23 23
24#define NVDLA_TASK_MEM_AVAIL_TIMEOUT_MS 10 /* 10 ms */
25#define NVDLA_TASK_MEM_AVAIL_RETRY_PERIOD 1 /* 1 ms */
26
24struct nvdla_queue_task_pool; 27struct nvdla_queue_task_pool;
25 28
26/** 29/**
diff --git a/drivers/video/tegra/host/nvdla/nvdla_queue.c b/drivers/video/tegra/host/nvdla/nvdla_queue.c
index 5c7bddd4b..ccb182b24 100644
--- a/drivers/video/tegra/host/nvdla/nvdla_queue.c
+++ b/drivers/video/tegra/host/nvdla/nvdla_queue.c
@@ -88,11 +88,17 @@ int nvdla_get_task_mem(struct nvdla_queue *queue,
88 struct nvdla_task *task = NULL; 88 struct nvdla_task *task = NULL;
89 struct nvdla_queue_task_mem_info task_mem_info; 89 struct nvdla_queue_task_mem_info task_mem_info;
90 struct platform_device *pdev = queue->pool->pdev; 90 struct platform_device *pdev = queue->pool->pdev;
91 int n_retries = (NVDLA_TASK_MEM_AVAIL_TIMEOUT_MS /
92 NVDLA_TASK_MEM_AVAIL_RETRY_PERIOD);
91 93
92 nvdla_dbg_fn(pdev, ""); 94 nvdla_dbg_fn(pdev, "");
93 95
94 /* get mem task descriptor and task mem from task_mem_pool */ 96 /* get mem task descriptor and task mem from task_mem_pool */
95 err = nvdla_queue_alloc_task_memory(queue, &task_mem_info); 97 do {
98 n_retries = n_retries - 1;
99 err = nvdla_queue_alloc_task_memory(queue, &task_mem_info);
100 } while ((n_retries > 0) && (err == -EAGAIN));
101
96 task = task_mem_info.kmem_addr; 102 task = task_mem_info.kmem_addr;
97 if ((err < 0) || !task) 103 if ((err < 0) || !task)
98 goto fail_to_assign_pool; 104 goto fail_to_assign_pool;