diff options
author | Alex Waterman <alexw@nvidia.com> | 2017-08-29 15:59:40 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-09-12 18:54:46 -0400 |
commit | 72f40c211eca854f713530e68f789d4a7c3bb9fa (patch) | |
tree | 5378f6b8103c1ea902077ecfa2a56f6a353589fd /drivers/gpu/nvgpu | |
parent | b79c165fd74f8269000f33691d8a480359e71585 (diff) |
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>
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/dma.c | 27 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/nvgpu_mem.h | 1 |
3 files changed, 22 insertions, 8 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/dma.c b/drivers/gpu/nvgpu/common/linux/dma.c index cd6ad1b2..13c1c347 100644 --- a/drivers/gpu/nvgpu/common/linux/dma.c +++ b/drivers/gpu/nvgpu/common/linux/dma.c | |||
@@ -112,6 +112,13 @@ int nvgpu_dma_alloc_flags_sys(struct gk20a *g, unsigned long flags, | |||
112 | 112 | ||
113 | gk20a_dbg_fn(""); | 113 | gk20a_dbg_fn(""); |
114 | 114 | ||
115 | /* | ||
116 | * Save the old size but for actual allocation purposes the size is | ||
117 | * going to be page aligned. | ||
118 | */ | ||
119 | mem->size = size; | ||
120 | size = PAGE_ALIGN(size); | ||
121 | |||
115 | if (flags) { | 122 | if (flags) { |
116 | DEFINE_DMA_ATTRS(dma_attrs); | 123 | DEFINE_DMA_ATTRS(dma_attrs); |
117 | 124 | ||
@@ -148,7 +155,7 @@ int nvgpu_dma_alloc_flags_sys(struct gk20a *g, unsigned long flags, | |||
148 | if (err) | 155 | if (err) |
149 | goto fail_free; | 156 | goto fail_free; |
150 | 157 | ||
151 | mem->size = size; | 158 | mem->aligned_size = size; |
152 | mem->aperture = APERTURE_SYSMEM; | 159 | mem->aperture = APERTURE_SYSMEM; |
153 | mem->priv.flags = flags; | 160 | mem->priv.flags = flags; |
154 | 161 | ||
@@ -188,6 +195,9 @@ int nvgpu_dma_alloc_flags_vid_at(struct gk20a *g, unsigned long flags, | |||
188 | 195 | ||
189 | gk20a_dbg_fn(""); | 196 | gk20a_dbg_fn(""); |
190 | 197 | ||
198 | mem->size = size; | ||
199 | size = PAGE_ALIGN(size); | ||
200 | |||
191 | if (!nvgpu_alloc_initialized(&g->mm.vidmem.allocator)) | 201 | if (!nvgpu_alloc_initialized(&g->mm.vidmem.allocator)) |
192 | return -ENOSYS; | 202 | return -ENOSYS; |
193 | 203 | ||
@@ -228,7 +238,7 @@ int nvgpu_dma_alloc_flags_vid_at(struct gk20a *g, unsigned long flags, | |||
228 | set_vidmem_page_alloc(mem->priv.sgt->sgl, addr); | 238 | set_vidmem_page_alloc(mem->priv.sgt->sgl, addr); |
229 | sg_set_page(mem->priv.sgt->sgl, NULL, size, 0); | 239 | sg_set_page(mem->priv.sgt->sgl, NULL, size, 0); |
230 | 240 | ||
231 | mem->size = size; | 241 | mem->aligned_size = size; |
232 | mem->aperture = APERTURE_VIDMEM; | 242 | mem->aperture = APERTURE_VIDMEM; |
233 | mem->allocator = vidmem_alloc; | 243 | mem->allocator = vidmem_alloc; |
234 | mem->priv.flags = flags; | 244 | mem->priv.flags = flags; |
@@ -352,16 +362,16 @@ static void nvgpu_dma_free_sys(struct gk20a *g, struct nvgpu_mem *mem) | |||
352 | nvgpu_dma_flags_to_attrs(&dma_attrs, mem->priv.flags); | 362 | nvgpu_dma_flags_to_attrs(&dma_attrs, mem->priv.flags); |
353 | 363 | ||
354 | if (mem->priv.flags & NVGPU_DMA_NO_KERNEL_MAPPING) { | 364 | if (mem->priv.flags & NVGPU_DMA_NO_KERNEL_MAPPING) { |
355 | dma_free_attrs(d, mem->size, mem->priv.pages, | 365 | dma_free_attrs(d, mem->aligned_size, mem->priv.pages, |
356 | sg_dma_address(mem->priv.sgt->sgl), | 366 | sg_dma_address(mem->priv.sgt->sgl), |
357 | __DMA_ATTR(dma_attrs)); | 367 | __DMA_ATTR(dma_attrs)); |
358 | } else { | 368 | } else { |
359 | dma_free_attrs(d, mem->size, mem->cpu_va, | 369 | dma_free_attrs(d, mem->aligned_size, mem->cpu_va, |
360 | sg_dma_address(mem->priv.sgt->sgl), | 370 | sg_dma_address(mem->priv.sgt->sgl), |
361 | __DMA_ATTR(dma_attrs)); | 371 | __DMA_ATTR(dma_attrs)); |
362 | } | 372 | } |
363 | } else { | 373 | } else { |
364 | dma_free_coherent(d, mem->size, mem->cpu_va, | 374 | dma_free_coherent(d, mem->aligned_size, mem->cpu_va, |
365 | sg_dma_address(mem->priv.sgt->sgl)); | 375 | sg_dma_address(mem->priv.sgt->sgl)); |
366 | } | 376 | } |
367 | mem->cpu_va = NULL; | 377 | mem->cpu_va = NULL; |
@@ -379,6 +389,7 @@ static void nvgpu_dma_free_sys(struct gk20a *g, struct nvgpu_mem *mem) | |||
379 | nvgpu_free_sgtable(g, &mem->priv.sgt); | 389 | nvgpu_free_sgtable(g, &mem->priv.sgt); |
380 | 390 | ||
381 | mem->size = 0; | 391 | mem->size = 0; |
392 | mem->aligned_size = 0; | ||
382 | mem->aperture = APERTURE_INVALID; | 393 | mem->aperture = APERTURE_INVALID; |
383 | } | 394 | } |
384 | 395 | ||
@@ -395,7 +406,8 @@ static void nvgpu_dma_free_vid(struct gk20a *g, struct nvgpu_mem *mem) | |||
395 | was_empty = nvgpu_list_empty(&g->mm.vidmem.clear_list_head); | 406 | was_empty = nvgpu_list_empty(&g->mm.vidmem.clear_list_head); |
396 | nvgpu_list_add_tail(&mem->clear_list_entry, | 407 | nvgpu_list_add_tail(&mem->clear_list_entry, |
397 | &g->mm.vidmem.clear_list_head); | 408 | &g->mm.vidmem.clear_list_head); |
398 | atomic64_add(mem->size, &g->mm.vidmem.bytes_pending.atomic_var); | 409 | atomic64_add(mem->aligned_size, |
410 | &g->mm.vidmem.bytes_pending.atomic_var); | ||
399 | nvgpu_mutex_release(&g->mm.vidmem.clear_list_mutex); | 411 | nvgpu_mutex_release(&g->mm.vidmem.clear_list_mutex); |
400 | 412 | ||
401 | if (was_empty) { | 413 | if (was_empty) { |
@@ -403,12 +415,13 @@ static void nvgpu_dma_free_vid(struct gk20a *g, struct nvgpu_mem *mem) | |||
403 | schedule_work(&g->mm.vidmem.clear_mem_worker); | 415 | schedule_work(&g->mm.vidmem.clear_mem_worker); |
404 | } | 416 | } |
405 | } else { | 417 | } else { |
406 | nvgpu_memset(g, mem, 0, 0, mem->size); | 418 | nvgpu_memset(g, mem, 0, 0, mem->aligned_size); |
407 | nvgpu_free(mem->allocator, | 419 | nvgpu_free(mem->allocator, |
408 | (u64)get_vidmem_page_alloc(mem->priv.sgt->sgl)); | 420 | (u64)get_vidmem_page_alloc(mem->priv.sgt->sgl)); |
409 | nvgpu_free_sgtable(g, &mem->priv.sgt); | 421 | nvgpu_free_sgtable(g, &mem->priv.sgt); |
410 | 422 | ||
411 | mem->size = 0; | 423 | mem->size = 0; |
424 | mem->aligned_size = 0; | ||
412 | mem->aperture = APERTURE_INVALID; | 425 | mem->aperture = APERTURE_INVALID; |
413 | } | 426 | } |
414 | #endif | 427 | #endif |
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c index 2d69a2aa..a6507d2d 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c | |||
@@ -1207,7 +1207,7 @@ static void gk20a_vidmem_clear_mem_worker(struct work_struct *work) | |||
1207 | (u64)get_vidmem_page_alloc(mem->priv.sgt->sgl)); | 1207 | (u64)get_vidmem_page_alloc(mem->priv.sgt->sgl)); |
1208 | nvgpu_free_sgtable(g, &mem->priv.sgt); | 1208 | nvgpu_free_sgtable(g, &mem->priv.sgt); |
1209 | 1209 | ||
1210 | WARN_ON(nvgpu_atomic64_sub_return(mem->size, | 1210 | WARN_ON(nvgpu_atomic64_sub_return(mem->aligned_size, |
1211 | &g->mm.vidmem.bytes_pending) < 0); | 1211 | &g->mm.vidmem.bytes_pending) < 0); |
1212 | mem->size = 0; | 1212 | mem->size = 0; |
1213 | mem->aperture = APERTURE_INVALID; | 1213 | mem->aperture = APERTURE_INVALID; |
diff --git a/drivers/gpu/nvgpu/include/nvgpu/nvgpu_mem.h b/drivers/gpu/nvgpu/include/nvgpu/nvgpu_mem.h index 5aa09f3d..f3be65c2 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/nvgpu_mem.h +++ b/drivers/gpu/nvgpu/include/nvgpu/nvgpu_mem.h | |||
@@ -50,6 +50,7 @@ struct nvgpu_mem { | |||
50 | */ | 50 | */ |
51 | enum nvgpu_aperture aperture; | 51 | enum nvgpu_aperture aperture; |
52 | size_t size; | 52 | size_t size; |
53 | size_t aligned_size; | ||
53 | u64 gpu_va; | 54 | u64 gpu_va; |
54 | bool skip_wmb; | 55 | bool skip_wmb; |
55 | 56 | ||