summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/vgpu/gr_vgpu.c
diff options
context:
space:
mode:
authorRichard Zhao <rizhao@nvidia.com>2018-01-30 02:24:37 -0500
committermobile promotions <svcmobile_promotions@nvidia.com>2018-02-27 17:30:52 -0500
commit6393eddfa996fba03464f897b85aa5ec79860fed (patch)
tree557ebe9be93e2b0464118e7d8ec019d9d5dbae5f /drivers/gpu/nvgpu/vgpu/gr_vgpu.c
parent7932568b7fe9e16b2b83bc58b2b3686c0d5e52d4 (diff)
gpu: nvgpu: vgpu: move common files out of linux folder
Most of files have been moved out of linux folder. More code could be common as halifying going on. Jira EVLR-2364 Change-Id: Ia9dbdbc82f45ceefe5c788eac7517000cd455d5e Signed-off-by: Richard Zhao <rizhao@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1649947 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/vgpu/gr_vgpu.c')
-rw-r--r--drivers/gpu/nvgpu/vgpu/gr_vgpu.c1283
1 files changed, 1283 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/vgpu/gr_vgpu.c b/drivers/gpu/nvgpu/vgpu/gr_vgpu.c
new file mode 100644
index 00000000..ee5a5d36
--- /dev/null
+++ b/drivers/gpu/nvgpu/vgpu/gr_vgpu.c
@@ -0,0 +1,1283 @@
1/*
2 * Virtualized GPU Graphics
3 *
4 * Copyright (c) 2014-2018, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#include <nvgpu/kmem.h>
26#include <nvgpu/bug.h>
27#include <nvgpu/dma.h>
28#include <nvgpu/error_notifier.h>
29#include <nvgpu/dma.h>
30#include <nvgpu/vgpu/vgpu_ivc.h>
31#include <nvgpu/vgpu/vgpu.h>
32
33#include "gr_vgpu.h"
34#include "gk20a/gk20a.h"
35#include "gk20a/dbg_gpu_gk20a.h"
36#include "gk20a/channel_gk20a.h"
37#include "gk20a/tsg_gk20a.h"
38
39#include <nvgpu/hw/gk20a/hw_gr_gk20a.h>
40#include <nvgpu/hw/gk20a/hw_ctxsw_prog_gk20a.h>
41
42void vgpu_gr_detect_sm_arch(struct gk20a *g)
43{
44 struct vgpu_priv_data *priv = vgpu_get_priv_data(g);
45
46 gk20a_dbg_fn("");
47
48 g->params.sm_arch_sm_version =
49 priv->constants.sm_arch_sm_version;
50 g->params.sm_arch_spa_version =
51 priv->constants.sm_arch_spa_version;
52 g->params.sm_arch_warp_count =
53 priv->constants.sm_arch_warp_count;
54}
55
56int vgpu_gr_commit_inst(struct channel_gk20a *c, u64 gpu_va)
57{
58 struct tegra_vgpu_cmd_msg msg;
59 struct tegra_vgpu_ch_ctx_params *p = &msg.params.ch_ctx;
60 int err;
61
62 gk20a_dbg_fn("");
63
64 msg.cmd = TEGRA_VGPU_CMD_CHANNEL_COMMIT_GR_CTX;
65 msg.handle = vgpu_get_handle(c->g);
66 p->handle = c->virt_ctx;
67 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
68
69 return (err || msg.ret) ? -1 : 0;
70}
71
72static int vgpu_gr_commit_global_ctx_buffers(struct gk20a *g,
73 struct channel_gk20a *c, bool patch)
74{
75 struct tegra_vgpu_cmd_msg msg;
76 struct tegra_vgpu_ch_ctx_params *p = &msg.params.ch_ctx;
77 int err;
78
79 gk20a_dbg_fn("");
80
81 msg.cmd = TEGRA_VGPU_CMD_CHANNEL_COMMIT_GR_GLOBAL_CTX;
82 msg.handle = vgpu_get_handle(g);
83 p->handle = c->virt_ctx;
84 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
85
86 return (err || msg.ret) ? -1 : 0;
87}
88
89/* load saved fresh copy of gloden image into channel gr_ctx */
90static int vgpu_gr_load_golden_ctx_image(struct gk20a *g,
91 struct channel_gk20a *c)
92{
93 struct tegra_vgpu_cmd_msg msg;
94 struct tegra_vgpu_ch_ctx_params *p = &msg.params.ch_ctx;
95 int err;
96
97 gk20a_dbg_fn("");
98
99 msg.cmd = TEGRA_VGPU_CMD_CHANNEL_LOAD_GR_GOLDEN_CTX;
100 msg.handle = vgpu_get_handle(g);
101 p->handle = c->virt_ctx;
102 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
103
104 return (err || msg.ret) ? -1 : 0;
105}
106
107int vgpu_gr_init_ctx_state(struct gk20a *g)
108{
109 struct gr_gk20a *gr = &g->gr;
110 struct vgpu_priv_data *priv = vgpu_get_priv_data(g);
111
112 gk20a_dbg_fn("");
113
114 g->gr.ctx_vars.golden_image_size = priv->constants.golden_ctx_size;
115 g->gr.ctx_vars.zcull_ctxsw_image_size = priv->constants.zcull_ctx_size;
116 g->gr.ctx_vars.pm_ctxsw_image_size = priv->constants.hwpm_ctx_size;
117 if (!g->gr.ctx_vars.golden_image_size ||
118 !g->gr.ctx_vars.zcull_ctxsw_image_size ||
119 !g->gr.ctx_vars.pm_ctxsw_image_size)
120 return -ENXIO;
121
122 gr->ctx_vars.buffer_size = g->gr.ctx_vars.golden_image_size;
123 g->gr.ctx_vars.priv_access_map_size = 512 * 1024;
124 return 0;
125}
126
127static int vgpu_gr_alloc_global_ctx_buffers(struct gk20a *g)
128{
129 struct gr_gk20a *gr = &g->gr;
130 int attr_buffer_size;
131
132 u32 cb_buffer_size = gr->bundle_cb_default_size *
133 gr_scc_bundle_cb_size_div_256b_byte_granularity_v();
134
135 u32 pagepool_buffer_size = g->ops.gr.pagepool_default_size(g) *
136 gr_scc_pagepool_total_pages_byte_granularity_v();
137
138 gk20a_dbg_fn("");
139
140 attr_buffer_size = g->ops.gr.calc_global_ctx_buffer_size(g);
141
142 gk20a_dbg_info("cb_buffer_size : %d", cb_buffer_size);
143 gr->global_ctx_buffer[CIRCULAR].mem.size = cb_buffer_size;
144
145 gk20a_dbg_info("pagepool_buffer_size : %d", pagepool_buffer_size);
146 gr->global_ctx_buffer[PAGEPOOL].mem.size = pagepool_buffer_size;
147
148 gk20a_dbg_info("attr_buffer_size : %d", attr_buffer_size);
149 gr->global_ctx_buffer[ATTRIBUTE].mem.size = attr_buffer_size;
150
151 gk20a_dbg_info("priv access map size : %d",
152 gr->ctx_vars.priv_access_map_size);
153 gr->global_ctx_buffer[PRIV_ACCESS_MAP].mem.size =
154 gr->ctx_vars.priv_access_map_size;
155
156 return 0;
157}
158
159static int vgpu_gr_map_global_ctx_buffers(struct gk20a *g,
160 struct channel_gk20a *c)
161{
162 struct tegra_vgpu_cmd_msg msg;
163 struct tegra_vgpu_ch_ctx_params *p = &msg.params.ch_ctx;
164 struct vm_gk20a *ch_vm = c->vm;
165 struct tsg_gk20a *tsg;
166 u64 *g_bfr_va;
167 u64 *g_bfr_size;
168 struct gr_gk20a *gr = &g->gr;
169 u64 gpu_va;
170 u32 i;
171 int err;
172
173 gk20a_dbg_fn("");
174
175 tsg = tsg_gk20a_from_ch(c);
176 if (!tsg)
177 return -EINVAL;
178
179 g_bfr_va = tsg->gr_ctx.global_ctx_buffer_va;
180 g_bfr_size = tsg->gr_ctx.global_ctx_buffer_size;
181
182 /* Circular Buffer */
183 gpu_va = __nvgpu_vm_alloc_va(ch_vm,
184 gr->global_ctx_buffer[CIRCULAR].mem.size,
185 gmmu_page_size_kernel);
186
187 if (!gpu_va)
188 goto clean_up;
189 g_bfr_va[CIRCULAR_VA] = gpu_va;
190 g_bfr_size[CIRCULAR_VA] = gr->global_ctx_buffer[CIRCULAR].mem.size;
191
192 /* Attribute Buffer */
193 gpu_va = __nvgpu_vm_alloc_va(ch_vm,
194 gr->global_ctx_buffer[ATTRIBUTE].mem.size,
195 gmmu_page_size_kernel);
196
197 if (!gpu_va)
198 goto clean_up;
199 g_bfr_va[ATTRIBUTE_VA] = gpu_va;
200 g_bfr_size[ATTRIBUTE_VA] = gr->global_ctx_buffer[ATTRIBUTE].mem.size;
201
202 /* Page Pool */
203 gpu_va = __nvgpu_vm_alloc_va(ch_vm,
204 gr->global_ctx_buffer[PAGEPOOL].mem.size,
205 gmmu_page_size_kernel);
206 if (!gpu_va)
207 goto clean_up;
208 g_bfr_va[PAGEPOOL_VA] = gpu_va;
209 g_bfr_size[PAGEPOOL_VA] = gr->global_ctx_buffer[PAGEPOOL].mem.size;
210
211 /* Priv register Access Map */
212 gpu_va = __nvgpu_vm_alloc_va(ch_vm,
213 gr->global_ctx_buffer[PRIV_ACCESS_MAP].mem.size,
214 gmmu_page_size_kernel);
215 if (!gpu_va)
216 goto clean_up;
217 g_bfr_va[PRIV_ACCESS_MAP_VA] = gpu_va;
218 g_bfr_size[PRIV_ACCESS_MAP_VA] =
219 gr->global_ctx_buffer[PRIV_ACCESS_MAP].mem.size;
220
221 msg.cmd = TEGRA_VGPU_CMD_CHANNEL_MAP_GR_GLOBAL_CTX;
222 msg.handle = vgpu_get_handle(g);
223 p->handle = c->virt_ctx;
224 p->cb_va = g_bfr_va[CIRCULAR_VA];
225 p->attr_va = g_bfr_va[ATTRIBUTE_VA];
226 p->page_pool_va = g_bfr_va[PAGEPOOL_VA];
227 p->priv_access_map_va = g_bfr_va[PRIV_ACCESS_MAP_VA];
228 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
229 if (err || msg.ret)
230 goto clean_up;
231
232 tsg->gr_ctx.global_ctx_buffer_mapped = true;
233 return 0;
234
235 clean_up:
236 for (i = 0; i < NR_GLOBAL_CTX_BUF_VA; i++) {
237 if (g_bfr_va[i]) {
238 __nvgpu_vm_free_va(ch_vm, g_bfr_va[i],
239 gmmu_page_size_kernel);
240 g_bfr_va[i] = 0;
241 }
242 }
243 return -ENOMEM;
244}
245
246static void vgpu_gr_unmap_global_ctx_buffers(struct tsg_gk20a *tsg)
247{
248 struct vm_gk20a *ch_vm = tsg->vm;
249 u64 *g_bfr_va = tsg->gr_ctx.global_ctx_buffer_va;
250 u64 *g_bfr_size = tsg->gr_ctx.global_ctx_buffer_size;
251 u32 i;
252
253 gk20a_dbg_fn("");
254
255 if (tsg->gr_ctx.global_ctx_buffer_mapped) {
256 /* server will unmap on channel close */
257
258 for (i = 0; i < NR_GLOBAL_CTX_BUF_VA; i++) {
259 if (g_bfr_va[i]) {
260 __nvgpu_vm_free_va(ch_vm, g_bfr_va[i],
261 gmmu_page_size_kernel);
262 g_bfr_va[i] = 0;
263 g_bfr_size[i] = 0;
264 }
265 }
266
267 tsg->gr_ctx.global_ctx_buffer_mapped = false;
268 }
269}
270
271int vgpu_gr_alloc_gr_ctx(struct gk20a *g,
272 struct nvgpu_gr_ctx *gr_ctx,
273 struct vm_gk20a *vm,
274 u32 class,
275 u32 flags)
276{
277 struct tegra_vgpu_cmd_msg msg = {0};
278 struct tegra_vgpu_gr_ctx_params *p = &msg.params.gr_ctx;
279 struct gr_gk20a *gr = &g->gr;
280 int err;
281
282 gk20a_dbg_fn("");
283
284 if (gr->ctx_vars.buffer_size == 0)
285 return 0;
286
287 /* alloc channel gr ctx buffer */
288 gr->ctx_vars.buffer_size = gr->ctx_vars.golden_image_size;
289 gr->ctx_vars.buffer_total_size = gr->ctx_vars.golden_image_size;
290
291 gr_ctx->mem.gpu_va = __nvgpu_vm_alloc_va(vm,
292 gr->ctx_vars.buffer_total_size,
293 gmmu_page_size_kernel);
294
295 if (!gr_ctx->mem.gpu_va)
296 return -ENOMEM;
297 gr_ctx->mem.size = gr->ctx_vars.buffer_total_size;
298 gr_ctx->mem.aperture = APERTURE_SYSMEM;
299
300 msg.cmd = TEGRA_VGPU_CMD_GR_CTX_ALLOC;
301 msg.handle = vgpu_get_handle(g);
302 p->as_handle = vm->handle;
303 p->gr_ctx_va = gr_ctx->mem.gpu_va;
304 p->class_num = class;
305 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
306 err = err ? err : msg.ret;
307
308 if (unlikely(err)) {
309 nvgpu_err(g, "fail to alloc gr_ctx");
310 __nvgpu_vm_free_va(vm, gr_ctx->mem.gpu_va,
311 gmmu_page_size_kernel);
312 gr_ctx->mem.aperture = APERTURE_INVALID;
313 } else {
314 gr_ctx->virt_ctx = p->gr_ctx_handle;
315 }
316
317 return err;
318}
319
320static int vgpu_gr_alloc_channel_patch_ctx(struct gk20a *g,
321 struct channel_gk20a *c)
322{
323 struct tsg_gk20a *tsg;
324 struct patch_desc *patch_ctx;
325 struct vm_gk20a *ch_vm = c->vm;
326 struct tegra_vgpu_cmd_msg msg;
327 struct tegra_vgpu_ch_ctx_params *p = &msg.params.ch_ctx;
328 int err;
329
330 gk20a_dbg_fn("");
331
332 tsg = tsg_gk20a_from_ch(c);
333 if (!tsg)
334 return -EINVAL;
335
336 patch_ctx = &tsg->gr_ctx.patch_ctx;
337 patch_ctx->mem.size = 128 * sizeof(u32);
338 patch_ctx->mem.gpu_va = __nvgpu_vm_alloc_va(ch_vm,
339 patch_ctx->mem.size,
340 gmmu_page_size_kernel);
341 if (!patch_ctx->mem.gpu_va)
342 return -ENOMEM;
343
344 msg.cmd = TEGRA_VGPU_CMD_CHANNEL_ALLOC_GR_PATCH_CTX;
345 msg.handle = vgpu_get_handle(g);
346 p->handle = c->virt_ctx;
347 p->patch_ctx_va = patch_ctx->mem.gpu_va;
348 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
349 if (err || msg.ret) {
350 __nvgpu_vm_free_va(ch_vm, patch_ctx->mem.gpu_va,
351 gmmu_page_size_kernel);
352 err = -ENOMEM;
353 }
354
355 return err;
356}
357
358static void vgpu_gr_free_channel_patch_ctx(struct tsg_gk20a *tsg)
359{
360 struct patch_desc *patch_ctx = &tsg->gr_ctx.patch_ctx;
361
362 gk20a_dbg_fn("");
363
364 if (patch_ctx->mem.gpu_va) {
365 /* server will free on channel close */
366
367 __nvgpu_vm_free_va(tsg->vm, patch_ctx->mem.gpu_va,
368 gmmu_page_size_kernel);
369 patch_ctx->mem.gpu_va = 0;
370 }
371}
372
373static void vgpu_gr_free_channel_pm_ctx(struct tsg_gk20a *tsg)
374{
375 struct nvgpu_gr_ctx *ch_ctx = &tsg->gr_ctx;
376 struct pm_ctx_desc *pm_ctx = &ch_ctx->pm_ctx;
377
378 gk20a_dbg_fn("");
379
380 /* check if hwpm was ever initialized. If not, nothing to do */
381 if (pm_ctx->mem.gpu_va == 0)
382 return;
383
384 /* server will free on channel close */
385
386 __nvgpu_vm_free_va(tsg->vm, pm_ctx->mem.gpu_va,
387 gmmu_page_size_kernel);
388 pm_ctx->mem.gpu_va = 0;
389}
390
391void vgpu_gr_free_gr_ctx(struct gk20a *g,
392 struct vm_gk20a *vm, struct nvgpu_gr_ctx *gr_ctx)
393{
394 struct tsg_gk20a *tsg;
395
396 gk20a_dbg_fn("");
397
398 if (gr_ctx->mem.gpu_va) {
399 struct tegra_vgpu_cmd_msg msg;
400 struct tegra_vgpu_gr_ctx_params *p = &msg.params.gr_ctx;
401 int err;
402
403 msg.cmd = TEGRA_VGPU_CMD_GR_CTX_FREE;
404 msg.handle = vgpu_get_handle(g);
405 p->gr_ctx_handle = gr_ctx->virt_ctx;
406 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
407 WARN_ON(err || msg.ret);
408
409 __nvgpu_vm_free_va(vm, gr_ctx->mem.gpu_va,
410 gmmu_page_size_kernel);
411
412 tsg = &g->fifo.tsg[gr_ctx->tsgid];
413 vgpu_gr_unmap_global_ctx_buffers(tsg);
414 vgpu_gr_free_channel_patch_ctx(tsg);
415 vgpu_gr_free_channel_pm_ctx(tsg);
416
417 nvgpu_dma_unmap_free(vm, &gr_ctx->pagepool_ctxsw_buffer);
418 nvgpu_dma_unmap_free(vm, &gr_ctx->betacb_ctxsw_buffer);
419 nvgpu_dma_unmap_free(vm, &gr_ctx->spill_ctxsw_buffer);
420 nvgpu_dma_unmap_free(vm, &gr_ctx->preempt_ctxsw_buffer);
421
422 memset(gr_ctx, 0, sizeof(*gr_ctx));
423 }
424}
425
426static int vgpu_gr_ch_bind_gr_ctx(struct channel_gk20a *c)
427{
428 struct tsg_gk20a *tsg;
429 struct nvgpu_gr_ctx *gr_ctx;
430 struct tegra_vgpu_cmd_msg msg = {0};
431 struct tegra_vgpu_channel_bind_gr_ctx_params *p =
432 &msg.params.ch_bind_gr_ctx;
433 int err;
434
435 tsg = tsg_gk20a_from_ch(c);
436 if (!tsg)
437 return -EINVAL;
438
439 gr_ctx = &tsg->gr_ctx;
440
441 msg.cmd = TEGRA_VGPU_CMD_CHANNEL_BIND_GR_CTX;
442 msg.handle = vgpu_get_handle(c->g);
443 p->ch_handle = c->virt_ctx;
444 p->gr_ctx_handle = gr_ctx->virt_ctx;
445 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
446 err = err ? err : msg.ret;
447 WARN_ON(err);
448
449 return err;
450}
451
452static int vgpu_gr_tsg_bind_gr_ctx(struct tsg_gk20a *tsg)
453{
454 struct nvgpu_gr_ctx *gr_ctx = &tsg->gr_ctx;
455 struct tegra_vgpu_cmd_msg msg = {0};
456 struct tegra_vgpu_tsg_bind_gr_ctx_params *p =
457 &msg.params.tsg_bind_gr_ctx;
458 int err;
459
460 msg.cmd = TEGRA_VGPU_CMD_TSG_BIND_GR_CTX;
461 msg.handle = vgpu_get_handle(tsg->g);
462 p->tsg_id = tsg->tsgid;
463 p->gr_ctx_handle = gr_ctx->virt_ctx;
464 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
465 err = err ? err : msg.ret;
466 WARN_ON(err);
467
468 return err;
469}
470
471int vgpu_gr_alloc_obj_ctx(struct channel_gk20a *c, u32 class_num, u32 flags)
472{
473 struct gk20a *g = c->g;
474 struct fifo_gk20a *f = &g->fifo;
475 struct nvgpu_gr_ctx *gr_ctx = NULL;
476 struct tsg_gk20a *tsg = NULL;
477 int err = 0;
478
479 gk20a_dbg_fn("");
480
481 /* an address space needs to have been bound at this point.*/
482 if (!gk20a_channel_as_bound(c)) {
483 nvgpu_err(g, "not bound to address space at time"
484 " of grctx allocation");
485 return -EINVAL;
486 }
487
488 if (!g->ops.gr.is_valid_class(g, class_num)) {
489 nvgpu_err(g, "invalid obj class 0x%x", class_num);
490 err = -EINVAL;
491 goto out;
492 }
493 c->obj_class = class_num;
494
495 if (!gk20a_is_channel_marked_as_tsg(c))
496 return -EINVAL;
497
498 tsg = &f->tsg[c->tsgid];
499 gr_ctx = &tsg->gr_ctx;
500
501 if (!nvgpu_mem_is_valid(&gr_ctx->mem)) {
502 tsg->vm = c->vm;
503 nvgpu_vm_get(tsg->vm);
504 err = g->ops.gr.alloc_gr_ctx(g, gr_ctx,
505 c->vm,
506 class_num,
507 flags);
508 if (!err) {
509 gr_ctx->tsgid = tsg->tsgid;
510 err = vgpu_gr_tsg_bind_gr_ctx(tsg);
511 }
512 if (err) {
513 nvgpu_err(g,
514 "fail to allocate TSG gr ctx buffer, err=%d", err);
515 nvgpu_vm_put(tsg->vm);
516 tsg->vm = NULL;
517 goto out;
518 }
519
520 err = vgpu_gr_ch_bind_gr_ctx(c);
521 if (err) {
522 nvgpu_err(g, "fail to bind gr ctx buffer");
523 goto out;
524 }
525
526 /* commit gr ctx buffer */
527 err = g->ops.gr.commit_inst(c, gr_ctx->mem.gpu_va);
528 if (err) {
529 nvgpu_err(g, "fail to commit gr ctx buffer");
530 goto out;
531 }
532
533 /* allocate patch buffer */
534 err = vgpu_gr_alloc_channel_patch_ctx(g, c);
535 if (err) {
536 nvgpu_err(g, "fail to allocate patch buffer");
537 goto out;
538 }
539
540 /* map global buffer to channel gpu_va and commit */
541 err = vgpu_gr_map_global_ctx_buffers(g, c);
542 if (err) {
543 nvgpu_err(g, "fail to map global ctx buffer");
544 goto out;
545 }
546
547 err = vgpu_gr_commit_global_ctx_buffers(g, c, true);
548 if (err) {
549 nvgpu_err(g, "fail to commit global ctx buffers");
550 goto out;
551 }
552
553 /* load golden image */
554 err = gr_gk20a_elpg_protected_call(g,
555 vgpu_gr_load_golden_ctx_image(g, c));
556 if (err) {
557 nvgpu_err(g, "fail to load golden ctx image");
558 goto out;
559 }
560 } else {
561 err = vgpu_gr_ch_bind_gr_ctx(c);
562 if (err) {
563 nvgpu_err(g, "fail to bind gr ctx buffer");
564 goto out;
565 }
566
567 /* commit gr ctx buffer */
568 err = g->ops.gr.commit_inst(c, gr_ctx->mem.gpu_va);
569 if (err) {
570 nvgpu_err(g, "fail to commit gr ctx buffer");
571 goto out;
572 }
573 }
574
575 /* PM ctxt switch is off by default */
576 gr_ctx->pm_ctx.pm_mode = ctxsw_prog_main_image_pm_mode_no_ctxsw_f();
577
578 gk20a_dbg_fn("done");
579 return 0;
580out:
581 /* 1. gr_ctx, patch_ctx and global ctx buffer mapping
582 can be reused so no need to release them.
583 2. golden image load is a one time thing so if
584 they pass, no need to undo. */
585 nvgpu_err(g, "fail");
586 return err;
587}
588
589static int vgpu_gr_init_gr_config(struct gk20a *g, struct gr_gk20a *gr)
590{
591 struct vgpu_priv_data *priv = vgpu_get_priv_data(g);
592 u32 gpc_index;
593 u32 sm_per_tpc;
594 int err = -ENOMEM;
595
596 gk20a_dbg_fn("");
597
598 gr->max_gpc_count = priv->constants.max_gpc_count;
599 gr->gpc_count = priv->constants.gpc_count;
600 gr->max_tpc_per_gpc_count = priv->constants.max_tpc_per_gpc_count;
601
602 gr->max_tpc_count = gr->max_gpc_count * gr->max_tpc_per_gpc_count;
603
604 gr->gpc_tpc_count = nvgpu_kzalloc(g, gr->gpc_count * sizeof(u32));
605 if (!gr->gpc_tpc_count)
606 goto cleanup;
607
608 gr->gpc_tpc_mask = nvgpu_kzalloc(g, gr->gpc_count * sizeof(u32));
609 if (!gr->gpc_tpc_mask)
610 goto cleanup;
611
612 sm_per_tpc = priv->constants.sm_per_tpc;
613 gr->sm_to_cluster = nvgpu_kzalloc(g, gr->gpc_count *
614 gr->max_tpc_per_gpc_count *
615 sm_per_tpc *
616 sizeof(struct sm_info));
617 if (!gr->sm_to_cluster)
618 goto cleanup;
619
620 gr->tpc_count = 0;
621 for (gpc_index = 0; gpc_index < gr->gpc_count; gpc_index++) {
622 gr->gpc_tpc_count[gpc_index] =
623 priv->constants.gpc_tpc_count[gpc_index];
624
625 gr->tpc_count += gr->gpc_tpc_count[gpc_index];
626
627 if (g->ops.gr.get_gpc_tpc_mask)
628 gr->gpc_tpc_mask[gpc_index] =
629 g->ops.gr.get_gpc_tpc_mask(g, gpc_index);
630 }
631
632 g->ops.gr.bundle_cb_defaults(g);
633 g->ops.gr.cb_size_default(g);
634 g->ops.gr.calc_global_ctx_buffer_size(g);
635 err = g->ops.gr.init_fs_state(g);
636 if (err)
637 goto cleanup;
638 return 0;
639cleanup:
640 nvgpu_err(g, "out of memory");
641
642 nvgpu_kfree(g, gr->gpc_tpc_count);
643 gr->gpc_tpc_count = NULL;
644
645 nvgpu_kfree(g, gr->gpc_tpc_mask);
646 gr->gpc_tpc_mask = NULL;
647
648 return err;
649}
650
651int vgpu_gr_bind_ctxsw_zcull(struct gk20a *g, struct gr_gk20a *gr,
652 struct channel_gk20a *c, u64 zcull_va,
653 u32 mode)
654{
655 struct tegra_vgpu_cmd_msg msg;
656 struct tegra_vgpu_zcull_bind_params *p = &msg.params.zcull_bind;
657 int err;
658
659 gk20a_dbg_fn("");
660
661 msg.cmd = TEGRA_VGPU_CMD_CHANNEL_BIND_ZCULL;
662 msg.handle = vgpu_get_handle(g);
663 p->handle = c->virt_ctx;
664 p->zcull_va = zcull_va;
665 p->mode = mode;
666 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
667
668 return (err || msg.ret) ? -ENOMEM : 0;
669}
670
671int vgpu_gr_get_zcull_info(struct gk20a *g, struct gr_gk20a *gr,
672 struct gr_zcull_info *zcull_params)
673{
674 struct tegra_vgpu_cmd_msg msg;
675 struct tegra_vgpu_zcull_info_params *p = &msg.params.zcull_info;
676 int err;
677
678 gk20a_dbg_fn("");
679
680 msg.cmd = TEGRA_VGPU_CMD_GET_ZCULL_INFO;
681 msg.handle = vgpu_get_handle(g);
682 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
683 if (err || msg.ret)
684 return -ENOMEM;
685
686 zcull_params->width_align_pixels = p->width_align_pixels;
687 zcull_params->height_align_pixels = p->height_align_pixels;
688 zcull_params->pixel_squares_by_aliquots = p->pixel_squares_by_aliquots;
689 zcull_params->aliquot_total = p->aliquot_total;
690 zcull_params->region_byte_multiplier = p->region_byte_multiplier;
691 zcull_params->region_header_size = p->region_header_size;
692 zcull_params->subregion_header_size = p->subregion_header_size;
693 zcull_params->subregion_width_align_pixels =
694 p->subregion_width_align_pixels;
695 zcull_params->subregion_height_align_pixels =
696 p->subregion_height_align_pixels;
697 zcull_params->subregion_count = p->subregion_count;
698
699 return 0;
700}
701
702u32 vgpu_gr_get_gpc_tpc_mask(struct gk20a *g, u32 gpc_index)
703{
704 struct vgpu_priv_data *priv = vgpu_get_priv_data(g);
705
706 return priv->constants.gpc_tpc_mask[gpc_index];
707}
708
709u32 vgpu_gr_get_max_fbps_count(struct gk20a *g)
710{
711 struct vgpu_priv_data *priv = vgpu_get_priv_data(g);
712
713 gk20a_dbg_fn("");
714
715 return priv->constants.num_fbps;
716}
717
718u32 vgpu_gr_get_fbp_en_mask(struct gk20a *g)
719{
720 struct vgpu_priv_data *priv = vgpu_get_priv_data(g);
721
722 gk20a_dbg_fn("");
723
724 return priv->constants.fbp_en_mask;
725}
726
727u32 vgpu_gr_get_max_ltc_per_fbp(struct gk20a *g)
728{
729 struct vgpu_priv_data *priv = vgpu_get_priv_data(g);
730
731 gk20a_dbg_fn("");
732
733 return priv->constants.ltc_per_fbp;
734}
735
736u32 vgpu_gr_get_max_lts_per_ltc(struct gk20a *g)
737{
738 struct vgpu_priv_data *priv = vgpu_get_priv_data(g);
739
740 gk20a_dbg_fn("");
741
742 return priv->constants.max_lts_per_ltc;
743}
744
745u32 *vgpu_gr_rop_l2_en_mask(struct gk20a *g)
746{
747 /* no one use it yet */
748 return NULL;
749}
750
751int vgpu_gr_add_zbc(struct gk20a *g, struct gr_gk20a *gr,
752 struct zbc_entry *zbc_val)
753{
754 struct tegra_vgpu_cmd_msg msg = {0};
755 struct tegra_vgpu_zbc_set_table_params *p = &msg.params.zbc_set_table;
756 int err;
757
758 gk20a_dbg_fn("");
759
760 msg.cmd = TEGRA_VGPU_CMD_ZBC_SET_TABLE;
761 msg.handle = vgpu_get_handle(g);
762
763 p->type = zbc_val->type;
764 p->format = zbc_val->format;
765 switch (p->type) {
766 case GK20A_ZBC_TYPE_COLOR:
767 memcpy(p->color_ds, zbc_val->color_ds, sizeof(p->color_ds));
768 memcpy(p->color_l2, zbc_val->color_l2, sizeof(p->color_l2));
769 break;
770 case GK20A_ZBC_TYPE_DEPTH:
771 p->depth = zbc_val->depth;
772 break;
773 default:
774 return -EINVAL;
775 }
776
777 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
778
779 return (err || msg.ret) ? -ENOMEM : 0;
780}
781
782int vgpu_gr_query_zbc(struct gk20a *g, struct gr_gk20a *gr,
783 struct zbc_query_params *query_params)
784{
785 struct tegra_vgpu_cmd_msg msg = {0};
786 struct tegra_vgpu_zbc_query_table_params *p =
787 &msg.params.zbc_query_table;
788 int err;
789
790 gk20a_dbg_fn("");
791
792 msg.cmd = TEGRA_VGPU_CMD_ZBC_QUERY_TABLE;
793 msg.handle = vgpu_get_handle(g);
794
795 p->type = query_params->type;
796 p->index_size = query_params->index_size;
797
798 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
799 if (err || msg.ret)
800 return -ENOMEM;
801
802 switch (query_params->type) {
803 case GK20A_ZBC_TYPE_COLOR:
804 memcpy(query_params->color_ds, p->color_ds,
805 sizeof(query_params->color_ds));
806 memcpy(query_params->color_l2, p->color_l2,
807 sizeof(query_params->color_l2));
808 break;
809 case GK20A_ZBC_TYPE_DEPTH:
810 query_params->depth = p->depth;
811 break;
812 case GK20A_ZBC_TYPE_INVALID:
813 query_params->index_size = p->index_size;
814 break;
815 default:
816 return -EINVAL;
817 }
818 query_params->ref_cnt = p->ref_cnt;
819 query_params->format = p->format;
820
821 return 0;
822}
823
824static void vgpu_remove_gr_support(struct gr_gk20a *gr)
825{
826 gk20a_dbg_fn("");
827
828 gk20a_comptag_allocator_destroy(gr->g, &gr->comp_tags);
829
830 nvgpu_kfree(gr->g, gr->sm_error_states);
831 gr->sm_error_states = NULL;
832
833 nvgpu_kfree(gr->g, gr->gpc_tpc_mask);
834 gr->gpc_tpc_mask = NULL;
835
836 nvgpu_kfree(gr->g, gr->sm_to_cluster);
837 gr->sm_to_cluster = NULL;
838
839 nvgpu_kfree(gr->g, gr->gpc_tpc_count);
840 gr->gpc_tpc_count = NULL;
841}
842
843static int vgpu_gr_init_gr_setup_sw(struct gk20a *g)
844{
845 struct gr_gk20a *gr = &g->gr;
846 int err;
847
848 gk20a_dbg_fn("");
849
850 if (gr->sw_ready) {
851 gk20a_dbg_fn("skip init");
852 return 0;
853 }
854
855 gr->g = g;
856
857#if defined(CONFIG_GK20A_CYCLE_STATS)
858 nvgpu_mutex_init(&g->gr.cs_lock);
859#endif
860
861 err = vgpu_gr_init_gr_config(g, gr);
862 if (err)
863 goto clean_up;
864
865 err = g->ops.gr.init_ctx_state(g);
866 if (err)
867 goto clean_up;
868
869 err = g->ops.ltc.init_comptags(g, gr);
870 if (err)
871 goto clean_up;
872
873 err = vgpu_gr_alloc_global_ctx_buffers(g);
874 if (err)
875 goto clean_up;
876
877 nvgpu_mutex_init(&gr->ctx_mutex);
878
879 gr->sm_error_states = nvgpu_kzalloc(g,
880 sizeof(struct nvgpu_gr_sm_error_state) *
881 gr->no_of_sm);
882 if (!gr->sm_error_states) {
883 err = -ENOMEM;
884 goto clean_up;
885 }
886
887 gr->remove_support = vgpu_remove_gr_support;
888 gr->sw_ready = true;
889
890 gk20a_dbg_fn("done");
891 return 0;
892
893clean_up:
894 nvgpu_err(g, "fail");
895 vgpu_remove_gr_support(gr);
896 return err;
897}
898
899int vgpu_init_gr_support(struct gk20a *g)
900{
901 gk20a_dbg_fn("");
902
903 return vgpu_gr_init_gr_setup_sw(g);
904}
905
906int vgpu_gr_isr(struct gk20a *g, struct tegra_vgpu_gr_intr_info *info)
907{
908 struct fifo_gk20a *f = &g->fifo;
909 struct channel_gk20a *ch = gk20a_channel_get(&f->channel[info->chid]);
910
911 gk20a_dbg_fn("");
912 if (!ch)
913 return 0;
914
915 if (info->type != TEGRA_VGPU_GR_INTR_NOTIFY &&
916 info->type != TEGRA_VGPU_GR_INTR_SEMAPHORE)
917 nvgpu_err(g, "gr intr (%d) on ch %u", info->type, info->chid);
918
919 switch (info->type) {
920 case TEGRA_VGPU_GR_INTR_NOTIFY:
921 nvgpu_cond_broadcast_interruptible(&ch->notifier_wq);
922 break;
923 case TEGRA_VGPU_GR_INTR_SEMAPHORE:
924 nvgpu_cond_broadcast_interruptible(&ch->semaphore_wq);
925 break;
926 case TEGRA_VGPU_GR_INTR_SEMAPHORE_TIMEOUT:
927 nvgpu_set_error_notifier(ch,
928 NVGPU_ERR_NOTIFIER_GR_SEMAPHORE_TIMEOUT);
929 break;
930 case TEGRA_VGPU_GR_INTR_ILLEGAL_NOTIFY:
931 nvgpu_set_error_notifier(ch,
932 NVGPU_ERR_NOTIFIER_GR_ILLEGAL_NOTIFY);
933 case TEGRA_VGPU_GR_INTR_ILLEGAL_METHOD:
934 break;
935 case TEGRA_VGPU_GR_INTR_ILLEGAL_CLASS:
936 nvgpu_set_error_notifier(ch,
937 NVGPU_ERR_NOTIFIER_GR_ERROR_SW_NOTIFY);
938 break;
939 case TEGRA_VGPU_GR_INTR_FECS_ERROR:
940 break;
941 case TEGRA_VGPU_GR_INTR_CLASS_ERROR:
942 nvgpu_set_error_notifier(ch,
943 NVGPU_ERR_NOTIFIER_GR_ERROR_SW_NOTIFY);
944 break;
945 case TEGRA_VGPU_GR_INTR_FIRMWARE_METHOD:
946 nvgpu_set_error_notifier(ch,
947 NVGPU_ERR_NOTIFIER_GR_ERROR_SW_NOTIFY);
948 break;
949 case TEGRA_VGPU_GR_INTR_EXCEPTION:
950 nvgpu_set_error_notifier(ch,
951 NVGPU_ERR_NOTIFIER_GR_ERROR_SW_NOTIFY);
952 break;
953 case TEGRA_VGPU_GR_INTR_SM_EXCEPTION:
954 gk20a_dbg_gpu_post_events(ch);
955 break;
956 default:
957 WARN_ON(1);
958 break;
959 }
960
961 gk20a_channel_put(ch);
962 return 0;
963}
964
965int vgpu_gr_nonstall_isr(struct gk20a *g,
966 struct tegra_vgpu_gr_nonstall_intr_info *info)
967{
968 gk20a_dbg_fn("");
969
970 switch (info->type) {
971 case TEGRA_VGPU_GR_NONSTALL_INTR_SEMAPHORE:
972 gk20a_channel_semaphore_wakeup(g, true);
973 break;
974 default:
975 WARN_ON(1);
976 break;
977 }
978
979 return 0;
980}
981
982int vgpu_gr_set_sm_debug_mode(struct gk20a *g,
983 struct channel_gk20a *ch, u64 sms, bool enable)
984{
985 struct tegra_vgpu_cmd_msg msg;
986 struct tegra_vgpu_sm_debug_mode *p = &msg.params.sm_debug_mode;
987 int err;
988
989 gk20a_dbg_fn("");
990
991 msg.cmd = TEGRA_VGPU_CMD_SET_SM_DEBUG_MODE;
992 msg.handle = vgpu_get_handle(g);
993 p->handle = ch->virt_ctx;
994 p->sms = sms;
995 p->enable = (u32)enable;
996 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
997 WARN_ON(err || msg.ret);
998
999 return err ? err : msg.ret;
1000}
1001
1002int vgpu_gr_update_smpc_ctxsw_mode(struct gk20a *g,
1003 struct channel_gk20a *ch, bool enable)
1004{
1005 struct tegra_vgpu_cmd_msg msg;
1006 struct tegra_vgpu_channel_set_ctxsw_mode *p = &msg.params.set_ctxsw_mode;
1007 int err;
1008
1009 gk20a_dbg_fn("");
1010
1011 msg.cmd = TEGRA_VGPU_CMD_CHANNEL_SET_SMPC_CTXSW_MODE;
1012 msg.handle = vgpu_get_handle(g);
1013 p->handle = ch->virt_ctx;
1014
1015 if (enable)
1016 p->mode = TEGRA_VGPU_CTXSW_MODE_CTXSW;
1017 else
1018 p->mode = TEGRA_VGPU_CTXSW_MODE_NO_CTXSW;
1019
1020 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
1021 WARN_ON(err || msg.ret);
1022
1023 return err ? err : msg.ret;
1024}
1025
1026int vgpu_gr_update_hwpm_ctxsw_mode(struct gk20a *g,
1027 struct channel_gk20a *ch, bool enable)
1028{
1029 struct tsg_gk20a *tsg;
1030 struct nvgpu_gr_ctx *ch_ctx;
1031 struct pm_ctx_desc *pm_ctx;
1032 struct tegra_vgpu_cmd_msg msg;
1033 struct tegra_vgpu_channel_set_ctxsw_mode *p = &msg.params.set_ctxsw_mode;
1034 int err;
1035
1036 gk20a_dbg_fn("");
1037
1038 tsg = tsg_gk20a_from_ch(ch);
1039 if (!tsg)
1040 return -EINVAL;
1041
1042 ch_ctx = &tsg->gr_ctx;
1043 pm_ctx = &ch_ctx->pm_ctx;
1044
1045 if (enable) {
1046 /*
1047 * send command to enable HWPM only once - otherwise server
1048 * will return an error due to using the same GPU VA twice.
1049 */
1050 if (pm_ctx->pm_mode == ctxsw_prog_main_image_pm_mode_ctxsw_f())
1051 return 0;
1052
1053 p->mode = TEGRA_VGPU_CTXSW_MODE_CTXSW;
1054
1055 /* Allocate buffer if necessary */
1056 if (pm_ctx->mem.gpu_va == 0) {
1057 pm_ctx->mem.gpu_va = __nvgpu_vm_alloc_va(ch->vm,
1058 g->gr.ctx_vars.pm_ctxsw_image_size,
1059 gmmu_page_size_kernel);
1060
1061 if (!pm_ctx->mem.gpu_va)
1062 return -ENOMEM;
1063 pm_ctx->mem.size = g->gr.ctx_vars.pm_ctxsw_image_size;
1064 }
1065 } else {
1066 if (pm_ctx->pm_mode == ctxsw_prog_main_image_pm_mode_no_ctxsw_f())
1067 return 0;
1068
1069 p->mode = TEGRA_VGPU_CTXSW_MODE_NO_CTXSW;
1070 }
1071
1072 msg.cmd = TEGRA_VGPU_CMD_CHANNEL_SET_HWPM_CTXSW_MODE;
1073 msg.handle = vgpu_get_handle(g);
1074 p->handle = ch->virt_ctx;
1075 p->gpu_va = pm_ctx->mem.gpu_va;
1076
1077 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
1078 WARN_ON(err || msg.ret);
1079 err = err ? err : msg.ret;
1080 if (!err)
1081 pm_ctx->pm_mode = enable ?
1082 ctxsw_prog_main_image_pm_mode_ctxsw_f() :
1083 ctxsw_prog_main_image_pm_mode_no_ctxsw_f();
1084
1085 return err;
1086}
1087
1088int vgpu_gr_clear_sm_error_state(struct gk20a *g,
1089 struct channel_gk20a *ch, u32 sm_id)
1090{
1091 struct gr_gk20a *gr = &g->gr;
1092 struct tegra_vgpu_cmd_msg msg;
1093 struct tegra_vgpu_clear_sm_error_state *p =
1094 &msg.params.clear_sm_error_state;
1095 int err;
1096
1097 nvgpu_mutex_acquire(&g->dbg_sessions_lock);
1098 msg.cmd = TEGRA_VGPU_CMD_CLEAR_SM_ERROR_STATE;
1099 msg.handle = vgpu_get_handle(g);
1100 p->handle = ch->virt_ctx;
1101 p->sm_id = sm_id;
1102
1103 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
1104 WARN_ON(err || msg.ret);
1105
1106 memset(&gr->sm_error_states[sm_id], 0, sizeof(*gr->sm_error_states));
1107 nvgpu_mutex_release(&g->dbg_sessions_lock);
1108
1109 return err ? err : msg.ret;
1110
1111
1112 return 0;
1113}
1114
1115static int vgpu_gr_suspend_resume_contexts(struct gk20a *g,
1116 struct dbg_session_gk20a *dbg_s,
1117 int *ctx_resident_ch_fd, u32 cmd)
1118{
1119 struct dbg_session_channel_data *ch_data;
1120 struct tegra_vgpu_cmd_msg msg;
1121 struct tegra_vgpu_suspend_resume_contexts *p;
1122 size_t n;
1123 int channel_fd = -1;
1124 int err = 0;
1125 void *handle = NULL;
1126 u16 *oob;
1127 size_t oob_size;
1128
1129 nvgpu_mutex_acquire(&g->dbg_sessions_lock);
1130 nvgpu_mutex_acquire(&dbg_s->ch_list_lock);
1131
1132 handle = vgpu_ivc_oob_get_ptr(vgpu_ivc_get_server_vmid(),
1133 TEGRA_VGPU_QUEUE_CMD,
1134 (void **)&oob, &oob_size);
1135 if (!handle) {
1136 err = -EINVAL;
1137 goto done;
1138 }
1139
1140 n = 0;
1141 nvgpu_list_for_each_entry(ch_data, &dbg_s->ch_list,
1142 dbg_session_channel_data, ch_entry)
1143 n++;
1144
1145 if (oob_size < n * sizeof(u16)) {
1146 err = -ENOMEM;
1147 goto done;
1148 }
1149
1150 msg.cmd = cmd;
1151 msg.handle = vgpu_get_handle(g);
1152 p = &msg.params.suspend_contexts;
1153 p->num_channels = n;
1154 n = 0;
1155 nvgpu_list_for_each_entry(ch_data, &dbg_s->ch_list,
1156 dbg_session_channel_data, ch_entry)
1157 oob[n++] = (u16)ch_data->chid;
1158
1159 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
1160 if (err || msg.ret) {
1161 err = -ENOMEM;
1162 goto done;
1163 }
1164
1165 if (p->resident_chid != (u16)~0) {
1166 nvgpu_list_for_each_entry(ch_data, &dbg_s->ch_list,
1167 dbg_session_channel_data, ch_entry) {
1168 if (ch_data->chid == p->resident_chid) {
1169 channel_fd = ch_data->channel_fd;
1170 break;
1171 }
1172 }
1173 }
1174
1175done:
1176 if (handle)
1177 vgpu_ivc_oob_put_ptr(handle);
1178 nvgpu_mutex_release(&dbg_s->ch_list_lock);
1179 nvgpu_mutex_release(&g->dbg_sessions_lock);
1180 *ctx_resident_ch_fd = channel_fd;
1181 return err;
1182}
1183
1184int vgpu_gr_suspend_contexts(struct gk20a *g,
1185 struct dbg_session_gk20a *dbg_s,
1186 int *ctx_resident_ch_fd)
1187{
1188 return vgpu_gr_suspend_resume_contexts(g, dbg_s,
1189 ctx_resident_ch_fd, TEGRA_VGPU_CMD_SUSPEND_CONTEXTS);
1190}
1191
1192int vgpu_gr_resume_contexts(struct gk20a *g,
1193 struct dbg_session_gk20a *dbg_s,
1194 int *ctx_resident_ch_fd)
1195{
1196 return vgpu_gr_suspend_resume_contexts(g, dbg_s,
1197 ctx_resident_ch_fd, TEGRA_VGPU_CMD_RESUME_CONTEXTS);
1198}
1199
1200void vgpu_gr_handle_sm_esr_event(struct gk20a *g,
1201 struct tegra_vgpu_sm_esr_info *info)
1202{
1203 struct nvgpu_gr_sm_error_state *sm_error_states;
1204
1205 if (info->sm_id >= g->gr.no_of_sm) {
1206 nvgpu_err(g, "invalid smd_id %d / %d",
1207 info->sm_id, g->gr.no_of_sm);
1208 return;
1209 }
1210
1211 nvgpu_mutex_acquire(&g->dbg_sessions_lock);
1212
1213 sm_error_states = &g->gr.sm_error_states[info->sm_id];
1214
1215 sm_error_states->hww_global_esr = info->hww_global_esr;
1216 sm_error_states->hww_warp_esr = info->hww_warp_esr;
1217 sm_error_states->hww_warp_esr_pc = info->hww_warp_esr_pc;
1218 sm_error_states->hww_global_esr_report_mask =
1219 info->hww_global_esr_report_mask;
1220 sm_error_states->hww_warp_esr_report_mask =
1221 info->hww_warp_esr_report_mask;
1222
1223 nvgpu_mutex_release(&g->dbg_sessions_lock);
1224}
1225
1226int vgpu_gr_init_sm_id_table(struct gk20a *g)
1227{
1228 struct tegra_vgpu_cmd_msg msg = {};
1229 struct tegra_vgpu_vsms_mapping_params *p = &msg.params.vsms_mapping;
1230 struct tegra_vgpu_vsms_mapping_entry *entry;
1231 struct vgpu_priv_data *priv = vgpu_get_priv_data(g);
1232 struct sm_info *sm_info;
1233 int err;
1234 struct gr_gk20a *gr = &g->gr;
1235 size_t oob_size;
1236 void *handle = NULL;
1237 u32 sm_id;
1238 u32 max_sm;
1239
1240 msg.cmd = TEGRA_VGPU_CMD_GET_VSMS_MAPPING;
1241 msg.handle = vgpu_get_handle(g);
1242 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
1243 err = err ? err : msg.ret;
1244 if (err) {
1245 nvgpu_err(g, "get vsms mapping failed err %d", err);
1246 return err;
1247 }
1248
1249 handle = vgpu_ivc_oob_get_ptr(vgpu_ivc_get_server_vmid(),
1250 TEGRA_VGPU_QUEUE_CMD,
1251 (void **)&entry, &oob_size);
1252 if (!handle)
1253 return -EINVAL;
1254
1255 max_sm = gr->gpc_count *
1256 gr->max_tpc_per_gpc_count *
1257 priv->constants.sm_per_tpc;
1258 if (p->num_sm > max_sm)
1259 return -EINVAL;
1260
1261 if ((p->num_sm * sizeof(*entry)) > oob_size)
1262 return -EINVAL;
1263
1264 gr->no_of_sm = p->num_sm;
1265 for (sm_id = 0; sm_id < p->num_sm; sm_id++, entry++) {
1266 sm_info = &gr->sm_to_cluster[sm_id];
1267 sm_info->tpc_index = entry->tpc_index;
1268 sm_info->gpc_index = entry->gpc_index;
1269 sm_info->sm_index = entry->sm_index;
1270 sm_info->global_tpc_index = entry->global_tpc_index;
1271 }
1272 vgpu_ivc_oob_put_ptr(handle);
1273
1274 return 0;
1275}
1276
1277int vgpu_gr_init_fs_state(struct gk20a *g)
1278{
1279 if (!g->ops.gr.init_sm_id_table)
1280 return -EINVAL;
1281
1282 return g->ops.gr.init_sm_id_table(g);
1283}