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 <ketanp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2839848
Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com>
Reviewed-by: Ashish Mhetre <amhetre@nvidia.com>
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
Ketan Patil
2023-01-09 09:14:32 +00:00
committed by Laxman Dewangan
parent e3a44ab6e8
commit a588f61b8e

View File

@@ -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);
}