summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/linux/dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/dma.c')
-rw-r--r--drivers/gpu/nvgpu/common/linux/dma.c114
1 files changed, 110 insertions, 4 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/dma.c b/drivers/gpu/nvgpu/common/linux/dma.c
index 43009fca..eff60f5b 100644
--- a/drivers/gpu/nvgpu/common/linux/dma.c
+++ b/drivers/gpu/nvgpu/common/linux/dma.c
@@ -18,10 +18,12 @@
18#include <linux/dma-mapping.h> 18#include <linux/dma-mapping.h>
19#include <linux/version.h> 19#include <linux/version.h>
20 20
21#include <nvgpu/log.h>
21#include <nvgpu/dma.h> 22#include <nvgpu/dma.h>
22#include <nvgpu/lock.h> 23#include <nvgpu/lock.h>
23#include <nvgpu/bug.h> 24#include <nvgpu/bug.h>
24#include <nvgpu/gmmu.h> 25#include <nvgpu/gmmu.h>
26#include <nvgpu/kmem.h>
25#include <nvgpu/enabled.h> 27#include <nvgpu/enabled.h>
26 28
27#include <nvgpu/linux/dma.h> 29#include <nvgpu/linux/dma.h>
@@ -30,6 +32,101 @@
30#include "gk20a/platform_gk20a.h" 32#include "gk20a/platform_gk20a.h"
31#include "os_linux.h" 33#include "os_linux.h"
32 34
35/*
36 * Enough to hold all the possible flags in string form. When a new flag is
37 * added it must be added here as well!!
38 */
39#define NVGPU_DMA_STR_SIZE \
40 sizeof("NO_KERNEL_MAPPING FORCE_CONTIGUOUS READ_ONLY")
41
42/*
43 * The returned string is kmalloc()ed here but must be freed by the caller.
44 */
45static char *nvgpu_dma_flags_to_str(struct gk20a *g, unsigned long flags)
46{
47 char *buf = nvgpu_kzalloc(g, NVGPU_DMA_STR_SIZE);
48 int bytes_available = NVGPU_DMA_STR_SIZE;
49
50 /*
51 * Return the empty buffer if there's no flags. Makes it easier on the
52 * calling code to just print it instead of any if (NULL) type logic.
53 */
54 if (!flags)
55 return buf;
56
57#define APPEND_FLAG(flag, str_flag) \
58 do { \
59 if (flags & flag) { \
60 strncat(buf, str_flag, bytes_available); \
61 bytes_available -= strlen(str_flag); \
62 } \
63 } while (0)
64
65 APPEND_FLAG(NVGPU_DMA_NO_KERNEL_MAPPING, "NO_KERNEL_MAPPING ");
66 APPEND_FLAG(NVGPU_DMA_FORCE_CONTIGUOUS, "FORCE_CONTIGUOUS ");
67 APPEND_FLAG(NVGPU_DMA_READ_ONLY, "READ_ONLY");
68#undef APPEND_FLAG
69
70 return buf;
71}
72
73/**
74 * __dma_dbg - Debug print for DMA allocs and frees.
75 *
76 * @g - The GPU.
77 * @size - The requested size of the alloc (size_t).
78 * @flags - The flags (unsigned long).
79 * @type - A string describing the type (i.e: sysmem or vidmem).
80 * @what - A string with 'alloc' or 'free'.
81 *
82 * @flags is the DMA flags. If there are none or it doesn't make sense to print
83 * flags just pass 0.
84 *
85 * Please use dma_dbg_alloc() and dma_dbg_free() instead of this function.
86 */
87static void __dma_dbg(struct gk20a *g, size_t size, unsigned long flags,
88 const char *type, const char *what)
89{
90 char *flags_str = NULL;
91
92 /*
93 * Don't bother making the flags_str if debugging is
94 * not enabled. This saves a malloc and a free.
95 */
96 if (!nvgpu_log_mask_enabled(g, gpu_dbg_dma))
97 return;
98
99 flags_str = nvgpu_dma_flags_to_str(g, flags);
100
101 __nvgpu_log_dbg(g, gpu_dbg_dma,
102 __func__, __LINE__,
103 "DMA %s: [%s] size=%-7zu aligned=%-7zu %s",
104 what, type,
105 size, PAGE_ALIGN(size),
106 flags_str);
107
108 if (flags_str)
109 nvgpu_kfree(g, flags_str);
110}
111
112#define dma_dbg_alloc(g, size, flags, type) \
113 __dma_dbg(g, size, flags, type, "alloc")
114#define dma_dbg_free(g, size, flags, type) \
115 __dma_dbg(g, size, flags, type, "free")
116
117/*
118 * For after the DMA alloc is done.
119 */
120#define __dma_dbg_done(g, size, type, what) \
121 nvgpu_log(g, gpu_dbg_dma, \
122 "DMA %s: [%s] size=%-7zu Done!", \
123 what, type, size); \
124
125#define dma_dbg_alloc_done(g, size, type) \
126 __dma_dbg_done(g, size, type, "alloc")
127#define dma_dbg_free_done(g, size, type) \
128 __dma_dbg_done(g, size, type, "free")
129
33#if defined(CONFIG_GK20A_VIDMEM) 130#if defined(CONFIG_GK20A_VIDMEM)
34static u64 __nvgpu_dma_alloc(struct nvgpu_allocator *allocator, dma_addr_t at, 131static u64 __nvgpu_dma_alloc(struct nvgpu_allocator *allocator, dma_addr_t at,
35 size_t size) 132 size_t size)
@@ -110,7 +207,7 @@ int nvgpu_dma_alloc_flags_sys(struct gk20a *g, unsigned long flags,
110 int err; 207 int err;
111 dma_addr_t iova; 208 dma_addr_t iova;
112 209
113 gk20a_dbg_fn(""); 210 dma_dbg_alloc(g, size, flags, "sysmem");
114 211
115 /* 212 /*
116 * Save the old size but for actual allocation purposes the size is 213 * Save the old size but for actual allocation purposes the size is
@@ -159,7 +256,7 @@ int nvgpu_dma_alloc_flags_sys(struct gk20a *g, unsigned long flags,
159 mem->aperture = APERTURE_SYSMEM; 256 mem->aperture = APERTURE_SYSMEM;
160 mem->priv.flags = flags; 257 mem->priv.flags = flags;
161 258
162 gk20a_dbg_fn("done"); 259 dma_dbg_alloc_done(g, mem->size, "sysmem");
163 260
164 return 0; 261 return 0;
165 262
@@ -194,7 +291,7 @@ int nvgpu_dma_alloc_flags_vid_at(struct gk20a *g, unsigned long flags,
194 &g->mm.vidmem.bootstrap_allocator; 291 &g->mm.vidmem.bootstrap_allocator;
195 int before_pending; 292 int before_pending;
196 293
197 gk20a_dbg_fn(""); 294 dma_dbg_alloc(g, size, flags, "vidmem");
198 295
199 mem->size = size; 296 mem->size = size;
200 size = PAGE_ALIGN(size); 297 size = PAGE_ALIGN(size);
@@ -246,7 +343,7 @@ int nvgpu_dma_alloc_flags_vid_at(struct gk20a *g, unsigned long flags,
246 343
247 nvgpu_init_list_node(&mem->clear_list_entry); 344 nvgpu_init_list_node(&mem->clear_list_entry);
248 345
249 gk20a_dbg_fn("done at 0x%llx size %zu", addr, size); 346 dma_dbg_alloc_done(g, mem->size, "vidmem");
250 347
251 return 0; 348 return 0;
252 349
@@ -355,6 +452,8 @@ static void nvgpu_dma_free_sys(struct gk20a *g, struct nvgpu_mem *mem)
355{ 452{
356 struct device *d = dev_from_gk20a(g); 453 struct device *d = dev_from_gk20a(g);
357 454
455 dma_dbg_free(g, mem->size, mem->priv.flags, "sysmem");
456
358 if (!(mem->mem_flags & NVGPU_MEM_FLAG_SHADOW_COPY) && 457 if (!(mem->mem_flags & NVGPU_MEM_FLAG_SHADOW_COPY) &&
359 !(mem->mem_flags & __NVGPU_MEM_FLAG_NO_DMA) && 458 !(mem->mem_flags & __NVGPU_MEM_FLAG_NO_DMA) &&
360 (mem->cpu_va || mem->priv.pages)) { 459 (mem->cpu_va || mem->priv.pages)) {
@@ -390,6 +489,8 @@ static void nvgpu_dma_free_sys(struct gk20a *g, struct nvgpu_mem *mem)
390 if (mem->priv.sgt) 489 if (mem->priv.sgt)
391 nvgpu_free_sgtable(g, &mem->priv.sgt); 490 nvgpu_free_sgtable(g, &mem->priv.sgt);
392 491
492 dma_dbg_free_done(g, mem->size, "sysmem");
493
393 mem->size = 0; 494 mem->size = 0;
394 mem->aligned_size = 0; 495 mem->aligned_size = 0;
395 mem->aperture = APERTURE_INVALID; 496 mem->aperture = APERTURE_INVALID;
@@ -399,6 +500,9 @@ static void nvgpu_dma_free_vid(struct gk20a *g, struct nvgpu_mem *mem)
399{ 500{
400#if defined(CONFIG_GK20A_VIDMEM) 501#if defined(CONFIG_GK20A_VIDMEM)
401 bool was_empty; 502 bool was_empty;
503 size_t mem_size = mem->size;
504
505 dma_dbg_free(g, mem->size, mem->priv.flags, "vidmem");
402 506
403 /* Sanity check - only this supported when allocating. */ 507 /* Sanity check - only this supported when allocating. */
404 WARN_ON(mem->priv.flags != NVGPU_DMA_NO_KERNEL_MAPPING); 508 WARN_ON(mem->priv.flags != NVGPU_DMA_NO_KERNEL_MAPPING);
@@ -426,6 +530,8 @@ static void nvgpu_dma_free_vid(struct gk20a *g, struct nvgpu_mem *mem)
426 mem->aligned_size = 0; 530 mem->aligned_size = 0;
427 mem->aperture = APERTURE_INVALID; 531 mem->aperture = APERTURE_INVALID;
428 } 532 }
533
534 dma_dbg_free_done(g, mem_size, "vidmem");
429#endif 535#endif
430} 536}
431 537