gpu: nvgpu: page align DMA allocs

Explicitly page align DMA memory allocations. Non-page aligned
DMA allocs can lead to nvgpu_mem structs that have a size that's
not page aligned. Those allocs, in some cases, can cause vGPU
maps to return an error.

More generally DMA allocs in Linux are never going to not be
page aligned both in size and address. So might as well page align
the alloc size to make code else where in the driver more simple.

To imlpement this an aligned_size field has been added to struct
nvgpu_mem. This field has the real page aligned size of the
allocation. The original size is still saved in size.

Change-Id: Ie08cfc4f39d5f97db84a54b8e314ad1fa53b72be
Signed-off-by: Alex Waterman <alexw@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1547902
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
This commit is contained in:
Alex Waterman
2017-08-29 12:59:40 -07:00
committed by mobile promotions
parent b79c165fd7
commit 72f40c211e
3 changed files with 22 additions and 8 deletions

View File

@@ -112,6 +112,13 @@ int nvgpu_dma_alloc_flags_sys(struct gk20a *g, unsigned long flags,
gk20a_dbg_fn("");
/*
* Save the old size but for actual allocation purposes the size is
* going to be page aligned.
*/
mem->size = size;
size = PAGE_ALIGN(size);
if (flags) {
DEFINE_DMA_ATTRS(dma_attrs);
@@ -148,7 +155,7 @@ int nvgpu_dma_alloc_flags_sys(struct gk20a *g, unsigned long flags,
if (err)
goto fail_free;
mem->size = size;
mem->aligned_size = size;
mem->aperture = APERTURE_SYSMEM;
mem->priv.flags = flags;
@@ -188,6 +195,9 @@ int nvgpu_dma_alloc_flags_vid_at(struct gk20a *g, unsigned long flags,
gk20a_dbg_fn("");
mem->size = size;
size = PAGE_ALIGN(size);
if (!nvgpu_alloc_initialized(&g->mm.vidmem.allocator))
return -ENOSYS;
@@ -228,7 +238,7 @@ int nvgpu_dma_alloc_flags_vid_at(struct gk20a *g, unsigned long flags,
set_vidmem_page_alloc(mem->priv.sgt->sgl, addr);
sg_set_page(mem->priv.sgt->sgl, NULL, size, 0);
mem->size = size;
mem->aligned_size = size;
mem->aperture = APERTURE_VIDMEM;
mem->allocator = vidmem_alloc;
mem->priv.flags = flags;
@@ -352,16 +362,16 @@ static void nvgpu_dma_free_sys(struct gk20a *g, struct nvgpu_mem *mem)
nvgpu_dma_flags_to_attrs(&dma_attrs, mem->priv.flags);
if (mem->priv.flags & NVGPU_DMA_NO_KERNEL_MAPPING) {
dma_free_attrs(d, mem->size, mem->priv.pages,
dma_free_attrs(d, mem->aligned_size, mem->priv.pages,
sg_dma_address(mem->priv.sgt->sgl),
__DMA_ATTR(dma_attrs));
} else {
dma_free_attrs(d, mem->size, mem->cpu_va,
dma_free_attrs(d, mem->aligned_size, mem->cpu_va,
sg_dma_address(mem->priv.sgt->sgl),
__DMA_ATTR(dma_attrs));
}
} else {
dma_free_coherent(d, mem->size, mem->cpu_va,
dma_free_coherent(d, mem->aligned_size, mem->cpu_va,
sg_dma_address(mem->priv.sgt->sgl));
}
mem->cpu_va = NULL;
@@ -379,6 +389,7 @@ static void nvgpu_dma_free_sys(struct gk20a *g, struct nvgpu_mem *mem)
nvgpu_free_sgtable(g, &mem->priv.sgt);
mem->size = 0;
mem->aligned_size = 0;
mem->aperture = APERTURE_INVALID;
}
@@ -395,7 +406,8 @@ static void nvgpu_dma_free_vid(struct gk20a *g, struct nvgpu_mem *mem)
was_empty = nvgpu_list_empty(&g->mm.vidmem.clear_list_head);
nvgpu_list_add_tail(&mem->clear_list_entry,
&g->mm.vidmem.clear_list_head);
atomic64_add(mem->size, &g->mm.vidmem.bytes_pending.atomic_var);
atomic64_add(mem->aligned_size,
&g->mm.vidmem.bytes_pending.atomic_var);
nvgpu_mutex_release(&g->mm.vidmem.clear_list_mutex);
if (was_empty) {
@@ -403,12 +415,13 @@ static void nvgpu_dma_free_vid(struct gk20a *g, struct nvgpu_mem *mem)
schedule_work(&g->mm.vidmem.clear_mem_worker);
}
} else {
nvgpu_memset(g, mem, 0, 0, mem->size);
nvgpu_memset(g, mem, 0, 0, mem->aligned_size);
nvgpu_free(mem->allocator,
(u64)get_vidmem_page_alloc(mem->priv.sgt->sgl));
nvgpu_free_sgtable(g, &mem->priv.sgt);
mem->size = 0;
mem->aligned_size = 0;
mem->aperture = APERTURE_INVALID;
}
#endif

View File

@@ -1207,7 +1207,7 @@ static void gk20a_vidmem_clear_mem_worker(struct work_struct *work)
(u64)get_vidmem_page_alloc(mem->priv.sgt->sgl));
nvgpu_free_sgtable(g, &mem->priv.sgt);
WARN_ON(nvgpu_atomic64_sub_return(mem->size,
WARN_ON(nvgpu_atomic64_sub_return(mem->aligned_size,
&g->mm.vidmem.bytes_pending) < 0);
mem->size = 0;
mem->aperture = APERTURE_INVALID;

View File

@@ -50,6 +50,7 @@ struct nvgpu_mem {
*/
enum nvgpu_aperture aperture;
size_t size;
size_t aligned_size;
u64 gpu_va;
bool skip_wmb;