summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/linux/mem_desc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/mem_desc.c')
-rw-r--r--drivers/gpu/nvgpu/common/linux/mem_desc.c225
1 files changed, 225 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/mem_desc.c b/drivers/gpu/nvgpu/common/linux/mem_desc.c
new file mode 100644
index 00000000..b2ef122e
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/linux/mem_desc.c
@@ -0,0 +1,225 @@
1/*
2 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <nvgpu/mem_desc.h>
18#include <nvgpu/page_allocator.h>
19
20#include "gk20a/gk20a.h"
21#include "gk20a/mm_gk20a.h"
22
23u32 __gk20a_aperture_mask(struct gk20a *g, enum gk20a_aperture aperture,
24 u32 sysmem_mask, u32 vidmem_mask)
25{
26 switch (aperture) {
27 case APERTURE_SYSMEM:
28 /* sysmem for dgpus; some igpus consider system memory vidmem */
29 return g->mm.vidmem_is_vidmem ? sysmem_mask : vidmem_mask;
30 case APERTURE_VIDMEM:
31 /* for dgpus only */
32 return vidmem_mask;
33 case APERTURE_INVALID:
34 WARN_ON("Bad aperture");
35 }
36 return 0;
37}
38
39u32 gk20a_aperture_mask(struct gk20a *g, struct mem_desc *mem,
40 u32 sysmem_mask, u32 vidmem_mask)
41{
42 return __gk20a_aperture_mask(g, mem->aperture,
43 sysmem_mask, vidmem_mask);
44}
45
46int gk20a_mem_begin(struct gk20a *g, struct mem_desc *mem)
47{
48 void *cpu_va;
49
50 if (mem->aperture != APERTURE_SYSMEM || g->mm.force_pramin)
51 return 0;
52
53 if (WARN_ON(mem->cpu_va)) {
54 gk20a_warn(dev_from_gk20a(g), "nested %s", __func__);
55 return -EBUSY;
56 }
57
58 cpu_va = vmap(mem->pages,
59 PAGE_ALIGN(mem->size) >> PAGE_SHIFT,
60 0, pgprot_writecombine(PAGE_KERNEL));
61
62 if (WARN_ON(!cpu_va))
63 return -ENOMEM;
64
65 mem->cpu_va = cpu_va;
66 return 0;
67}
68
69void gk20a_mem_end(struct gk20a *g, struct mem_desc *mem)
70{
71 if (mem->aperture != APERTURE_SYSMEM || g->mm.force_pramin)
72 return;
73
74 vunmap(mem->cpu_va);
75 mem->cpu_va = NULL;
76}
77
78u32 gk20a_mem_rd32(struct gk20a *g, struct mem_desc *mem, u32 w)
79{
80 u32 data = 0;
81
82 if (mem->aperture == APERTURE_SYSMEM && !g->mm.force_pramin) {
83 u32 *ptr = mem->cpu_va;
84
85 WARN_ON(!ptr);
86 data = ptr[w];
87#ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
88 gk20a_dbg(gpu_dbg_mem, " %p = 0x%x", ptr + w, data);
89#endif
90 } else if (mem->aperture == APERTURE_VIDMEM || g->mm.force_pramin) {
91 u32 value;
92 u32 *p = &value;
93
94 nvgpu_pramin_access_batched(g, mem, w * sizeof(u32),
95 sizeof(u32), pramin_access_batch_rd_n, &p);
96
97 data = value;
98
99 } else {
100 WARN_ON("Accessing unallocated mem_desc");
101 }
102
103 return data;
104}
105
106u32 gk20a_mem_rd(struct gk20a *g, struct mem_desc *mem, u32 offset)
107{
108 WARN_ON(offset & 3);
109 return gk20a_mem_rd32(g, mem, offset / sizeof(u32));
110}
111
112void gk20a_mem_rd_n(struct gk20a *g, struct mem_desc *mem,
113 u32 offset, void *dest, u32 size)
114{
115 WARN_ON(offset & 3);
116 WARN_ON(size & 3);
117
118 if (mem->aperture == APERTURE_SYSMEM && !g->mm.force_pramin) {
119 u8 *src = (u8 *)mem->cpu_va + offset;
120
121 WARN_ON(!mem->cpu_va);
122 memcpy(dest, src, size);
123#ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
124 if (size)
125 gk20a_dbg(gpu_dbg_mem, " %p = 0x%x ... [%d bytes]",
126 src, *dest, size);
127#endif
128 } else if (mem->aperture == APERTURE_VIDMEM || g->mm.force_pramin) {
129 u32 *dest_u32 = dest;
130
131 nvgpu_pramin_access_batched(g, mem, offset, size,
132 pramin_access_batch_rd_n, &dest_u32);
133 } else {
134 WARN_ON("Accessing unallocated mem_desc");
135 }
136}
137
138void gk20a_mem_wr32(struct gk20a *g, struct mem_desc *mem, u32 w, u32 data)
139{
140 if (mem->aperture == APERTURE_SYSMEM && !g->mm.force_pramin) {
141 u32 *ptr = mem->cpu_va;
142
143 WARN_ON(!ptr);
144#ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
145 gk20a_dbg(gpu_dbg_mem, " %p = 0x%x", ptr + w, data);
146#endif
147 ptr[w] = data;
148 } else if (mem->aperture == APERTURE_VIDMEM || g->mm.force_pramin) {
149 u32 value = data;
150 u32 *p = &value;
151
152 nvgpu_pramin_access_batched(g, mem, w * sizeof(u32),
153 sizeof(u32), pramin_access_batch_wr_n, &p);
154 if (!mem->skip_wmb)
155 wmb();
156 } else {
157 WARN_ON("Accessing unallocated mem_desc");
158 }
159}
160
161void gk20a_mem_wr(struct gk20a *g, struct mem_desc *mem, u32 offset, u32 data)
162{
163 WARN_ON(offset & 3);
164 gk20a_mem_wr32(g, mem, offset / sizeof(u32), data);
165}
166
167void gk20a_mem_wr_n(struct gk20a *g, struct mem_desc *mem, u32 offset,
168 void *src, u32 size)
169{
170 WARN_ON(offset & 3);
171 WARN_ON(size & 3);
172
173 if (mem->aperture == APERTURE_SYSMEM && !g->mm.force_pramin) {
174 u8 *dest = (u8 *)mem->cpu_va + offset;
175
176 WARN_ON(!mem->cpu_va);
177#ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
178 if (size)
179 gk20a_dbg(gpu_dbg_mem, " %p = 0x%x ... [%d bytes]",
180 dest, *src, size);
181#endif
182 memcpy(dest, src, size);
183 } else if (mem->aperture == APERTURE_VIDMEM || g->mm.force_pramin) {
184 u32 *src_u32 = src;
185
186 nvgpu_pramin_access_batched(g, mem, offset, size,
187 pramin_access_batch_wr_n, &src_u32);
188 if (!mem->skip_wmb)
189 wmb();
190 } else {
191 WARN_ON("Accessing unallocated mem_desc");
192 }
193}
194
195void gk20a_memset(struct gk20a *g, struct mem_desc *mem, u32 offset,
196 u32 c, u32 size)
197{
198 WARN_ON(offset & 3);
199 WARN_ON(size & 3);
200 WARN_ON(c & ~0xff);
201
202 c &= 0xff;
203
204 if (mem->aperture == APERTURE_SYSMEM && !g->mm.force_pramin) {
205 u8 *dest = (u8 *)mem->cpu_va + offset;
206
207 WARN_ON(!mem->cpu_va);
208#ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
209 if (size)
210 gk20a_dbg(gpu_dbg_mem, " %p = 0x%x [times %d]",
211 dest, c, size);
212#endif
213 memset(dest, c, size);
214 } else if (mem->aperture == APERTURE_VIDMEM || g->mm.force_pramin) {
215 u32 repeat_value = c | (c << 8) | (c << 16) | (c << 24);
216 u32 *p = &repeat_value;
217
218 nvgpu_pramin_access_batched(g, mem, offset, size,
219 pramin_access_batch_set, &p);
220 if (!mem->skip_wmb)
221 wmb();
222 } else {
223 WARN_ON("Accessing unallocated mem_desc");
224 }
225}