summaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2017-04-12 14:19:09 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-04-25 17:26:00 -0400
commitaff9d46c00a2a82c93d6cc43d790584e7e474d0e (patch)
treedd86be88334529cf4b109c68e477a9e5c0e6b8b6 /drivers/gpu
parent5714f5eaaf4715c9989e5c2bf732cdb9136b0fbe (diff)
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 <alexw@nvidia.com> Reviewed-on: http://git-master/r/1464080 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/nvgpu/common/linux/dma.c8
-rw-r--r--drivers/gpu/nvgpu/common/linux/nvgpu_mem.c38
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/linux/nvgpu_mem.h31
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/nvgpu_mem.h10
4 files changed, 87 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
301int __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}
diff --git a/drivers/gpu/nvgpu/include/nvgpu/linux/nvgpu_mem.h b/drivers/gpu/nvgpu/include/nvgpu/linux/nvgpu_mem.h
index 8b1e646e..9c52811e 100644
--- a/drivers/gpu/nvgpu/include/nvgpu/linux/nvgpu_mem.h
+++ b/drivers/gpu/nvgpu/include/nvgpu/linux/nvgpu_mem.h
@@ -20,10 +20,41 @@
20struct page; 20struct page;
21struct sg_table; 21struct sg_table;
22 22
23struct gk20a;
24struct nvgpu_mem;
25
23struct nvgpu_mem_priv { 26struct nvgpu_mem_priv {
24 struct page **pages; 27 struct page **pages;
25 struct sg_table *sgt; 28 struct sg_table *sgt;
26 unsigned long flags; 29 unsigned long flags;
27}; 30};
28 31
32/**
33 * __nvgpu_mem_create_from_pages - Create an nvgpu_mem from physical pages.
34 *
35 * @g - The GPU.
36 * @dest - nvgpu_mem to initialize.
37 * @pages - A list of page pointers.
38 * @nr_pages - The number of pages in @pages.
39 *
40 * Create a new nvgpu_mem struct from a pre-existing list of physical pages. The
41 * pages need not be contiguous (the underlying scatter gather list will help
42 * with that). However, note, this API will explicitly make it so that the GMMU
43 * mapping code bypasses SMMU access for the passed pages. This allows one to
44 * make mem_descs that describe MMIO regions or other non-DRAM things.
45 *
46 * This only works for SYSMEM (or other things like SYSMEM - basically just not
47 * VIDMEM). Also, this API is only available for Linux as it heavily depends on
48 * the notion of struct %page.
49 *
50 * The resulting nvgpu_mem should be released with the nvgpu_dma_free() or the
51 * nvgpu_dma_unmap_free() function depending on whether or not the resulting
52 * nvgpu_mem has been mapped. The underlying pages themselves must be cleaned up
53 * by the caller of this API.
54 *
55 * Returns 0 on success, or a relevant error otherwise.
56 */
57int __nvgpu_mem_create_from_pages(struct gk20a *g, struct nvgpu_mem *dest,
58 struct page **pages, int nr_pages);
59
29#endif 60#endif
diff --git a/drivers/gpu/nvgpu/include/nvgpu/nvgpu_mem.h b/drivers/gpu/nvgpu/include/nvgpu/nvgpu_mem.h
index b01fbec5..66d04ab8 100644
--- a/drivers/gpu/nvgpu/include/nvgpu/nvgpu_mem.h
+++ b/drivers/gpu/nvgpu/include/nvgpu/nvgpu_mem.h
@@ -68,6 +68,16 @@ struct nvgpu_mem {
68 * therefor zeroed (to prevent leaking information in VIDMEM buffers). 68 * therefor zeroed (to prevent leaking information in VIDMEM buffers).
69 */ 69 */
70#define NVGPU_MEM_FLAG_USER_MEM (1 << 2) 70#define NVGPU_MEM_FLAG_USER_MEM (1 << 2)
71
72 /*
73 * Internal flag that specifies this struct has not been made with DMA
74 * memory and as a result should not try to use the DMA routines for
75 * freeing the backing memory.
76 *
77 * However, this will not stop the DMA API from freeing other parts of
78 * nvgpu_mem in a system specific way.
79 */
80#define __NVGPU_MEM_FLAG_NO_DMA (1 << 3)
71 unsigned long mem_flags; 81 unsigned long mem_flags;
72 82
73 /* 83 /*