summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeepak Nibade <dnibade@nvidia.com>2017-09-15 08:32:09 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-10-13 16:42:01 -0400
commit11d2647af2b38fc5b40db76871d97dcfd0eec833 (patch)
tree4c43fdc6d6c880bd7c708e199afbe26e82175afa
parent00f54f1ae8d0335707a26cca6ef9317ae691635c (diff)
video: tegra: host: enable lazy unmapping on context devices
Since context devices are a limited resource, these devices are dynamically allocated and re-used across multiple processes If lazy unmapping is enabled for context devices, one process can see all the mappings of other process mapped into same context device Hence lazy unmapping was disabled so far. To fix this handle allocation of context devices as following - store a unique prev_identifier into iommu_ctx - iommu_context_dev_allocate() will receive an identifier to compare - if same identifier is stashed into any of the free context device, return that context device since it will have all the mappings stashed - if not, look for a device which does not have prev_identifier set and is clean - if no device is available without prev_identifier, pick any one of the free device but explicitly call dma_buf_release_stash() to remove stashed mappings This ensures that new processes cannot see mappings of old process even if context device is reused. And since this is handled now, enable lazy unmapping on context devices too Bug 1950747 Change-Id: I40bf2e05691ddf1a65646f8706d165c1538db3ae Signed-off-by: Deepak Nibade <dnibade@nvidia.com> Signed-off-by: Pritesh Raithatha <praithatha@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1560847 Reviewed-on: https://git-master.nvidia.com/r/1565250 Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Sachin Nikam <snikam@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
-rw-r--r--drivers/video/tegra/host/chip_support.h2
-rw-r--r--drivers/video/tegra/host/host1x/host1x_vm_t186.c4
-rw-r--r--drivers/video/tegra/host/iommu_context_dev.c51
-rw-r--r--drivers/video/tegra/host/iommu_context_dev.h2
-rw-r--r--drivers/video/tegra/host/nvhost_vm.c2
5 files changed, 51 insertions, 10 deletions
diff --git a/drivers/video/tegra/host/chip_support.h b/drivers/video/tegra/host/chip_support.h
index 23fcf6f39..1fcd53c15 100644
--- a/drivers/video/tegra/host/chip_support.h
+++ b/drivers/video/tegra/host/chip_support.h
@@ -65,7 +65,7 @@ struct nvhost_cdma_ops {
65}; 65};
66 66
67struct nvhost_vm_ops { 67struct nvhost_vm_ops {
68 int (*init)(struct nvhost_vm *vm); 68 int (*init)(struct nvhost_vm *vm, void *identifier);
69 void (*deinit)(struct nvhost_vm *vm); 69 void (*deinit)(struct nvhost_vm *vm);
70 int (*pin_static_buffer)(struct platform_device *pdev, 70 int (*pin_static_buffer)(struct platform_device *pdev,
71 void *vaddr, dma_addr_t paddr, 71 void *vaddr, dma_addr_t paddr,
diff --git a/drivers/video/tegra/host/host1x/host1x_vm_t186.c b/drivers/video/tegra/host/host1x/host1x_vm_t186.c
index 65f0742c6..c198ec84e 100644
--- a/drivers/video/tegra/host/host1x/host1x_vm_t186.c
+++ b/drivers/video/tegra/host/host1x/host1x_vm_t186.c
@@ -27,14 +27,14 @@
27/* 5 second timeout */ 27/* 5 second timeout */
28#define NVHOST_VM_WAIT_TIMEOUT (5000) 28#define NVHOST_VM_WAIT_TIMEOUT (5000)
29 29
30static int host1x_vm_init(struct nvhost_vm *vm) 30static int host1x_vm_init(struct nvhost_vm *vm, void *identifier)
31{ 31{
32 struct platform_device *pdev; 32 struct platform_device *pdev;
33 unsigned int i = 0; 33 unsigned int i = 0;
34 34
35 /* wait until we have a context device */ 35 /* wait until we have a context device */
36 do { 36 do {
37 pdev = iommu_context_dev_allocate(); 37 pdev = iommu_context_dev_allocate(identifier);
38 if (!pdev) { 38 if (!pdev) {
39 ++i; 39 ++i;
40 mdelay(1); 40 mdelay(1);
diff --git a/drivers/video/tegra/host/iommu_context_dev.c b/drivers/video/tegra/host/iommu_context_dev.c
index ead02e9dd..af9de61f3 100644
--- a/drivers/video/tegra/host/iommu_context_dev.c
+++ b/drivers/video/tegra/host/iommu_context_dev.c
@@ -47,24 +47,65 @@ struct iommu_ctx {
47 struct list_head list; 47 struct list_head list;
48 struct device_dma_parameters dma_parms; 48 struct device_dma_parameters dma_parms;
49 bool allocated; 49 bool allocated;
50 void *prev_identifier;
50}; 51};
51 52
52static LIST_HEAD(iommu_ctx_list); 53static LIST_HEAD(iommu_ctx_list);
53static LIST_HEAD(iommu_static_mappings_list); 54static LIST_HEAD(iommu_static_mappings_list);
54static DEFINE_MUTEX(iommu_ctx_list_mutex); 55static DEFINE_MUTEX(iommu_ctx_list_mutex);
55 56
56struct platform_device *iommu_context_dev_allocate(void) 57struct platform_device *iommu_context_dev_allocate(void *identifier)
57{ 58{
58 struct iommu_ctx *ctx; 59 struct iommu_ctx *ctx, *ctx_new = NULL;
60 bool dirty = false;
59 61
60 mutex_lock(&iommu_ctx_list_mutex); 62 mutex_lock(&iommu_ctx_list_mutex);
63 /*
64 * First check if we have same identifier stashed into
65 * some context device
66 * If yes, use that context device since it will have all
67 * the mappings stashed too
68 */
61 list_for_each_entry(ctx, &iommu_ctx_list, list) { 69 list_for_each_entry(ctx, &iommu_ctx_list, list) {
62 if (!ctx->allocated) { 70 if (!ctx->allocated && identifier == ctx->prev_identifier) {
63 ctx->allocated = true; 71 ctx->allocated = true;
64 mutex_unlock(&iommu_ctx_list_mutex); 72 mutex_unlock(&iommu_ctx_list_mutex);
65 return ctx->pdev; 73 return ctx->pdev;
66 } 74 }
67 } 75 }
76
77 /*
78 * Otherwise, find a device which does not have any identifier stashed
79 * If there is no device left without identifier stashed, use any of
80 * the free device and explicitly remove all the stashings from it
81 */
82 list_for_each_entry(ctx, &iommu_ctx_list, list) {
83 if (!ctx->allocated && !ctx_new) {
84 ctx_new = ctx;
85 dirty = true;
86 }
87 if (!ctx->allocated && !ctx->prev_identifier) {
88 ctx_new = ctx;
89 dirty = false;
90 break;
91 }
92 }
93
94 if (ctx_new) {
95 if (dirty) {
96 /*
97 * Ensure that all stashed mappings are removed from this context device
98 * before this context device gets reassigned to some other process
99 */
100 dma_buf_release_stash(&ctx_new->pdev->dev);
101 }
102
103 ctx_new->prev_identifier = identifier;
104 ctx_new->allocated = true;
105 mutex_unlock(&iommu_ctx_list_mutex);
106 return ctx_new->pdev;
107 }
108
68 mutex_unlock(&iommu_ctx_list_mutex); 109 mutex_unlock(&iommu_ctx_list_mutex);
69 110
70 return NULL; 111 return NULL;
@@ -200,8 +241,8 @@ static int iommu_context_dev_probe(struct platform_device *pdev)
200 pdev->dev.dma_parms = &ctx->dma_parms; 241 pdev->dev.dma_parms = &ctx->dma_parms;
201 dma_set_max_seg_size(&pdev->dev, UINT_MAX); 242 dma_set_max_seg_size(&pdev->dev, UINT_MAX);
202 243
203 /* disable lazy unmapping for context devices */ 244 /* flag required to handle stashings in context devices */
204 dma_buf_disable_lazy_unmapping(&pdev->dev); 245 pdev->dev.context_dev = true;
205 246
206 dev_info(&pdev->dev, "initialized (streamid=%d)", 247 dev_info(&pdev->dev, "initialized (streamid=%d)",
207 iommu_get_hwid(pdev->dev.archdata.iommu, &pdev->dev, 0)); 248 iommu_get_hwid(pdev->dev.archdata.iommu, &pdev->dev, 0));
diff --git a/drivers/video/tegra/host/iommu_context_dev.h b/drivers/video/tegra/host/iommu_context_dev.h
index e219265c2..9f0f40519 100644
--- a/drivers/video/tegra/host/iommu_context_dev.h
+++ b/drivers/video/tegra/host/iommu_context_dev.h
@@ -19,7 +19,7 @@
19#ifndef IOMMU_CONTEXT_DEV_H 19#ifndef IOMMU_CONTEXT_DEV_H
20#define IOMMU_CONTEXT_DEV_H 20#define IOMMU_CONTEXT_DEV_H
21 21
22struct platform_device *iommu_context_dev_allocate(void); 22struct platform_device *iommu_context_dev_allocate(void *identifier);
23void iommu_context_dev_release(struct platform_device *pdev); 23void iommu_context_dev_release(struct platform_device *pdev);
24int iommu_context_dev_get_streamid(struct platform_device *pdev); 24int iommu_context_dev_get_streamid(struct platform_device *pdev);
25int iommu_context_dev_map_static(void *vaddr, dma_addr_t paddr, size_t size); 25int iommu_context_dev_map_static(void *vaddr, dma_addr_t paddr, size_t size);
diff --git a/drivers/video/tegra/host/nvhost_vm.c b/drivers/video/tegra/host/nvhost_vm.c
index aaa03eb9b..979bb31fd 100644
--- a/drivers/video/tegra/host/nvhost_vm.c
+++ b/drivers/video/tegra/host/nvhost_vm.c
@@ -224,7 +224,7 @@ struct nvhost_vm *nvhost_vm_allocate(struct platform_device *pdev,
224 mutex_unlock(&host->vm_mutex); 224 mutex_unlock(&host->vm_mutex);
225 225
226 if (vm_op().init && vm->enable_hw) { 226 if (vm_op().init && vm->enable_hw) {
227 err = vm_op().init(vm); 227 err = vm_op().init(vm, identifier);
228 if (err) 228 if (err)
229 goto err_init; 229 goto err_init;
230 } 230 }