video: tegra: nvmap: Restore handle size

NvRmMemHandleAllocAttr can be called with multiple input heaps, if
allocation from first heap fails, then allocation from next heap is
attempted and so on. In case of GPU carveout, the handle size is aligned
to next 2MB while for other heaps, it is aligned to 4KB. If the user
provides an array of heaps, where first one is GPU carveout, then the
handle size is aligned to 2MB and then if the enough memory is not
available in GPU carveout the allocation call fails, but the handle size
is not restored back to 4KB aligned size. So the next allocation attempt
from the second heap would request for incorrect buffer size. Correct
this behavior by restoring the handle size back to 4KB aligned size, if
allocation from GPU carveout fails.

Bug 4661684

Change-Id: I6d93eb96b21e384554df888d9819dcfc2f3565fa
Signed-off-by: Ketan Patil <ketanp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3159925
Reviewed-by: Pritesh Raithatha <praithatha@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Ashish Mhetre <amhetre@nvidia.com>
This commit is contained in:
Ketan Patil
2024-06-11 14:21:19 +00:00
committed by mobile promotions
parent caeb9cd1b8
commit a163533e77

View File

@@ -200,6 +200,7 @@ int nvmap_ioctl_alloc(struct file *filp, void __user *arg)
int err, i; int err, i;
unsigned int page_sz = PAGE_SIZE; unsigned int page_sz = PAGE_SIZE;
long dmabuf_ref = 0; long dmabuf_ref = 0;
size_t old_size;
if (copy_from_user(&op, arg, sizeof(op))) if (copy_from_user(&op, arg, sizeof(op)))
return -EFAULT; return -EFAULT;
@@ -219,6 +220,7 @@ int nvmap_ioctl_alloc(struct file *filp, void __user *arg)
if (IS_ERR_OR_NULL(handle)) if (IS_ERR_OR_NULL(handle))
return -EINVAL; return -EINVAL;
old_size = handle->size;
/* /*
* In case of Gpu carveout, the handle size needs to be aligned to granule. * In case of Gpu carveout, the handle size needs to be aligned to granule.
*/ */
@@ -233,6 +235,7 @@ int nvmap_ioctl_alloc(struct file *filp, void __user *arg)
} }
if (!is_nvmap_memory_available(handle->size, op.heap_mask, op.numa_nid)) { if (!is_nvmap_memory_available(handle->size, op.heap_mask, op.numa_nid)) {
handle->size = old_size;
nvmap_handle_put(handle); nvmap_handle_put(handle);
return -ENOMEM; return -ENOMEM;
} }
@@ -261,6 +264,9 @@ int nvmap_ioctl_alloc(struct file *filp, void __user *arg)
dmabuf_ref, dmabuf_ref,
is_ro ? "RO" : "RW"); is_ro ? "RO" : "RW");
} }
if (err)
handle->size = old_size;
nvmap_handle_put(handle); nvmap_handle_put(handle);
return err; return err;
} }