summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2017-07-31 15:32:07 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-10-10 11:01:04 -0400
commit3c37701377459fbea2b460e1b9c65a863dfb04b2 (patch)
tree60a57a260dc8bcbd81089af8e9e966074e3bc881 /drivers/gpu/nvgpu/common
parentb61306795b53647e8d1d4279417df1e1fe0f4b86 (diff)
gpu: nvgpu: Split VIDMEM support from mm_gk20a.c
Split VIDMEM support into its own code files organized as such: common/mm/vidmem.c - Base vidmem support common/linux/vidmem.c - Linux specific user-space interaction include/nvgpu/vidmem.h - Vidmem API definitions Also use the config to enable/disable VIDMEM support in the makefile and remove as many CONFIG_GK20A_VIDMEM preprocessor checks as possible from the source code. And lastly update a while-loop that iterated over an SGT to use the new for_each construct for iterating over SGTs. Currently this organization is not perfectly adhered to. More patches will fix that. JIRA NVGPU-30 JIRA NVGPU-138 Change-Id: Ic0f4d2cf38b65849c7dc350a69b175421477069c Signed-off-by: Alex Waterman <alexw@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1540705 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/common')
-rw-r--r--drivers/gpu/nvgpu/common/linux/dma.c1
-rw-r--r--drivers/gpu/nvgpu/common/linux/ioctl_ctrl.c1
-rw-r--r--drivers/gpu/nvgpu/common/linux/nvgpu_mem.c1
-rw-r--r--drivers/gpu/nvgpu/common/linux/vidmem.c268
-rw-r--r--drivers/gpu/nvgpu/common/linux/vm.c29
-rw-r--r--drivers/gpu/nvgpu/common/mm/gmmu.c1
-rw-r--r--drivers/gpu/nvgpu/common/mm/nvgpu_mem.c1
-rw-r--r--drivers/gpu/nvgpu/common/mm/vidmem.c259
-rw-r--r--drivers/gpu/nvgpu/common/pramin.c1
9 files changed, 562 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/dma.c b/drivers/gpu/nvgpu/common/linux/dma.c
index 7b892731..2ed1cc5a 100644
--- a/drivers/gpu/nvgpu/common/linux/dma.c
+++ b/drivers/gpu/nvgpu/common/linux/dma.c
@@ -25,6 +25,7 @@
25#include <nvgpu/gmmu.h> 25#include <nvgpu/gmmu.h>
26#include <nvgpu/kmem.h> 26#include <nvgpu/kmem.h>
27#include <nvgpu/enabled.h> 27#include <nvgpu/enabled.h>
28#include <nvgpu/vidmem.h>
28 29
29#include <nvgpu/linux/dma.h> 30#include <nvgpu/linux/dma.h>
30 31
diff --git a/drivers/gpu/nvgpu/common/linux/ioctl_ctrl.c b/drivers/gpu/nvgpu/common/linux/ioctl_ctrl.c
index 220cb3e7..87ae0a3d 100644
--- a/drivers/gpu/nvgpu/common/linux/ioctl_ctrl.c
+++ b/drivers/gpu/nvgpu/common/linux/ioctl_ctrl.c
@@ -25,6 +25,7 @@
25#include <nvgpu/kmem.h> 25#include <nvgpu/kmem.h>
26#include <nvgpu/bug.h> 26#include <nvgpu/bug.h>
27#include <nvgpu/bus.h> 27#include <nvgpu/bus.h>
28#include <nvgpu/vidmem.h>
28 29
29#include "ioctl_ctrl.h" 30#include "ioctl_ctrl.h"
30#include "ioctl_tsg.h" 31#include "ioctl_tsg.h"
diff --git a/drivers/gpu/nvgpu/common/linux/nvgpu_mem.c b/drivers/gpu/nvgpu/common/linux/nvgpu_mem.c
index 0be41a44..e8aea0be 100644
--- a/drivers/gpu/nvgpu/common/linux/nvgpu_mem.c
+++ b/drivers/gpu/nvgpu/common/linux/nvgpu_mem.c
@@ -22,6 +22,7 @@
22#include <nvgpu/bug.h> 22#include <nvgpu/bug.h>
23#include <nvgpu/enabled.h> 23#include <nvgpu/enabled.h>
24#include <nvgpu/kmem.h> 24#include <nvgpu/kmem.h>
25#include <nvgpu/vidmem.h>
25 26
26#include <nvgpu/linux/dma.h> 27#include <nvgpu/linux/dma.h>
27 28
diff --git a/drivers/gpu/nvgpu/common/linux/vidmem.c b/drivers/gpu/nvgpu/common/linux/vidmem.c
new file mode 100644
index 00000000..e89dd07a
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/linux/vidmem.c
@@ -0,0 +1,268 @@
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 <linux/dma-buf.h>
18
19#include <linux/platform/tegra/tegra_fd.h>
20
21#include <nvgpu/dma.h>
22#include <nvgpu/enabled.h>
23#include <nvgpu/vidmem.h>
24#include <nvgpu/nvgpu_mem.h>
25#include <nvgpu/page_allocator.h>
26
27#include <nvgpu/linux/dma.h>
28
29#include "gk20a/gk20a.h"
30#include "gk20a/mm_gk20a.h"
31
32#include "vm_priv.h"
33
34void set_vidmem_page_alloc(struct scatterlist *sgl, u64 addr)
35{
36 /* set bit 0 to indicate vidmem allocation */
37 sg_dma_address(sgl) = (addr | 1ULL);
38}
39
40bool is_vidmem_page_alloc(u64 addr)
41{
42 return !!(addr & 1ULL);
43}
44
45struct nvgpu_page_alloc *get_vidmem_page_alloc(struct scatterlist *sgl)
46{
47 u64 addr;
48
49 addr = sg_dma_address(sgl);
50
51 if (is_vidmem_page_alloc(addr))
52 addr = addr & ~1ULL;
53 else
54 WARN_ON(1);
55
56 return (struct nvgpu_page_alloc *)(uintptr_t)addr;
57}
58
59static struct sg_table *gk20a_vidbuf_map_dma_buf(
60 struct dma_buf_attachment *attach, enum dma_data_direction dir)
61{
62 struct gk20a_vidmem_buf *buf = attach->dmabuf->priv;
63
64 return buf->mem->priv.sgt;
65}
66
67static void gk20a_vidbuf_unmap_dma_buf(struct dma_buf_attachment *attach,
68 struct sg_table *sgt,
69 enum dma_data_direction dir)
70{
71}
72
73static void gk20a_vidbuf_release(struct dma_buf *dmabuf)
74{
75 struct gk20a_vidmem_buf *buf = dmabuf->priv;
76
77 gk20a_dbg_fn("");
78
79 if (buf->dmabuf_priv)
80 buf->dmabuf_priv_delete(buf->dmabuf_priv);
81
82 nvgpu_dma_free(buf->g, buf->mem);
83 nvgpu_kfree(buf->g, buf);
84}
85
86static void *gk20a_vidbuf_kmap(struct dma_buf *dmabuf, unsigned long page_num)
87{
88 WARN_ON("Not supported");
89 return NULL;
90}
91
92static void *gk20a_vidbuf_kmap_atomic(struct dma_buf *dmabuf,
93 unsigned long page_num)
94{
95 WARN_ON("Not supported");
96 return NULL;
97}
98
99static int gk20a_vidbuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
100{
101 return -EINVAL;
102}
103
104static int gk20a_vidbuf_set_private(struct dma_buf *dmabuf,
105 struct device *dev, void *priv, void (*delete)(void *priv))
106{
107 struct gk20a_vidmem_buf *buf = dmabuf->priv;
108
109 buf->dmabuf_priv = priv;
110 buf->dmabuf_priv_delete = delete;
111
112 return 0;
113}
114
115static void *gk20a_vidbuf_get_private(struct dma_buf *dmabuf,
116 struct device *dev)
117{
118 struct gk20a_vidmem_buf *buf = dmabuf->priv;
119
120 return buf->dmabuf_priv;
121}
122
123static const struct dma_buf_ops gk20a_vidbuf_ops = {
124 .map_dma_buf = gk20a_vidbuf_map_dma_buf,
125 .unmap_dma_buf = gk20a_vidbuf_unmap_dma_buf,
126 .release = gk20a_vidbuf_release,
127 .kmap_atomic = gk20a_vidbuf_kmap_atomic,
128 .kmap = gk20a_vidbuf_kmap,
129 .mmap = gk20a_vidbuf_mmap,
130 .set_drvdata = gk20a_vidbuf_set_private,
131 .get_drvdata = gk20a_vidbuf_get_private,
132};
133
134static struct dma_buf *gk20a_vidbuf_export(struct gk20a_vidmem_buf *buf)
135{
136 DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
137
138 exp_info.priv = buf;
139 exp_info.ops = &gk20a_vidbuf_ops;
140 exp_info.size = buf->mem->size;
141 exp_info.flags = O_RDWR;
142
143 return dma_buf_export(&exp_info);
144}
145
146struct gk20a *gk20a_vidmem_buf_owner(struct dma_buf *dmabuf)
147{
148 struct gk20a_vidmem_buf *buf = dmabuf->priv;
149
150 if (dmabuf->ops != &gk20a_vidbuf_ops)
151 return NULL;
152
153 return buf->g;
154}
155
156int gk20a_vidmem_buf_alloc(struct gk20a *g, size_t bytes)
157{
158 struct gk20a_vidmem_buf *buf;
159 int err = 0, fd;
160
161 gk20a_dbg_fn("");
162
163 buf = nvgpu_kzalloc(g, sizeof(*buf));
164 if (!buf)
165 return -ENOMEM;
166
167 buf->g = g;
168
169 if (!g->mm.vidmem.cleared) {
170 nvgpu_mutex_acquire(&g->mm.vidmem.first_clear_mutex);
171 if (!g->mm.vidmem.cleared) {
172 err = gk20a_vidmem_clear_all(g);
173 if (err) {
174 nvgpu_err(g,
175 "failed to clear whole vidmem");
176 goto err_kfree;
177 }
178 }
179 nvgpu_mutex_release(&g->mm.vidmem.first_clear_mutex);
180 }
181
182 buf->mem = nvgpu_kzalloc(g, sizeof(struct nvgpu_mem));
183 if (!buf->mem)
184 goto err_kfree;
185
186 buf->mem->mem_flags |= NVGPU_MEM_FLAG_USER_MEM;
187
188 err = nvgpu_dma_alloc_vid(g, bytes, buf->mem);
189 if (err)
190 goto err_memfree;
191
192 buf->dmabuf = gk20a_vidbuf_export(buf);
193 if (IS_ERR(buf->dmabuf)) {
194 err = PTR_ERR(buf->dmabuf);
195 goto err_bfree;
196 }
197
198 fd = tegra_alloc_fd(current->files, 1024, O_RDWR);
199 if (fd < 0) {
200 /* ->release frees what we have done */
201 dma_buf_put(buf->dmabuf);
202 return fd;
203 }
204
205 /* fclose() on this drops one ref, freeing the dma buf */
206 fd_install(fd, buf->dmabuf->file);
207
208 return fd;
209
210err_bfree:
211 nvgpu_dma_free(g, buf->mem);
212err_memfree:
213 nvgpu_kfree(g, buf->mem);
214err_kfree:
215 nvgpu_kfree(g, buf);
216 return err;
217}
218
219int gk20a_vidbuf_access_memory(struct gk20a *g, struct dma_buf *dmabuf,
220 void *buffer, u64 offset, u64 size, u32 cmd)
221{
222 struct gk20a_vidmem_buf *vidmem_buf;
223 struct nvgpu_mem *mem;
224 int err = 0;
225
226 if (gk20a_dmabuf_aperture(g, dmabuf) != APERTURE_VIDMEM)
227 return -EINVAL;
228
229 vidmem_buf = dmabuf->priv;
230 mem = vidmem_buf->mem;
231
232 switch (cmd) {
233 case NVGPU_DBG_GPU_IOCTL_ACCESS_FB_MEMORY_CMD_READ:
234 nvgpu_mem_rd_n(g, mem, offset, buffer, size);
235 break;
236
237 case NVGPU_DBG_GPU_IOCTL_ACCESS_FB_MEMORY_CMD_WRITE:
238 nvgpu_mem_wr_n(g, mem, offset, buffer, size);
239 break;
240
241 default:
242 err = -EINVAL;
243 }
244
245 return err;
246}
247
248void gk20a_vidmem_clear_mem_worker(struct work_struct *work)
249{
250 struct mm_gk20a *mm = container_of(work, struct mm_gk20a,
251 vidmem.clear_mem_worker);
252 struct gk20a *g = mm->g;
253 struct nvgpu_mem *mem;
254
255 while ((mem = get_pending_mem_desc(mm)) != NULL) {
256 gk20a_gmmu_clear_vidmem_mem(g, mem);
257 nvgpu_free(mem->allocator,
258 (u64)get_vidmem_page_alloc(mem->priv.sgt->sgl));
259 nvgpu_free_sgtable(g, &mem->priv.sgt);
260
261 WARN_ON(nvgpu_atomic64_sub_return(mem->aligned_size,
262 &g->mm.vidmem.bytes_pending) < 0);
263 mem->size = 0;
264 mem->aperture = APERTURE_INVALID;
265
266 nvgpu_kfree(g, mem);
267 }
268}
diff --git a/drivers/gpu/nvgpu/common/linux/vm.c b/drivers/gpu/nvgpu/common/linux/vm.c
index 2e29f0f7..f4ac3d41 100644
--- a/drivers/gpu/nvgpu/common/linux/vm.c
+++ b/drivers/gpu/nvgpu/common/linux/vm.c
@@ -23,6 +23,8 @@
23#include <nvgpu/vm_area.h> 23#include <nvgpu/vm_area.h>
24#include <nvgpu/nvgpu_mem.h> 24#include <nvgpu/nvgpu_mem.h>
25#include <nvgpu/page_allocator.h> 25#include <nvgpu/page_allocator.h>
26#include <nvgpu/vidmem.h>
27#include <nvgpu/enabled.h>
26 28
27#include <nvgpu/linux/nvgpu_mem.h> 29#include <nvgpu/linux/nvgpu_mem.h>
28 30
@@ -34,6 +36,33 @@
34#include "vm_priv.h" 36#include "vm_priv.h"
35#include "os_linux.h" 37#include "os_linux.h"
36 38
39/*
40 * Temporary location for this code until a dmabuf.c file exists.
41 */
42enum nvgpu_aperture gk20a_dmabuf_aperture(struct gk20a *g,
43 struct dma_buf *dmabuf)
44{
45 struct gk20a *buf_owner = gk20a_vidmem_buf_owner(dmabuf);
46 bool unified_memory = nvgpu_is_enabled(g, NVGPU_MM_UNIFIED_MEMORY);
47
48 if (buf_owner == NULL) {
49 /* Not nvgpu-allocated, assume system memory */
50 return APERTURE_SYSMEM;
51 } else if (WARN_ON(buf_owner == g && unified_memory)) {
52 /* Looks like our video memory, but this gpu doesn't support
53 * it. Warn about a bug and bail out */
54 nvgpu_warn(g,
55 "dmabuf is our vidmem but we don't have local vidmem");
56 return APERTURE_INVALID;
57 } else if (buf_owner != g) {
58 /* Someone else's vidmem */
59 return APERTURE_INVALID;
60 } else {
61 /* Yay, buf_owner == g */
62 return APERTURE_VIDMEM;
63 }
64}
65
37static struct nvgpu_mapped_buf *__nvgpu_vm_find_mapped_buf_reverse( 66static struct nvgpu_mapped_buf *__nvgpu_vm_find_mapped_buf_reverse(
38 struct vm_gk20a *vm, struct dma_buf *dmabuf, u32 kind) 67 struct vm_gk20a *vm, struct dma_buf *dmabuf, u32 kind)
39{ 68{
diff --git a/drivers/gpu/nvgpu/common/mm/gmmu.c b/drivers/gpu/nvgpu/common/mm/gmmu.c
index f61ec3fc..1eed3a3b 100644
--- a/drivers/gpu/nvgpu/common/mm/gmmu.c
+++ b/drivers/gpu/nvgpu/common/mm/gmmu.c
@@ -28,6 +28,7 @@
28#include <nvgpu/enabled.h> 28#include <nvgpu/enabled.h>
29#include <nvgpu/page_allocator.h> 29#include <nvgpu/page_allocator.h>
30#include <nvgpu/barrier.h> 30#include <nvgpu/barrier.h>
31#include <nvgpu/vidmem.h>
31 32
32#include "gk20a/gk20a.h" 33#include "gk20a/gk20a.h"
33#include "gk20a/mm_gk20a.h" 34#include "gk20a/mm_gk20a.h"
diff --git a/drivers/gpu/nvgpu/common/mm/nvgpu_mem.c b/drivers/gpu/nvgpu/common/mm/nvgpu_mem.c
index faee482d..2b6e6e6a 100644
--- a/drivers/gpu/nvgpu/common/mm/nvgpu_mem.c
+++ b/drivers/gpu/nvgpu/common/mm/nvgpu_mem.c
@@ -23,6 +23,7 @@
23#include <nvgpu/kmem.h> 23#include <nvgpu/kmem.h>
24#include <nvgpu/nvgpu_mem.h> 24#include <nvgpu/nvgpu_mem.h>
25#include <nvgpu/dma.h> 25#include <nvgpu/dma.h>
26#include <nvgpu/vidmem.h>
26 27
27#include "gk20a/gk20a.h" 28#include "gk20a/gk20a.h"
28 29
diff --git a/drivers/gpu/nvgpu/common/mm/vidmem.c b/drivers/gpu/nvgpu/common/mm/vidmem.c
new file mode 100644
index 00000000..1ba07ca6
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/mm/vidmem.c
@@ -0,0 +1,259 @@
1/*
2 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22
23#include <linux/scatterlist.h>
24
25#include <nvgpu/vidmem.h>
26#include <nvgpu/page_allocator.h>
27
28#include "gk20a/gk20a.h"
29#include "gk20a/mm_gk20a.h"
30
31void gk20a_vidmem_destroy(struct gk20a *g)
32{
33 if (nvgpu_alloc_initialized(&g->mm.vidmem.allocator))
34 nvgpu_alloc_destroy(&g->mm.vidmem.allocator);
35}
36
37int gk20a_vidmem_clear_all(struct gk20a *g)
38{
39 struct mm_gk20a *mm = &g->mm;
40 struct gk20a_fence *gk20a_fence_out = NULL;
41 u64 region2_base = 0;
42 int err = 0;
43
44 if (mm->vidmem.ce_ctx_id == (u32)~0)
45 return -EINVAL;
46
47 err = gk20a_ce_execute_ops(g,
48 mm->vidmem.ce_ctx_id,
49 0,
50 mm->vidmem.base,
51 mm->vidmem.bootstrap_base - mm->vidmem.base,
52 0x00000000,
53 NVGPU_CE_DST_LOCATION_LOCAL_FB,
54 NVGPU_CE_MEMSET,
55 NULL,
56 0,
57 NULL);
58 if (err) {
59 nvgpu_err(g,
60 "Failed to clear vidmem region 1 : %d", err);
61 return err;
62 }
63
64 region2_base = mm->vidmem.bootstrap_base + mm->vidmem.bootstrap_size;
65
66 err = gk20a_ce_execute_ops(g,
67 mm->vidmem.ce_ctx_id,
68 0,
69 region2_base,
70 mm->vidmem.size - region2_base,
71 0x00000000,
72 NVGPU_CE_DST_LOCATION_LOCAL_FB,
73 NVGPU_CE_MEMSET,
74 NULL,
75 0,
76 &gk20a_fence_out);
77 if (err) {
78 nvgpu_err(g,
79 "Failed to clear vidmem region 2 : %d", err);
80 return err;
81 }
82
83 if (gk20a_fence_out) {
84 struct nvgpu_timeout timeout;
85
86 nvgpu_timeout_init(g, &timeout,
87 gk20a_get_gr_idle_timeout(g),
88 NVGPU_TIMER_CPU_TIMER);
89
90 do {
91 err = gk20a_fence_wait(g, gk20a_fence_out,
92 gk20a_get_gr_idle_timeout(g));
93 } while (err == -ERESTARTSYS &&
94 !nvgpu_timeout_expired(&timeout));
95
96 gk20a_fence_put(gk20a_fence_out);
97 if (err) {
98 nvgpu_err(g,
99 "fence wait failed for CE execute ops");
100 return err;
101 }
102 }
103
104 mm->vidmem.cleared = true;
105
106 return 0;
107}
108
109int gk20a_init_vidmem(struct mm_gk20a *mm)
110{
111 struct gk20a *g = mm->g;
112 size_t size = g->ops.mm.get_vidmem_size ?
113 g->ops.mm.get_vidmem_size(g) : 0;
114 u64 bootstrap_base, bootstrap_size, base;
115 u64 default_page_size = SZ_64K;
116 int err;
117
118 static struct nvgpu_alloc_carveout wpr_co =
119 NVGPU_CARVEOUT("wpr-region", 0, SZ_16M);
120
121 if (!size)
122 return 0;
123
124 wpr_co.base = size - SZ_256M;
125 bootstrap_base = wpr_co.base;
126 bootstrap_size = SZ_16M;
127 base = default_page_size;
128
129 /*
130 * Bootstrap allocator for use before the CE is initialized (CE
131 * initialization requires vidmem but we want to use the CE to zero
132 * out vidmem before allocating it...
133 */
134 err = nvgpu_page_allocator_init(g, &g->mm.vidmem.bootstrap_allocator,
135 "vidmem-bootstrap",
136 bootstrap_base, bootstrap_size,
137 SZ_4K, 0);
138
139 err = nvgpu_page_allocator_init(g, &g->mm.vidmem.allocator,
140 "vidmem",
141 base, size - base,
142 default_page_size,
143 GPU_ALLOC_4K_VIDMEM_PAGES);
144 if (err) {
145 nvgpu_err(g, "Failed to register vidmem for size %zu: %d",
146 size, err);
147 return err;
148 }
149
150 /* Reserve bootstrap region in vidmem allocator */
151 nvgpu_alloc_reserve_carveout(&g->mm.vidmem.allocator, &wpr_co);
152
153 mm->vidmem.base = base;
154 mm->vidmem.size = size - base;
155 mm->vidmem.bootstrap_base = bootstrap_base;
156 mm->vidmem.bootstrap_size = bootstrap_size;
157
158 nvgpu_mutex_init(&mm->vidmem.first_clear_mutex);
159
160 INIT_WORK(&mm->vidmem.clear_mem_worker, gk20a_vidmem_clear_mem_worker);
161 nvgpu_atomic64_set(&mm->vidmem.bytes_pending, 0);
162 nvgpu_init_list_node(&mm->vidmem.clear_list_head);
163 nvgpu_mutex_init(&mm->vidmem.clear_list_mutex);
164
165 gk20a_dbg_info("registered vidmem: %zu MB", size / SZ_1M);
166
167 return 0;
168}
169
170int gk20a_vidmem_get_space(struct gk20a *g, u64 *space)
171{
172 struct nvgpu_allocator *allocator = &g->mm.vidmem.allocator;
173
174 gk20a_dbg_fn("");
175
176 if (!nvgpu_alloc_initialized(allocator))
177 return -ENOSYS;
178
179 nvgpu_mutex_acquire(&g->mm.vidmem.clear_list_mutex);
180 *space = nvgpu_alloc_space(allocator) +
181 nvgpu_atomic64_read(&g->mm.vidmem.bytes_pending);
182 nvgpu_mutex_release(&g->mm.vidmem.clear_list_mutex);
183 return 0;
184}
185
186int gk20a_gmmu_clear_vidmem_mem(struct gk20a *g, struct nvgpu_mem *mem)
187{
188 struct gk20a_fence *gk20a_fence_out = NULL;
189 struct gk20a_fence *gk20a_last_fence = NULL;
190 struct nvgpu_page_alloc *alloc = NULL;
191 void *sgl = NULL;
192 int err = 0;
193
194 if (g->mm.vidmem.ce_ctx_id == (u32)~0)
195 return -EINVAL;
196
197 alloc = get_vidmem_page_alloc(mem->priv.sgt->sgl);
198
199 nvgpu_sgt_for_each_sgl(sgl, &alloc->sgt) {
200 if (gk20a_last_fence)
201 gk20a_fence_put(gk20a_last_fence);
202
203 err = gk20a_ce_execute_ops(g,
204 g->mm.vidmem.ce_ctx_id,
205 0,
206 nvgpu_sgt_get_phys(&alloc->sgt, sgl),
207 nvgpu_sgt_get_length(&alloc->sgt, sgl),
208 0x00000000,
209 NVGPU_CE_DST_LOCATION_LOCAL_FB,
210 NVGPU_CE_MEMSET,
211 NULL,
212 0,
213 &gk20a_fence_out);
214
215 if (err) {
216 nvgpu_err(g,
217 "Failed gk20a_ce_execute_ops[%d]", err);
218 return err;
219 }
220
221 gk20a_last_fence = gk20a_fence_out;
222 }
223
224 if (gk20a_last_fence) {
225 struct nvgpu_timeout timeout;
226
227 nvgpu_timeout_init(g, &timeout,
228 gk20a_get_gr_idle_timeout(g),
229 NVGPU_TIMER_CPU_TIMER);
230
231 do {
232 err = gk20a_fence_wait(g, gk20a_last_fence,
233 gk20a_get_gr_idle_timeout(g));
234 } while (err == -ERESTARTSYS &&
235 !nvgpu_timeout_expired(&timeout));
236
237 gk20a_fence_put(gk20a_last_fence);
238 if (err)
239 nvgpu_err(g,
240 "fence wait failed for CE execute ops");
241 }
242
243 return err;
244}
245
246struct nvgpu_mem *get_pending_mem_desc(struct mm_gk20a *mm)
247{
248 struct nvgpu_mem *mem = NULL;
249
250 nvgpu_mutex_acquire(&mm->vidmem.clear_list_mutex);
251 if (!nvgpu_list_empty(&mm->vidmem.clear_list_head)) {
252 mem = nvgpu_list_first_entry(&mm->vidmem.clear_list_head,
253 nvgpu_mem, clear_list_entry);
254 nvgpu_list_del(&mem->clear_list_entry);
255 }
256 nvgpu_mutex_release(&mm->vidmem.clear_list_mutex);
257
258 return mem;
259}
diff --git a/drivers/gpu/nvgpu/common/pramin.c b/drivers/gpu/nvgpu/common/pramin.c
index 4f7d6248..56179a6b 100644
--- a/drivers/gpu/nvgpu/common/pramin.c
+++ b/drivers/gpu/nvgpu/common/pramin.c
@@ -23,6 +23,7 @@
23#include <nvgpu/pramin.h> 23#include <nvgpu/pramin.h>
24#include <nvgpu/page_allocator.h> 24#include <nvgpu/page_allocator.h>
25#include <nvgpu/enabled.h> 25#include <nvgpu/enabled.h>
26#include <nvgpu/vidmem.h>
26 27
27#include "gk20a/gk20a.h" 28#include "gk20a/gk20a.h"
28 29