From aff9d46c00a2a82c93d6cc43d790584e7e474d0e Mon Sep 17 00:00:00 2001 From: Alex Waterman Date: Wed, 12 Apr 2017 11:19:09 -0700 Subject: gpu: nvgpu: Add __nvgpu_mem_create_from_pages() Add a function to create a nvgpu_mem from a list of arbitrary pages. This API is useful for pages not necessarily allocated by the Linux page allocator. It is useful for making nvgpu_mems that represent carveouts or other things like that. JIRA NVGPU-12 JIRA NVGPU-30 Change-Id: Ibcb6432f077a6b0ecf9d183248e47a1f9ecb3ddd Signed-off-by: Alex Waterman Reviewed-on: http://git-master/r/1464080 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom Reviewed-by: svccoveritychecker --- drivers/gpu/nvgpu/common/linux/dma.c | 8 +++++++ drivers/gpu/nvgpu/common/linux/nvgpu_mem.c | 38 ++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) (limited to 'drivers/gpu/nvgpu/common/linux') 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) struct device *d = dev_from_gk20a(g); if (!(mem->mem_flags & NVGPU_MEM_FLAG_SHADOW_COPY) && + !(mem->mem_flags & __NVGPU_MEM_FLAG_NO_DMA) && (mem->cpu_va || mem->priv.pages)) { if (mem->priv.flags) { DEFINE_DMA_ATTRS(dma_attrs); @@ -358,6 +359,13 @@ static void nvgpu_dma_free_sys(struct gk20a *g, struct nvgpu_mem *mem) mem->priv.pages = NULL; } + /* + * When this flag is set we expect that pages is still populated but not + * by the DMA API. + */ + if (mem->mem_flags & __NVGPU_MEM_FLAG_NO_DMA) + nvgpu_kfree(g, mem->priv.pages); + if (mem->priv.sgt) nvgpu_free_sgtable(g, &mem->priv.sgt); 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, return ret; } + +int __nvgpu_mem_create_from_pages(struct gk20a *g, struct nvgpu_mem *dest, + struct page **pages, int nr_pages) +{ + struct sg_table *sgt; + struct page **our_pages = + nvgpu_kmalloc(g, sizeof(struct page *) * nr_pages); + + if (!our_pages) + return -ENOMEM; + + memcpy(our_pages, pages, sizeof(struct page *) * nr_pages); + + if (nvgpu_get_sgtable_from_pages(g, &sgt, pages, 0, + nr_pages * PAGE_SIZE)) { + nvgpu_kfree(g, our_pages); + return -ENOMEM; + } + + /* + * If we are making an SGT from physical pages we can be reasonably + * certain that this should bypass the SMMU - thus we set the DMA (aka + * IOVA) address to 0. This tells the GMMU mapping code to not make a + * mapping directed to the SMMU. + */ + sg_dma_address(sgt->sgl) = 0; + + dest->mem_flags = __NVGPU_MEM_FLAG_NO_DMA; + dest->aperture = APERTURE_SYSMEM; + dest->skip_wmb = 0; + dest->size = PAGE_SIZE * nr_pages; + + dest->priv.flags = 0; + dest->priv.pages = our_pages; + dest->priv.sgt = sgt; + + return 0; +} -- cgit v1.2.2