diff options
Diffstat (limited to 'drivers/gpu/nvgpu/common')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/dma.c | 8 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/nvgpu_mem.c | 38 |
2 files changed, 46 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/dma.c b/drivers/gpu/nvgpu/common/linux/dma.c index abcf36f1..eb2d0ac4 100644 --- a/drivers/gpu/nvgpu/common/linux/dma.c +++ b/drivers/gpu/nvgpu/common/linux/dma.c | |||
@@ -335,6 +335,7 @@ static void nvgpu_dma_free_sys(struct gk20a *g, struct nvgpu_mem *mem) | |||
335 | struct device *d = dev_from_gk20a(g); | 335 | struct device *d = dev_from_gk20a(g); |
336 | 336 | ||
337 | if (!(mem->mem_flags & NVGPU_MEM_FLAG_SHADOW_COPY) && | 337 | if (!(mem->mem_flags & NVGPU_MEM_FLAG_SHADOW_COPY) && |
338 | !(mem->mem_flags & __NVGPU_MEM_FLAG_NO_DMA) && | ||
338 | (mem->cpu_va || mem->priv.pages)) { | 339 | (mem->cpu_va || mem->priv.pages)) { |
339 | if (mem->priv.flags) { | 340 | if (mem->priv.flags) { |
340 | DEFINE_DMA_ATTRS(dma_attrs); | 341 | DEFINE_DMA_ATTRS(dma_attrs); |
@@ -358,6 +359,13 @@ static void nvgpu_dma_free_sys(struct gk20a *g, struct nvgpu_mem *mem) | |||
358 | mem->priv.pages = NULL; | 359 | mem->priv.pages = NULL; |
359 | } | 360 | } |
360 | 361 | ||
362 | /* | ||
363 | * When this flag is set we expect that pages is still populated but not | ||
364 | * by the DMA API. | ||
365 | */ | ||
366 | if (mem->mem_flags & __NVGPU_MEM_FLAG_NO_DMA) | ||
367 | nvgpu_kfree(g, mem->priv.pages); | ||
368 | |||
361 | if (mem->priv.sgt) | 369 | if (mem->priv.sgt) |
362 | nvgpu_free_sgtable(g, &mem->priv.sgt); | 370 | nvgpu_free_sgtable(g, &mem->priv.sgt); |
363 | 371 | ||
diff --git a/drivers/gpu/nvgpu/common/linux/nvgpu_mem.c b/drivers/gpu/nvgpu/common/linux/nvgpu_mem.c index b46dbb6b..58488067 100644 --- a/drivers/gpu/nvgpu/common/linux/nvgpu_mem.c +++ b/drivers/gpu/nvgpu/common/linux/nvgpu_mem.c | |||
@@ -297,3 +297,41 @@ int nvgpu_mem_create_from_mem(struct gk20a *g, | |||
297 | 297 | ||
298 | return ret; | 298 | return ret; |
299 | } | 299 | } |
300 | |||
301 | int __nvgpu_mem_create_from_pages(struct gk20a *g, struct nvgpu_mem *dest, | ||
302 | struct page **pages, int nr_pages) | ||
303 | { | ||
304 | struct sg_table *sgt; | ||
305 | struct page **our_pages = | ||
306 | nvgpu_kmalloc(g, sizeof(struct page *) * nr_pages); | ||
307 | |||
308 | if (!our_pages) | ||
309 | return -ENOMEM; | ||
310 | |||
311 | memcpy(our_pages, pages, sizeof(struct page *) * nr_pages); | ||
312 | |||
313 | if (nvgpu_get_sgtable_from_pages(g, &sgt, pages, 0, | ||
314 | nr_pages * PAGE_SIZE)) { | ||
315 | nvgpu_kfree(g, our_pages); | ||
316 | return -ENOMEM; | ||
317 | } | ||
318 | |||
319 | /* | ||
320 | * If we are making an SGT from physical pages we can be reasonably | ||
321 | * certain that this should bypass the SMMU - thus we set the DMA (aka | ||
322 | * IOVA) address to 0. This tells the GMMU mapping code to not make a | ||
323 | * mapping directed to the SMMU. | ||
324 | */ | ||
325 | sg_dma_address(sgt->sgl) = 0; | ||
326 | |||
327 | dest->mem_flags = __NVGPU_MEM_FLAG_NO_DMA; | ||
328 | dest->aperture = APERTURE_SYSMEM; | ||
329 | dest->skip_wmb = 0; | ||
330 | dest->size = PAGE_SIZE * nr_pages; | ||
331 | |||
332 | dest->priv.flags = 0; | ||
333 | dest->priv.pages = our_pages; | ||
334 | dest->priv.sgt = sgt; | ||
335 | |||
336 | return 0; | ||
337 | } | ||