diff options
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/dma.c | 8 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/nvgpu_mem.c | 38 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/linux/nvgpu_mem.h | 31 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/nvgpu_mem.h | 10 |
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 | |||
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 | } | ||
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 @@ | |||
20 | struct page; | 20 | struct page; |
21 | struct sg_table; | 21 | struct sg_table; |
22 | 22 | ||
23 | struct gk20a; | ||
24 | struct nvgpu_mem; | ||
25 | |||
23 | struct nvgpu_mem_priv { | 26 | struct 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 | */ | ||
57 | int __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 | /* |