From a588f61b8e6bf7a3180685cffc1beb5f00dac4ce Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Mon, 9 Jan 2023 09:14:32 +0000 Subject: [PATCH] video: tegra: nvmap: Remove use of bitmap_allocate_region NvMap is using bitmap_allocate_region while doing allocation from IVM carveout. It expects size to be always power of 2, this is resulting into memory shortage. Better way to handle this is to use the function bitmap_find_next_zero_area which expects bitmap size rather than order. Then use bitmap_set to set the allocated bits from the bitmap. Similarly, while freeing the buffer, use bitmap_clear instead of bitmap_release_region. Bug 3923812 Change-Id: I91005d16f678405f341c4fc620509f56af538e1c Signed-off-by: Ketan Patil Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2839848 Reviewed-by: svc_kernel_abi Reviewed-by: Ashish Mhetre Reviewed-by: Sachin Nikam GVS: Gerrit_Virtual_Submit --- drivers/video/tegra/nvmap/nvmap_init.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/video/tegra/nvmap/nvmap_init.c b/drivers/video/tegra/nvmap/nvmap_init.c index 1303f894..25211dd9 100644 --- a/drivers/video/tegra/nvmap/nvmap_init.c +++ b/drivers/video/tegra/nvmap/nvmap_init.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2022, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -528,8 +528,9 @@ void *nvmap_dma_mark_declared_memory_occupied(struct device *dev, dma_addr_t device_addr, size_t size) { struct dma_coherent_mem_replica *mem; - unsigned long flags; - int pos, err; + unsigned long flags, pageno; + unsigned int alloc_size; + int pos; if (!dev || !dev->dma_mem) return ERR_PTR(-EINVAL); @@ -537,15 +538,20 @@ void *nvmap_dma_mark_declared_memory_occupied(struct device *dev, mem = (struct dma_coherent_mem_replica *)(dev->dma_mem); size += device_addr & ~PAGE_MASK; + alloc_size = PAGE_ALIGN(size) >> PAGE_SHIFT; spin_lock_irqsave(&mem->spinlock, flags); pos = PFN_DOWN(device_addr - mem->device_base); - err = bitmap_allocate_region(mem->bitmap, pos, get_order(size)); + pageno = bitmap_find_next_zero_area(mem->bitmap, mem->size, pos, alloc_size, 0); + if (pageno >= mem->size) + goto error; + bitmap_set(mem->bitmap, pageno, alloc_size); spin_unlock_irqrestore(&mem->spinlock, flags); - - if (err != 0) - return ERR_PTR(err); return mem->virt_base + (pos << PAGE_SHIFT); + +error: + spin_unlock_irqrestore(&mem->spinlock, flags); + return ERR_PTR(-ENOMEM); } void nvmap_dma_mark_declared_memory_unoccupied(struct device *dev, @@ -553,6 +559,7 @@ void nvmap_dma_mark_declared_memory_unoccupied(struct device *dev, { struct dma_coherent_mem_replica *mem; unsigned long flags; + unsigned int alloc_size; int pos; if (!dev || !dev->dma_mem) @@ -561,10 +568,11 @@ void nvmap_dma_mark_declared_memory_unoccupied(struct device *dev, mem = (struct dma_coherent_mem_replica *)(dev->dma_mem); size += device_addr & ~PAGE_MASK; + alloc_size = PAGE_ALIGN(size) >> PAGE_SHIFT; spin_lock_irqsave(&mem->spinlock, flags); pos = PFN_DOWN(device_addr - mem->device_base); - bitmap_release_region(mem->bitmap, pos, get_order(size)); + bitmap_clear(mem->bitmap, pos, alloc_size); spin_unlock_irqrestore(&mem->spinlock, flags); }