summaryrefslogtreecommitdiffstats
path: root/drivers/video/tegra
diff options
context:
space:
mode:
authorSagar Kamble <skamble@nvidia.com>2020-10-10 00:04:13 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2021-05-10 23:40:10 -0400
commit24a08ffaf92b57699e8cb90880eb94b14a0429f5 (patch)
tree5a841d5593b62362b0075604d55319f9ae93b49b /drivers/video/tegra
parenta3c08fdbdb3508ac4895fd159aaabff576fdcd14 (diff)
video: tegra: nvmap: export dma_buf as RO when NVMAP_HANDLE_RO is set
Following kernel BUG is encountered when closing the file whose mode is overridden to RO throgh fmode field as inode->i_readcount is not initialized for the file. This is seen when running the test NvRmGpuTest_Channel_SimplestPb_RoMappedBuffer_From_CPUVA on K5.9. The correct way to set the file mode as RO is to export the dma_buf as RO that will initialize inode->i_readcount properly. [ 1228.027800] kernel BUG at kernel/kernel-5.9/include/linux/fs.h:2842! [ 1228.035330] Internal error: Oops - BUG: 0 [#3] PREEMPT SMP [ 1228.115034] Hardware name: Jetson-AGX (DT) [ 1228.119234] pstate: 60400009 (nZCv daif +PAN -UAO BTYPE=--) [ 1228.125023] pc : __fput+0x22c/0x230 [ 1228.128690] lr : __fput+0xa4/0x230 [ 1228.216800] Call trace: [ 1228.219258] __fput+0x22c/0x230 [ 1228.222407] ____fput+0x20/0x30 [ 1228.225388] task_work_run+0x88/0x140 [ 1228.228886] do_notify_resume+0x204/0x868 [ 1228.233080] work_pending+0x8/0x204 [ 1228.236583] Code: 17ffff8e aa1703e0 9400b26f 17ffffa6 (d4210000) [ 1228.242702] ---[ end trace af706a6663eb46e5 ]--- [ 1228.247252] note: nvrm_gpu_tests[1156] exited with preempt_count 1 Bug 200660013 Change-Id: Ie238f59a46aa7b016249a01e39e7bbd73ecfab02 Signed-off-by: Sagar Kamble <skamble@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2515024 (cherry picked from commit 891dc46b2e85424fc81544a83d6752eb1ea57dae) Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2521315 Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: Puneet Saxena <puneets@nvidia.com> Reviewed-by: Bibek Basu <bbasu@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: Amulya Yarlagadda <ayarlagadda@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/nvmap/nvmap_dmabuf.c20
-rw-r--r--drivers/video/tegra/nvmap/nvmap_handle.c6
-rw-r--r--drivers/video/tegra/nvmap/nvmap_ioctl.c4
-rw-r--r--drivers/video/tegra/nvmap/nvmap_priv.h4
4 files changed, 17 insertions, 17 deletions
diff --git a/drivers/video/tegra/nvmap/nvmap_dmabuf.c b/drivers/video/tegra/nvmap/nvmap_dmabuf.c
index 3424bb7f8..54f514546 100644
--- a/drivers/video/tegra/nvmap/nvmap_dmabuf.c
+++ b/drivers/video/tegra/nvmap/nvmap_dmabuf.c
@@ -607,14 +607,20 @@ EXPORT_SYMBOL(dmabuf_is_nvmap);
607 607
608#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) 608#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)
609static struct dma_buf *__dma_buf_export(struct nvmap_handle_info *info, 609static struct dma_buf *__dma_buf_export(struct nvmap_handle_info *info,
610 size_t size) 610 size_t size, bool ro_buf)
611{ 611{
612 DEFINE_DMA_BUF_EXPORT_INFO(exp_info); 612 DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
613 613
614 exp_info.priv = info; 614 exp_info.priv = info;
615 exp_info.ops = &nvmap_dma_buf_ops; 615 exp_info.ops = &nvmap_dma_buf_ops;
616 exp_info.size = size; 616 exp_info.size = size;
617 exp_info.flags = O_RDWR; 617
618 if (ro_buf) {
619 exp_info.flags = O_RDONLY;
620 } else {
621 exp_info.flags = O_RDWR;
622 }
623
618 exp_info.exp_flags = DMABUF_CAN_DEFER_UNMAP | 624 exp_info.exp_flags = DMABUF_CAN_DEFER_UNMAP |
619 DMABUF_SKIP_CACHE_SYNC; 625 DMABUF_SKIP_CACHE_SYNC;
620 626
@@ -629,7 +635,7 @@ static struct dma_buf *__dma_buf_export(struct nvmap_handle_info *info,
629 * Make a dmabuf object for an nvmap handle. 635 * Make a dmabuf object for an nvmap handle.
630 */ 636 */
631struct dma_buf *__nvmap_make_dmabuf(struct nvmap_client *client, 637struct dma_buf *__nvmap_make_dmabuf(struct nvmap_client *client,
632 struct nvmap_handle *handle) 638 struct nvmap_handle *handle, bool ro_buf)
633{ 639{
634 int err; 640 int err;
635 struct dma_buf *dmabuf; 641 struct dma_buf *dmabuf;
@@ -644,7 +650,7 @@ struct dma_buf *__nvmap_make_dmabuf(struct nvmap_client *client,
644 INIT_LIST_HEAD(&info->maps); 650 INIT_LIST_HEAD(&info->maps);
645 mutex_init(&info->maps_lock); 651 mutex_init(&info->maps_lock);
646 652
647 dmabuf = __dma_buf_export(info, handle->size); 653 dmabuf = __dma_buf_export(info, handle->size, ro_buf);
648 if (IS_ERR(dmabuf)) { 654 if (IS_ERR(dmabuf)) {
649 err = PTR_ERR(dmabuf); 655 err = PTR_ERR(dmabuf);
650 goto err_export; 656 goto err_export;
@@ -689,12 +695,6 @@ int nvmap_get_dmabuf_fd(struct nvmap_client *client, struct nvmap_handle *h)
689 dmabuf = __nvmap_dmabuf_export(client, h); 695 dmabuf = __nvmap_dmabuf_export(client, h);
690 if (IS_ERR(dmabuf)) 696 if (IS_ERR(dmabuf))
691 return PTR_ERR(dmabuf); 697 return PTR_ERR(dmabuf);
692 /*
693 * If the user allocated buffer is ReadOnly, make
694 * dma_buf ReadOnly.
695 */
696 if (h->is_ro)
697 dmabuf->file->f_mode &= ~(FMODE_WRITE | FMODE_PWRITE);
698 698
699 fd = __nvmap_dmabuf_fd(client, dmabuf, O_CLOEXEC); 699 fd = __nvmap_dmabuf_fd(client, dmabuf, O_CLOEXEC);
700 if (IS_ERR_VALUE((uintptr_t)fd)) 700 if (IS_ERR_VALUE((uintptr_t)fd))
diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c
index 8df4b3a71..7a58f1c68 100644
--- a/drivers/video/tegra/nvmap/nvmap_handle.c
+++ b/drivers/video/tegra/nvmap/nvmap_handle.c
@@ -186,7 +186,7 @@ struct nvmap_handle_ref *nvmap_create_handle_from_va(struct nvmap_client *client
186 if (!(vm_flags & VM_WRITE) && !(flags & NVMAP_HANDLE_RO)) 186 if (!(vm_flags & VM_WRITE) && !(flags & NVMAP_HANDLE_RO))
187 return ERR_PTR(-EINVAL); 187 return ERR_PTR(-EINVAL);
188 188
189 ref = nvmap_create_handle(client, size); 189 ref = nvmap_create_handle(client, size, flags & NVMAP_HANDLE_RO);
190 if (!IS_ERR(ref)) 190 if (!IS_ERR(ref))
191 ref->handle->orig_size = size; 191 ref->handle->orig_size = size;
192 192
@@ -194,7 +194,7 @@ struct nvmap_handle_ref *nvmap_create_handle_from_va(struct nvmap_client *client
194} 194}
195 195
196struct nvmap_handle_ref *nvmap_create_handle(struct nvmap_client *client, 196struct nvmap_handle_ref *nvmap_create_handle(struct nvmap_client *client,
197 size_t size) 197 size_t size, bool ro_buf)
198{ 198{
199 void *err = ERR_PTR(-ENOMEM); 199 void *err = ERR_PTR(-ENOMEM);
200 struct nvmap_handle *h; 200 struct nvmap_handle *h;
@@ -231,7 +231,7 @@ struct nvmap_handle_ref *nvmap_create_handle(struct nvmap_client *client,
231 * This takes out 1 ref on the dambuf. This corresponds to the 231 * This takes out 1 ref on the dambuf. This corresponds to the
232 * handle_ref that gets automatically made by nvmap_create_handle(). 232 * handle_ref that gets automatically made by nvmap_create_handle().
233 */ 233 */
234 h->dmabuf = __nvmap_make_dmabuf(client, h); 234 h->dmabuf = __nvmap_make_dmabuf(client, h, ro_buf);
235 if (IS_ERR(h->dmabuf)) { 235 if (IS_ERR(h->dmabuf)) {
236 err = h->dmabuf; 236 err = h->dmabuf;
237 goto make_dmabuf_fail; 237 goto make_dmabuf_fail;
diff --git a/drivers/video/tegra/nvmap/nvmap_ioctl.c b/drivers/video/tegra/nvmap/nvmap_ioctl.c
index e67077768..a6a29b9e0 100644
--- a/drivers/video/tegra/nvmap/nvmap_ioctl.c
+++ b/drivers/video/tegra/nvmap/nvmap_ioctl.c
@@ -223,7 +223,7 @@ int nvmap_ioctl_create(struct file *filp, unsigned int cmd, void __user *arg)
223 op.size64 = op.size; 223 op.size64 = op.size;
224 224
225 if ((cmd == NVMAP_IOC_CREATE) || (cmd == NVMAP_IOC_CREATE_64)) { 225 if ((cmd == NVMAP_IOC_CREATE) || (cmd == NVMAP_IOC_CREATE_64)) {
226 ref = nvmap_create_handle(client, op.size64); 226 ref = nvmap_create_handle(client, op.size64, false);
227 if (!IS_ERR(ref)) 227 if (!IS_ERR(ref))
228 ref->handle->orig_size = op.size64; 228 ref->handle->orig_size = op.size64;
229 } else if (cmd == NVMAP_IOC_FROM_FD) { 229 } else if (cmd == NVMAP_IOC_FROM_FD) {
@@ -632,7 +632,7 @@ int nvmap_ioctl_create_from_ivc(struct file *filp, void __user *arg)
632 ((1ULL << NVMAP_IVM_LENGTH_WIDTH) - 1)) << PAGE_SHIFT; 632 ((1ULL << NVMAP_IVM_LENGTH_WIDTH) - 1)) << PAGE_SHIFT;
633 peer = (op.ivm_id >> NVMAP_IVM_IVMID_SHIFT); 633 peer = (op.ivm_id >> NVMAP_IVM_IVMID_SHIFT);
634 634
635 ref = nvmap_create_handle(client, size); 635 ref = nvmap_create_handle(client, size, false);
636 if (IS_ERR(ref)) { 636 if (IS_ERR(ref)) {
637 nvmap_heap_free(block); 637 nvmap_heap_free(block);
638 return PTR_ERR(ref); 638 return PTR_ERR(ref);
diff --git a/drivers/video/tegra/nvmap/nvmap_priv.h b/drivers/video/tegra/nvmap/nvmap_priv.h
index 1e7b01f1f..0d6ea52f1 100644
--- a/drivers/video/tegra/nvmap/nvmap_priv.h
+++ b/drivers/video/tegra/nvmap/nvmap_priv.h
@@ -382,7 +382,7 @@ struct nvmap_handle_ref *__nvmap_validate_locked(struct nvmap_client *priv,
382struct nvmap_handle *nvmap_validate_get(struct nvmap_handle *h); 382struct nvmap_handle *nvmap_validate_get(struct nvmap_handle *h);
383 383
384struct nvmap_handle_ref *nvmap_create_handle(struct nvmap_client *client, 384struct nvmap_handle_ref *nvmap_create_handle(struct nvmap_client *client,
385 size_t size); 385 size_t size, bool ro_buf);
386 386
387struct nvmap_handle_ref *nvmap_create_handle_from_va(struct nvmap_client *client, 387struct nvmap_handle_ref *nvmap_create_handle_from_va(struct nvmap_client *client,
388 ulong addr, size_t size, 388 ulong addr, size_t size,
@@ -468,7 +468,7 @@ int nvmap_cache_debugfs_init(struct dentry *nvmap_root);
468struct dma_buf *__nvmap_dmabuf_export(struct nvmap_client *client, 468struct dma_buf *__nvmap_dmabuf_export(struct nvmap_client *client,
469 struct nvmap_handle *handle); 469 struct nvmap_handle *handle);
470struct dma_buf *__nvmap_make_dmabuf(struct nvmap_client *client, 470struct dma_buf *__nvmap_make_dmabuf(struct nvmap_client *client,
471 struct nvmap_handle *handle); 471 struct nvmap_handle *handle, bool ro_buf);
472struct sg_table *__nvmap_sg_table(struct nvmap_client *client, 472struct sg_table *__nvmap_sg_table(struct nvmap_client *client,
473 struct nvmap_handle *h); 473 struct nvmap_handle *h);
474void __nvmap_free_sg_table(struct nvmap_client *client, 474void __nvmap_free_sg_table(struct nvmap_client *client,