summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/vgpu/gp10b
diff options
context:
space:
mode:
authorDeepak Nibade <dnibade@nvidia.com>2016-12-27 05:01:00 -0500
committerDeepak Nibade <dnibade@nvidia.com>2016-12-27 05:35:06 -0500
commit7a81883a0d70c3a43ad2841ac235f6dc344c60fb (patch)
tree92923d2efccf90d1961071fa9acde59178a0d688 /drivers/gpu/nvgpu/vgpu/gp10b
parent505b442551a2e27aa3bc9e608c5a2bc9fccecbc4 (diff)
parent2aa3c85f8e82b3c07c39e677663abd3687c1822a (diff)
Merge remote-tracking branch 'remotes/origin/dev/merge-nvgpu-t18x-into-nvgpu' into dev-kernel
Merge T186 - gp10b/gp106 code into common nvgpu repo Bug 200266498 Change-Id: Ibf100ee38010cbed85c149b69b99147256f9a005 Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/vgpu/gp10b')
-rw-r--r--drivers/gpu/nvgpu/vgpu/gp10b/vgpu_fifo_gp10b.c48
-rw-r--r--drivers/gpu/nvgpu/vgpu/gp10b/vgpu_fifo_gp10b.h21
-rw-r--r--drivers/gpu/nvgpu/vgpu/gp10b/vgpu_gr_gp10b.c321
-rw-r--r--drivers/gpu/nvgpu/vgpu/gp10b/vgpu_gr_gp10b.h21
-rw-r--r--drivers/gpu/nvgpu/vgpu/gp10b/vgpu_hal_gp10b.c36
-rw-r--r--drivers/gpu/nvgpu/vgpu/gp10b/vgpu_mm_gp10b.c188
-rw-r--r--drivers/gpu/nvgpu/vgpu/gp10b/vgpu_mm_gp10b.h21
7 files changed, 656 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_fifo_gp10b.c b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_fifo_gp10b.c
new file mode 100644
index 00000000..23d945fb
--- /dev/null
+++ b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_fifo_gp10b.c
@@ -0,0 +1,48 @@
1/*
2 * Copyright (c) 2015-2016, 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
14#include "vgpu_fifo_gp10b.h"
15
16static int vgpu_gp10b_fifo_init_engine_info(struct fifo_gk20a *f)
17{
18 struct fifo_engine_info_gk20a *gr_info;
19 struct fifo_engine_info_gk20a *ce_info;
20 const u32 gr_sw_id = ENGINE_GR_GK20A;
21 const u32 ce_sw_id = ENGINE_GRCE_GK20A;
22
23 gk20a_dbg_fn("");
24
25 f->num_engines = 2;
26
27 gr_info = &f->engine_info[0];
28
29 /* FIXME: retrieve this from server */
30 gr_info->runlist_id = 0;
31 gr_info->engine_enum = gr_sw_id;
32 f->active_engines_list[0] = 0;
33
34 ce_info = &f->engine_info[1];
35 ce_info->runlist_id = 0;
36 ce_info->inst_id = 0;
37 ce_info->engine_enum = ce_sw_id;
38 f->active_engines_list[1] = 1;
39
40 return 0;
41}
42
43void vgpu_gp10b_init_fifo_ops(struct gpu_ops *gops)
44{
45 /* syncpoint protection not supported yet */
46 gops->fifo.init_engine_info = vgpu_gp10b_fifo_init_engine_info;
47 gops->fifo.resetup_ramfc = NULL;
48}
diff --git a/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_fifo_gp10b.h b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_fifo_gp10b.h
new file mode 100644
index 00000000..4ede0b6d
--- /dev/null
+++ b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_fifo_gp10b.h
@@ -0,0 +1,21 @@
1/*
2 * Copyright (c) 2015, 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
14#ifndef __VGPU_FIFO_GP10B_H__
15#define __VGPU_FIFO_GP10B_H__
16
17#include "gk20a/gk20a.h"
18
19void vgpu_gp10b_init_fifo_ops(struct gpu_ops *gops);
20
21#endif
diff --git a/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_gr_gp10b.c b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_gr_gp10b.c
new file mode 100644
index 00000000..85dc8c22
--- /dev/null
+++ b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_gr_gp10b.c
@@ -0,0 +1,321 @@
1/*
2 * Copyright (c) 2015-2016, 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
14#include "vgpu/vgpu.h"
15#include "vgpu_gr_gp10b.h"
16#include "vgpu/gm20b/vgpu_gr_gm20b.h"
17
18#include "gp10b/hw_gr_gp10b.h"
19
20static void vgpu_gr_gp10b_free_gr_ctx(struct gk20a *g, struct vm_gk20a *vm,
21 struct gr_ctx_desc *gr_ctx)
22{
23 struct tegra_vgpu_cmd_msg msg = {0};
24 struct tegra_vgpu_gr_ctx_params *p = &msg.params.gr_ctx;
25 int err;
26
27 gk20a_dbg_fn("");
28
29 if (!gr_ctx || !gr_ctx->mem.gpu_va)
30 return;
31
32 msg.cmd = TEGRA_VGPU_CMD_GR_CTX_FREE;
33 msg.handle = vgpu_get_handle(g);
34 p->gr_ctx_handle = gr_ctx->virt_ctx;
35 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
36 WARN_ON(err || msg.ret);
37
38 gk20a_vm_free_va(vm, gr_ctx->mem.gpu_va, gr_ctx->mem.size,
39 gmmu_page_size_kernel);
40
41 gk20a_gmmu_unmap_free(vm, &gr_ctx->t18x.pagepool_ctxsw_buffer);
42 gk20a_gmmu_unmap_free(vm, &gr_ctx->t18x.betacb_ctxsw_buffer);
43 gk20a_gmmu_unmap_free(vm, &gr_ctx->t18x.spill_ctxsw_buffer);
44 gk20a_gmmu_unmap_free(vm, &gr_ctx->t18x.preempt_ctxsw_buffer);
45
46 kfree(gr_ctx);
47}
48
49static int vgpu_gr_gp10b_alloc_gr_ctx(struct gk20a *g,
50 struct gr_ctx_desc **__gr_ctx,
51 struct vm_gk20a *vm,
52 u32 class,
53 u32 flags)
54{
55 struct gr_ctx_desc *gr_ctx;
56 u32 graphics_preempt_mode = 0;
57 u32 compute_preempt_mode = 0;
58 int err;
59
60 gk20a_dbg_fn("");
61
62 err = vgpu_gr_alloc_gr_ctx(g, __gr_ctx, vm, class, flags);
63 if (err)
64 return err;
65
66 gr_ctx = *__gr_ctx;
67
68 if (flags & NVGPU_ALLOC_OBJ_FLAGS_GFXP)
69 graphics_preempt_mode = NVGPU_GRAPHICS_PREEMPTION_MODE_GFXP;
70 if (flags & NVGPU_ALLOC_OBJ_FLAGS_CILP)
71 compute_preempt_mode = NVGPU_COMPUTE_PREEMPTION_MODE_CILP;
72
73 if (graphics_preempt_mode || compute_preempt_mode) {
74 if (g->ops.gr.set_ctxsw_preemption_mode) {
75 err = g->ops.gr.set_ctxsw_preemption_mode(g, gr_ctx, vm,
76 class, graphics_preempt_mode, compute_preempt_mode);
77 if (err) {
78 gk20a_err(dev_from_gk20a(g),
79 "set_ctxsw_preemption_mode failed");
80 goto fail;
81 }
82 } else {
83 err = -ENOSYS;
84 goto fail;
85 }
86 }
87
88 gk20a_dbg_fn("done");
89 return err;
90
91fail:
92 vgpu_gr_gp10b_free_gr_ctx(g, vm, gr_ctx);
93 return err;
94}
95
96static int vgpu_gr_gp10b_set_ctxsw_preemption_mode(struct gk20a *g,
97 struct gr_ctx_desc *gr_ctx,
98 struct vm_gk20a *vm, u32 class,
99 u32 graphics_preempt_mode,
100 u32 compute_preempt_mode)
101{
102 struct tegra_vgpu_cmd_msg msg = {};
103 struct tegra_vgpu_gr_bind_ctxsw_buffers_params *p =
104 &msg.params.gr_bind_ctxsw_buffers;
105 int err = 0;
106
107 WARN_ON(TEGRA_VGPU_GR_BIND_CTXSW_BUFFER_MAX !=
108 TEGRA_VGPU_GR_BIND_CTXSW_BUFFER_LAST);
109
110 if (class == PASCAL_A && g->gr.t18x.ctx_vars.force_preemption_gfxp)
111 graphics_preempt_mode = NVGPU_GRAPHICS_PREEMPTION_MODE_GFXP;
112
113 if (class == PASCAL_COMPUTE_A &&
114 g->gr.t18x.ctx_vars.force_preemption_cilp)
115 compute_preempt_mode = NVGPU_COMPUTE_PREEMPTION_MODE_CILP;
116
117 /* check for invalid combinations */
118 if ((graphics_preempt_mode == 0) && (compute_preempt_mode == 0))
119 return -EINVAL;
120
121 if ((graphics_preempt_mode == NVGPU_GRAPHICS_PREEMPTION_MODE_GFXP) &&
122 (compute_preempt_mode == NVGPU_COMPUTE_PREEMPTION_MODE_CILP))
123 return -EINVAL;
124
125 /* set preemption modes */
126 switch (graphics_preempt_mode) {
127 case NVGPU_GRAPHICS_PREEMPTION_MODE_GFXP:
128 {
129 u32 spill_size =
130 gr_gpc0_swdx_rm_spill_buffer_size_256b_default_v() *
131 gr_gpc0_swdx_rm_spill_buffer_size_256b_byte_granularity_v();
132 u32 pagepool_size = g->ops.gr.pagepool_default_size(g) *
133 gr_scc_pagepool_total_pages_byte_granularity_v();
134 u32 betacb_size = g->gr.attrib_cb_default_size +
135 (gr_gpc0_ppc0_cbm_beta_cb_size_v_gfxp_v() -
136 gr_gpc0_ppc0_cbm_beta_cb_size_v_default_v());
137 u32 attrib_cb_size = (betacb_size + g->gr.alpha_cb_size) *
138 gr_gpc0_ppc0_cbm_beta_cb_size_v_granularity_v() *
139 g->gr.max_tpc_count;
140 struct mem_desc *desc;
141
142 attrib_cb_size = ALIGN(attrib_cb_size, 128);
143
144 gk20a_dbg_info("gfxp context preempt size=%d",
145 g->gr.t18x.ctx_vars.preempt_image_size);
146 gk20a_dbg_info("gfxp context spill size=%d", spill_size);
147 gk20a_dbg_info("gfxp context pagepool size=%d", pagepool_size);
148 gk20a_dbg_info("gfxp context attrib cb size=%d",
149 attrib_cb_size);
150
151 err = gr_gp10b_alloc_buffer(vm,
152 g->gr.t18x.ctx_vars.preempt_image_size,
153 &gr_ctx->t18x.preempt_ctxsw_buffer);
154 if (err) {
155 err = -ENOMEM;
156 goto fail;
157 }
158 desc = &gr_ctx->t18x.preempt_ctxsw_buffer;
159 p->gpu_va[TEGRA_VGPU_GR_BIND_CTXSW_BUFFER_MAIN] = desc->gpu_va;
160 p->size[TEGRA_VGPU_GR_BIND_CTXSW_BUFFER_MAIN] = desc->size;
161
162 err = gr_gp10b_alloc_buffer(vm,
163 spill_size,
164 &gr_ctx->t18x.spill_ctxsw_buffer);
165 if (err) {
166 err = -ENOMEM;
167 goto fail;
168 }
169 desc = &gr_ctx->t18x.spill_ctxsw_buffer;
170 p->gpu_va[TEGRA_VGPU_GR_BIND_CTXSW_BUFFER_SPILL] = desc->gpu_va;
171 p->size[TEGRA_VGPU_GR_BIND_CTXSW_BUFFER_SPILL] = desc->size;
172
173 err = gr_gp10b_alloc_buffer(vm,
174 pagepool_size,
175 &gr_ctx->t18x.pagepool_ctxsw_buffer);
176 if (err) {
177 err = -ENOMEM;
178 goto fail;
179 }
180 desc = &gr_ctx->t18x.pagepool_ctxsw_buffer;
181 p->gpu_va[TEGRA_VGPU_GR_BIND_CTXSW_BUFFER_PAGEPOOL] =
182 desc->gpu_va;
183 p->size[TEGRA_VGPU_GR_BIND_CTXSW_BUFFER_PAGEPOOL] = desc->size;
184
185 err = gr_gp10b_alloc_buffer(vm,
186 attrib_cb_size,
187 &gr_ctx->t18x.betacb_ctxsw_buffer);
188 if (err) {
189 err = -ENOMEM;
190 goto fail;
191 }
192 desc = &gr_ctx->t18x.betacb_ctxsw_buffer;
193 p->gpu_va[TEGRA_VGPU_GR_BIND_CTXSW_BUFFER_BETACB] =
194 desc->gpu_va;
195 p->size[TEGRA_VGPU_GR_BIND_CTXSW_BUFFER_BETACB] = desc->size;
196
197 gr_ctx->graphics_preempt_mode = NVGPU_GRAPHICS_PREEMPTION_MODE_GFXP;
198 p->mode = TEGRA_VGPU_GR_CTXSW_PREEMPTION_MODE_GFX_GFXP;
199 break;
200 }
201 case NVGPU_GRAPHICS_PREEMPTION_MODE_WFI:
202 gr_ctx->graphics_preempt_mode = graphics_preempt_mode;
203 break;
204
205 default:
206 break;
207 }
208
209 if (class == PASCAL_COMPUTE_A) {
210 switch (compute_preempt_mode) {
211 case NVGPU_COMPUTE_PREEMPTION_MODE_WFI:
212 gr_ctx->compute_preempt_mode =
213 NVGPU_COMPUTE_PREEMPTION_MODE_WFI;
214 p->mode = TEGRA_VGPU_GR_CTXSW_PREEMPTION_MODE_WFI;
215 break;
216 case NVGPU_COMPUTE_PREEMPTION_MODE_CTA:
217 gr_ctx->compute_preempt_mode =
218 NVGPU_COMPUTE_PREEMPTION_MODE_CTA;
219 p->mode =
220 TEGRA_VGPU_GR_CTXSW_PREEMPTION_MODE_COMPUTE_CTA;
221 break;
222 case NVGPU_COMPUTE_PREEMPTION_MODE_CILP:
223 gr_ctx->compute_preempt_mode =
224 NVGPU_COMPUTE_PREEMPTION_MODE_CILP;
225 p->mode =
226 TEGRA_VGPU_GR_CTXSW_PREEMPTION_MODE_COMPUTE_CILP;
227 break;
228 default:
229 break;
230 }
231 }
232
233 if (gr_ctx->graphics_preempt_mode || gr_ctx->compute_preempt_mode) {
234 msg.cmd = TEGRA_VGPU_CMD_CHANNEL_BIND_GR_CTXSW_BUFFERS;
235 msg.handle = vgpu_get_handle(g);
236 p->gr_ctx_handle = gr_ctx->virt_ctx;
237 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
238 if (err || msg.ret) {
239 err = -ENOMEM;
240 goto fail;
241 }
242 }
243
244 return err;
245
246fail:
247 gk20a_err(dev_from_gk20a(g), "%s failed %d", __func__, err);
248 return err;
249}
250
251static int vgpu_gr_gp10b_set_preemption_mode(struct channel_gk20a *ch,
252 u32 graphics_preempt_mode,
253 u32 compute_preempt_mode)
254{
255 struct gr_ctx_desc *gr_ctx = ch->ch_ctx.gr_ctx;
256 struct gk20a *g = ch->g;
257 struct tsg_gk20a *tsg;
258 struct vm_gk20a *vm;
259 u32 class;
260 int err;
261
262 class = ch->obj_class;
263 if (!class)
264 return -EINVAL;
265
266 /* preemption already set ? */
267 if (gr_ctx->graphics_preempt_mode || gr_ctx->compute_preempt_mode)
268 return -EINVAL;
269
270 if (gk20a_is_channel_marked_as_tsg(ch)) {
271 tsg = &g->fifo.tsg[ch->tsgid];
272 vm = tsg->vm;
273 } else {
274 vm = ch->vm;
275 }
276
277 if (g->ops.gr.set_ctxsw_preemption_mode) {
278 err = g->ops.gr.set_ctxsw_preemption_mode(g, gr_ctx, vm, class,
279 graphics_preempt_mode,
280 compute_preempt_mode);
281 if (err) {
282 gk20a_err(dev_from_gk20a(g),
283 "set_ctxsw_preemption_mode failed");
284 return err;
285 }
286 } else {
287 err = -ENOSYS;
288 }
289
290 return err;
291}
292
293static int vgpu_gr_gp10b_init_ctx_state(struct gk20a *g)
294{
295 int err;
296
297 gk20a_dbg_fn("");
298
299 err = vgpu_gr_init_ctx_state(g);
300 if (err)
301 return err;
302
303 vgpu_get_attribute(vgpu_get_handle(g),
304 TEGRA_VGPU_ATTRIB_PREEMPT_CTX_SIZE,
305 &g->gr.t18x.ctx_vars.preempt_image_size);
306 if (!g->gr.t18x.ctx_vars.preempt_image_size)
307 return -ENXIO;
308
309 return 0;
310}
311
312void vgpu_gp10b_init_gr_ops(struct gpu_ops *gops)
313{
314 vgpu_gm20b_init_gr_ops(gops);
315 gops->gr.alloc_gr_ctx = vgpu_gr_gp10b_alloc_gr_ctx;
316 gops->gr.free_gr_ctx = vgpu_gr_gp10b_free_gr_ctx;
317 gops->gr.init_ctx_state = vgpu_gr_gp10b_init_ctx_state;
318 gops->gr.set_preemption_mode = vgpu_gr_gp10b_set_preemption_mode;
319 gops->gr.set_ctxsw_preemption_mode =
320 vgpu_gr_gp10b_set_ctxsw_preemption_mode;
321}
diff --git a/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_gr_gp10b.h b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_gr_gp10b.h
new file mode 100644
index 00000000..b3be49a7
--- /dev/null
+++ b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_gr_gp10b.h
@@ -0,0 +1,21 @@
1/*
2 * Copyright (c) 2015, 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
14#ifndef __VGPU_GR_GP10B_H__
15#define __VGPU_GR_GP10B_H__
16
17#include "gk20a/gk20a.h"
18
19void vgpu_gp10b_init_gr_ops(struct gpu_ops *gops);
20
21#endif
diff --git a/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_hal_gp10b.c b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_hal_gp10b.c
new file mode 100644
index 00000000..b665a8dd
--- /dev/null
+++ b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_hal_gp10b.c
@@ -0,0 +1,36 @@
1/*
2 * Copyright (c) 2015, 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
14#include "vgpu/vgpu.h"
15#include "gp10b/hal_gp10b.h"
16#include "vgpu_gr_gp10b.h"
17#include "vgpu_fifo_gp10b.h"
18#include "vgpu_mm_gp10b.h"
19#include "nvgpu_gpuid_t18x.h"
20
21int vgpu_gp10b_init_hal(struct gk20a *g)
22{
23 int err;
24
25 gk20a_dbg_fn("");
26
27 err = gp10b_init_hal(g);
28 if (err)
29 return err;
30
31 vgpu_init_hal_common(g);
32 vgpu_gp10b_init_gr_ops(&g->ops);
33 vgpu_gp10b_init_fifo_ops(&g->ops);
34 vgpu_gp10b_init_mm_ops(&g->ops);
35 return 0;
36}
diff --git a/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_mm_gp10b.c b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_mm_gp10b.c
new file mode 100644
index 00000000..66fda2d9
--- /dev/null
+++ b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_mm_gp10b.c
@@ -0,0 +1,188 @@
1/*
2 * Virtualized GPU Memory Management
3 *
4 * Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 */
15
16#include <linux/dma-mapping.h>
17#include "vgpu/vgpu.h"
18#include "vgpu_mm_gp10b.h"
19#include "gk20a/semaphore_gk20a.h"
20#include "gk20a/mm_gk20a.h"
21
22static int vgpu_gp10b_init_mm_setup_hw(struct gk20a *g)
23{
24 g->mm.bypass_smmu = true;
25 g->mm.disable_bigpage = true;
26 return 0;
27}
28
29static inline int add_mem_desc(struct tegra_vgpu_mem_desc *mem_desc,
30 u64 addr, u64 size, size_t *oob_size)
31{
32 if (*oob_size < sizeof(*mem_desc))
33 return -ENOMEM;
34
35 mem_desc->addr = addr;
36 mem_desc->length = size;
37 *oob_size -= sizeof(*mem_desc);
38 return 0;
39}
40
41static u64 vgpu_gp10b_locked_gmmu_map(struct vm_gk20a *vm,
42 u64 map_offset,
43 struct sg_table *sgt,
44 u64 buffer_offset,
45 u64 size,
46 int pgsz_idx,
47 u8 kind_v,
48 u32 ctag_offset,
49 u32 flags,
50 int rw_flag,
51 bool clear_ctags,
52 bool sparse,
53 bool priv,
54 struct vm_gk20a_mapping_batch *batch,
55 enum gk20a_aperture aperture)
56{
57 int err = 0;
58 struct device *d = dev_from_vm(vm);
59 struct gk20a *g = gk20a_from_vm(vm);
60 struct tegra_vgpu_cmd_msg msg;
61 struct tegra_vgpu_as_map_ex_params *p = &msg.params.as_map_ex;
62 struct tegra_vgpu_mem_desc *mem_desc;
63 u32 page_size = vm->gmmu_page_sizes[pgsz_idx];
64 u64 space_to_skip = buffer_offset;
65 u64 buffer_size = 0;
66 u32 mem_desc_count = 0;
67 struct scatterlist *sgl;
68 void *handle = NULL;
69 size_t oob_size;
70 u8 prot;
71
72 gk20a_dbg_fn("");
73
74 /* FIXME: add support for sparse mappings */
75
76 if (WARN_ON(!sgt) || WARN_ON(!g->mm.bypass_smmu))
77 return 0;
78
79 if (space_to_skip & (page_size - 1))
80 return 0;
81
82 /* Allocate (or validate when map_offset != 0) the virtual address. */
83 if (!map_offset) {
84 map_offset = gk20a_vm_alloc_va(vm, size, pgsz_idx);
85 if (!map_offset) {
86 gk20a_err(d, "failed to allocate va space");
87 err = -ENOMEM;
88 goto fail;
89 }
90 }
91
92 handle = tegra_gr_comm_oob_get_ptr(TEGRA_GR_COMM_CTX_CLIENT,
93 tegra_gr_comm_get_server_vmid(),
94 TEGRA_VGPU_QUEUE_CMD,
95 (void **)&mem_desc, &oob_size);
96 if (!handle) {
97 err = -EINVAL;
98 goto fail;
99 }
100
101 sgl = sgt->sgl;
102 while (space_to_skip && sgl &&
103 (space_to_skip + page_size > sgl->length)) {
104 space_to_skip -= sgl->length;
105 sgl = sg_next(sgl);
106 }
107 WARN_ON(!sgl);
108
109 if (add_mem_desc(&mem_desc[mem_desc_count++],
110 sg_phys(sgl) + space_to_skip,
111 sgl->length - space_to_skip,
112 &oob_size)) {
113 err = -ENOMEM;
114 goto fail;
115 }
116 buffer_size += sgl->length - space_to_skip;
117
118 sgl = sg_next(sgl);
119 while (sgl && buffer_size < size) {
120 if (add_mem_desc(&mem_desc[mem_desc_count++], sg_phys(sgl),
121 sgl->length, &oob_size)) {
122 err = -ENOMEM;
123 goto fail;
124 }
125
126 buffer_size += sgl->length;
127 sgl = sg_next(sgl);
128 }
129
130 if (rw_flag == gk20a_mem_flag_read_only)
131 prot = TEGRA_VGPU_MAP_PROT_READ_ONLY;
132 else if (rw_flag == gk20a_mem_flag_write_only)
133 prot = TEGRA_VGPU_MAP_PROT_WRITE_ONLY;
134 else
135 prot = TEGRA_VGPU_MAP_PROT_NONE;
136
137 if (pgsz_idx == gmmu_page_size_kernel) {
138 if (page_size == vm->gmmu_page_sizes[gmmu_page_size_small]) {
139 pgsz_idx = gmmu_page_size_small;
140 } else if (page_size ==
141 vm->gmmu_page_sizes[gmmu_page_size_big]) {
142 pgsz_idx = gmmu_page_size_big;
143 } else {
144 gk20a_err(d, "invalid kernel page size %d\n",
145 page_size);
146 goto fail;
147 }
148 }
149
150 msg.cmd = TEGRA_VGPU_CMD_AS_MAP_EX;
151 msg.handle = vgpu_get_handle(g);
152 p->handle = vm->handle;
153 p->gpu_va = map_offset;
154 p->size = size;
155 p->mem_desc_count = mem_desc_count;
156 p->pgsz_idx = pgsz_idx;
157 p->iova = 0;
158 p->kind = kind_v;
159 p->cacheable =
160 (flags & NVGPU_MAP_BUFFER_FLAGS_CACHEABLE_TRUE) ? 1 : 0;
161 p->prot = prot;
162 p->ctag_offset = ctag_offset;
163 p->clear_ctags = clear_ctags;
164 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
165 if (err || msg.ret)
166 goto fail;
167
168 /* TLB invalidate handled on server side */
169
170 tegra_gr_comm_oob_put_ptr(handle);
171 return map_offset;
172fail:
173 if (handle)
174 tegra_gr_comm_oob_put_ptr(handle);
175 gk20a_err(d, "%s: failed with err=%d\n", __func__, err);
176 return 0;
177}
178
179void vgpu_gp10b_init_mm_ops(struct gpu_ops *gops)
180{
181 gk20a_dbg_fn("");
182
183 gops->mm.gmmu_map = vgpu_gp10b_locked_gmmu_map;
184 gops->mm.init_mm_setup_hw = vgpu_gp10b_init_mm_setup_hw;
185
186 /* FIXME: add support for sparse mappings */
187 gops->mm.support_sparse = NULL;
188}
diff --git a/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_mm_gp10b.h b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_mm_gp10b.h
new file mode 100644
index 00000000..5bdc9d1b
--- /dev/null
+++ b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_mm_gp10b.h
@@ -0,0 +1,21 @@
1/*
2 * Copyright (c) 2015, 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
14#ifndef __VGPU_MM_GP10B_H__
15#define __VGPU_MM_GP10B_H__
16
17#include "gk20a/gk20a.h"
18
19void vgpu_gp10b_init_mm_ops(struct gpu_ops *gops);
20
21#endif