diff options
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/nvgpu_mem.c | 19 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/vm.c | 71 |
2 files changed, 23 insertions, 67 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/nvgpu_mem.c b/drivers/gpu/nvgpu/common/linux/nvgpu_mem.c index 1dbbd1a0..2587d56a 100644 --- a/drivers/gpu/nvgpu/common/linux/nvgpu_mem.c +++ b/drivers/gpu/nvgpu/common/linux/nvgpu_mem.c | |||
@@ -529,6 +529,12 @@ static u64 nvgpu_mem_linux_sgl_gpu_addr(struct gk20a *g, void *sgl, | |||
529 | sg_dma_address((struct scatterlist *)sgl)); | 529 | sg_dma_address((struct scatterlist *)sgl)); |
530 | } | 530 | } |
531 | 531 | ||
532 | static bool nvgpu_mem_linux_sgt_iommuable(struct gk20a *g, | ||
533 | struct nvgpu_sgt *sgt) | ||
534 | { | ||
535 | return true; | ||
536 | } | ||
537 | |||
532 | static void nvgpu_mem_linux_sgl_free(struct gk20a *g, struct nvgpu_sgt *sgt) | 538 | static void nvgpu_mem_linux_sgl_free(struct gk20a *g, struct nvgpu_sgt *sgt) |
533 | { | 539 | { |
534 | /* | 540 | /* |
@@ -539,12 +545,13 @@ static void nvgpu_mem_linux_sgl_free(struct gk20a *g, struct nvgpu_sgt *sgt) | |||
539 | } | 545 | } |
540 | 546 | ||
541 | static const struct nvgpu_sgt_ops nvgpu_linux_sgt_ops = { | 547 | static const struct nvgpu_sgt_ops nvgpu_linux_sgt_ops = { |
542 | .sgl_next = nvgpu_mem_linux_sgl_next, | 548 | .sgl_next = nvgpu_mem_linux_sgl_next, |
543 | .sgl_phys = nvgpu_mem_linux_sgl_phys, | 549 | .sgl_phys = nvgpu_mem_linux_sgl_phys, |
544 | .sgl_dma = nvgpu_mem_linux_sgl_dma, | 550 | .sgl_dma = nvgpu_mem_linux_sgl_dma, |
545 | .sgl_length = nvgpu_mem_linux_sgl_length, | 551 | .sgl_length = nvgpu_mem_linux_sgl_length, |
546 | .sgl_gpu_addr = nvgpu_mem_linux_sgl_gpu_addr, | 552 | .sgl_gpu_addr = nvgpu_mem_linux_sgl_gpu_addr, |
547 | .sgt_free = nvgpu_mem_linux_sgl_free, | 553 | .sgt_iommuable = nvgpu_mem_linux_sgt_iommuable, |
554 | .sgt_free = nvgpu_mem_linux_sgl_free, | ||
548 | }; | 555 | }; |
549 | 556 | ||
550 | static struct nvgpu_sgt *__nvgpu_mem_get_sgl_from_vidmem( | 557 | static struct nvgpu_sgt *__nvgpu_mem_get_sgl_from_vidmem( |
diff --git a/drivers/gpu/nvgpu/common/linux/vm.c b/drivers/gpu/nvgpu/common/linux/vm.c index 895a5771..006216c2 100644 --- a/drivers/gpu/nvgpu/common/linux/vm.c +++ b/drivers/gpu/nvgpu/common/linux/vm.c | |||
@@ -59,62 +59,6 @@ static struct nvgpu_mapped_buf *__nvgpu_vm_find_mapped_buf_reverse( | |||
59 | return NULL; | 59 | return NULL; |
60 | } | 60 | } |
61 | 61 | ||
62 | /* | ||
63 | * Determine alignment for a passed buffer. Necessary since the buffer may | ||
64 | * appear big to map with large pages but the SGL may have chunks that are not | ||
65 | * aligned on a 64/128kB large page boundary. | ||
66 | */ | ||
67 | static u64 nvgpu_get_buffer_alignment(struct gk20a *g, struct scatterlist *sgl, | ||
68 | enum nvgpu_aperture aperture) | ||
69 | { | ||
70 | u64 align = 0, chunk_align = 0; | ||
71 | u64 buf_addr; | ||
72 | |||
73 | if (aperture == APERTURE_VIDMEM) { | ||
74 | struct nvgpu_page_alloc *alloc = | ||
75 | nvgpu_vidmem_get_page_alloc(sgl); | ||
76 | struct nvgpu_sgt *sgt = &alloc->sgt; | ||
77 | void *sgl_vid = sgt->sgl; | ||
78 | |||
79 | while (sgl_vid) { | ||
80 | chunk_align = 1ULL << | ||
81 | __ffs(nvgpu_sgt_get_phys(sgt, sgl_vid)) | | ||
82 | nvgpu_sgt_get_length(sgt, sgl_vid); | ||
83 | |||
84 | if (align) | ||
85 | align = min(align, chunk_align); | ||
86 | else | ||
87 | align = chunk_align; | ||
88 | |||
89 | sgl_vid = nvgpu_sgt_get_next(sgt, sgl_vid); | ||
90 | } | ||
91 | |||
92 | return align; | ||
93 | } | ||
94 | |||
95 | buf_addr = (u64)sg_dma_address(sgl); | ||
96 | |||
97 | if (g->mm.bypass_smmu || buf_addr == DMA_ERROR_CODE || !buf_addr) { | ||
98 | while (sgl) { | ||
99 | buf_addr = (u64)sg_phys(sgl); | ||
100 | chunk_align = 1ULL << __ffs(buf_addr | | ||
101 | (u64)sgl->length); | ||
102 | |||
103 | if (align) | ||
104 | align = min(align, chunk_align); | ||
105 | else | ||
106 | align = chunk_align; | ||
107 | sgl = sg_next(sgl); | ||
108 | } | ||
109 | |||
110 | return align; | ||
111 | } | ||
112 | |||
113 | align = 1ULL << __ffs(buf_addr); | ||
114 | |||
115 | return align; | ||
116 | } | ||
117 | |||
118 | int nvgpu_vm_find_buf(struct vm_gk20a *vm, u64 gpu_va, | 62 | int nvgpu_vm_find_buf(struct vm_gk20a *vm, u64 gpu_va, |
119 | struct dma_buf **dmabuf, | 63 | struct dma_buf **dmabuf, |
120 | u64 *offset) | 64 | u64 *offset) |
@@ -218,7 +162,7 @@ int nvgpu_vm_map_linux(struct vm_gk20a *vm, | |||
218 | struct nvgpu_ctag_buffer_info binfo = { 0 }; | 162 | struct nvgpu_ctag_buffer_info binfo = { 0 }; |
219 | struct gk20a_comptags comptags; | 163 | struct gk20a_comptags comptags; |
220 | struct nvgpu_vm_area *vm_area = NULL; | 164 | struct nvgpu_vm_area *vm_area = NULL; |
221 | struct nvgpu_sgt *nvgpu_sgt; | 165 | struct nvgpu_sgt *nvgpu_sgt = NULL; |
222 | struct sg_table *sgt; | 166 | struct sg_table *sgt; |
223 | struct nvgpu_mapped_buf *mapped_buffer = NULL; | 167 | struct nvgpu_mapped_buf *mapped_buffer = NULL; |
224 | enum nvgpu_aperture aperture; | 168 | enum nvgpu_aperture aperture; |
@@ -279,6 +223,10 @@ int nvgpu_vm_map_linux(struct vm_gk20a *vm, | |||
279 | goto clean_up; | 223 | goto clean_up; |
280 | } | 224 | } |
281 | 225 | ||
226 | nvgpu_sgt = nvgpu_linux_sgt_create(g, sgt); | ||
227 | if (!nvgpu_sgt) | ||
228 | goto clean_up; | ||
229 | |||
282 | aperture = gk20a_dmabuf_aperture(g, dmabuf); | 230 | aperture = gk20a_dmabuf_aperture(g, dmabuf); |
283 | if (aperture == APERTURE_INVALID) { | 231 | if (aperture == APERTURE_INVALID) { |
284 | err = -EINVAL; | 232 | err = -EINVAL; |
@@ -288,7 +236,7 @@ int nvgpu_vm_map_linux(struct vm_gk20a *vm, | |||
288 | if (flags & NVGPU_AS_MAP_BUFFER_FLAGS_FIXED_OFFSET) | 236 | if (flags & NVGPU_AS_MAP_BUFFER_FLAGS_FIXED_OFFSET) |
289 | map_offset = offset_align; | 237 | map_offset = offset_align; |
290 | 238 | ||
291 | align = nvgpu_get_buffer_alignment(g, sgt->sgl, aperture); | 239 | align = nvgpu_sgt_alignment(g, nvgpu_sgt); |
292 | if (g->mm.disable_bigpage) | 240 | if (g->mm.disable_bigpage) |
293 | binfo.pgsz_idx = gmmu_page_size_small; | 241 | binfo.pgsz_idx = gmmu_page_size_small; |
294 | else | 242 | else |
@@ -370,8 +318,6 @@ int nvgpu_vm_map_linux(struct vm_gk20a *vm, | |||
370 | ctag_offset += buffer_offset >> | 318 | ctag_offset += buffer_offset >> |
371 | ilog2(g->ops.fb.compression_page_size(g)); | 319 | ilog2(g->ops.fb.compression_page_size(g)); |
372 | 320 | ||
373 | nvgpu_sgt = nvgpu_linux_sgt_create(g, sgt); | ||
374 | |||
375 | /* update gmmu ptes */ | 321 | /* update gmmu ptes */ |
376 | map_offset = g->ops.mm.gmmu_map(vm, | 322 | map_offset = g->ops.mm.gmmu_map(vm, |
377 | map_offset, | 323 | map_offset, |
@@ -391,7 +337,7 @@ int nvgpu_vm_map_linux(struct vm_gk20a *vm, | |||
391 | if (!map_offset) | 337 | if (!map_offset) |
392 | goto clean_up; | 338 | goto clean_up; |
393 | 339 | ||
394 | nvgpu_sgt_free(nvgpu_sgt, g); | 340 | nvgpu_sgt_free(g, nvgpu_sgt); |
395 | 341 | ||
396 | mapped_buffer = nvgpu_kzalloc(g, sizeof(*mapped_buffer)); | 342 | mapped_buffer = nvgpu_kzalloc(g, sizeof(*mapped_buffer)); |
397 | if (!mapped_buffer) { | 343 | if (!mapped_buffer) { |
@@ -434,6 +380,9 @@ int nvgpu_vm_map_linux(struct vm_gk20a *vm, | |||
434 | 380 | ||
435 | clean_up: | 381 | clean_up: |
436 | nvgpu_kfree(g, mapped_buffer); | 382 | nvgpu_kfree(g, mapped_buffer); |
383 | |||
384 | if (nvgpu_sgt) | ||
385 | nvgpu_sgt_free(g, nvgpu_sgt); | ||
437 | if (va_allocated) | 386 | if (va_allocated) |
438 | __nvgpu_vm_free_va(vm, map_offset, binfo.pgsz_idx); | 387 | __nvgpu_vm_free_va(vm, map_offset, binfo.pgsz_idx); |
439 | if (!IS_ERR(sgt)) | 388 | if (!IS_ERR(sgt)) |