diff options
author | Arvind M <am@nvidia.com> | 2021-04-21 03:18:07 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2021-04-22 22:10:49 -0400 |
commit | c852734bc80c8262f81a0ca666fe444c59d7189f (patch) | |
tree | 04bfc03eb003e66a18f79ddcd465d75654a3e2fb /drivers/video/tegra | |
parent | 31f770700e4b7fc80fae72a670d3d482727887f1 (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.c | 34 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvdla/dla_queue.h | 5 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvdla/nvdla_queue.c | 8 |
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 | ||
53 | struct nvdla_queue_task_pool { | 54 | struct 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 | ||
63 | static int nvdla_queue_task_pool_alloc(struct platform_device *pdev, | 67 | static 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 | ||
101 | err_alloc_task_pool: | 108 | err_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 | |||
24 | struct nvdla_queue_task_pool; | 27 | struct 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; |