summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_gr_gp10b.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/vgpu/gp10b/vgpu_gr_gp10b.c')
-rw-r--r--drivers/gpu/nvgpu/vgpu/gp10b/vgpu_gr_gp10b.c321
1 files changed, 321 insertions, 0 deletions
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}