diff options
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/nvgpu_mem.c')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/nvgpu_mem.c | 38 |
1 files changed, 38 insertions, 0 deletions
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 | } | ||