summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonsta Holtta <kholtta@nvidia.com>2018-09-11 07:47:51 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2019-08-15 03:58:54 -0400
commit8b484c0b531b95fce024e101cdd204f1f8107c29 (patch)
treed55f5ab0ed32e8c45ecfb9fa639456eba5433de2
parent758cb76e225775ba5ac3dd2cb9415cb40dc83810 (diff)
gpu: nvgpu: support usermode submit buffers
Import userd and gpfifo buffers from userspace if provided via NVGPU_IOCTL_CHANNEL_ALLOC_GPFIFO_EX. Also supply the work submit token (i.e., the hw channel id) to userspace. To keep the buffers alive, store their dmabuf and attachment/sgt handles in nvgpu_channel_linux. Our nvgpu_mem doesn't provide such data for buffers that are mainly in kernel use. The buffers are freed via a new API in the os_channel interface. Fix a bug in gk20a_channel_free_usermode_buffers: also unmap the usermode gpfifo buffer. Bug 200145225 Bug 200541476 Change-Id: I8416af7085c91b044ac8ccd9faa38e2a6d0c3946 Signed-off-by: Konsta Holtta <kholtta@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1795821 Signed-off-by: Debarshi Dutta <ddutta@nvidia.com> (cherry picked from commit 99b1c6dcdf328efcfe47338ad1b71a114ab7f272 in dev-main) Reviewed-on: https://git-master.nvidia.com/r/2170603 GVS: Gerrit_Virtual_Submit Reviewed-by: Bibek Basu <bbasu@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r--drivers/gpu/nvgpu/common/fifo/channel.c9
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/channel.h2
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/gk20a.h3
-rw-r--r--drivers/gpu/nvgpu/os/linux/channel.h15
-rw-r--r--drivers/gpu/nvgpu/os/linux/ioctl_channel.c13
-rw-r--r--drivers/gpu/nvgpu/os/linux/linux-channel.c149
-rw-r--r--include/uapi/linux/nvgpu.h18
7 files changed, 205 insertions, 4 deletions
diff --git a/drivers/gpu/nvgpu/common/fifo/channel.c b/drivers/gpu/nvgpu/common/fifo/channel.c
index adb59ac4..6ebeb596 100644
--- a/drivers/gpu/nvgpu/common/fifo/channel.c
+++ b/drivers/gpu/nvgpu/common/fifo/channel.c
@@ -1228,7 +1228,9 @@ int nvgpu_channel_setup_bind(struct channel_gk20a *c,
1228 nvgpu_log_info(g, "channel %d : gpfifo_base 0x%016llx, size %d", 1228 nvgpu_log_info(g, "channel %d : gpfifo_base 0x%016llx, size %d",
1229 c->chid, gpfifo_gpu_va, c->gpfifo.entry_num); 1229 c->chid, gpfifo_gpu_va, c->gpfifo.entry_num);
1230 1230
1231 g->ops.fifo.setup_userd(c); 1231 if (!c->usermode_submit_enabled) {
1232 g->ops.fifo.setup_userd(c);
1233 }
1232 1234
1233 if (g->aggressive_sync_destroy_thresh == 0U) { 1235 if (g->aggressive_sync_destroy_thresh == 0U) {
1234 nvgpu_mutex_acquire(&c->sync_lock); 1236 nvgpu_mutex_acquire(&c->sync_lock);
@@ -1326,7 +1328,10 @@ void gk20a_channel_free_usermode_buffers(struct channel_gk20a *c)
1326 nvgpu_dma_free(c->g, &c->usermode_userd); 1328 nvgpu_dma_free(c->g, &c->usermode_userd);
1327 } 1329 }
1328 if (nvgpu_mem_is_valid(&c->usermode_gpfifo)) { 1330 if (nvgpu_mem_is_valid(&c->usermode_gpfifo)) {
1329 nvgpu_dma_free(c->g, &c->usermode_gpfifo); 1331 nvgpu_dma_unmap_free(c->vm, &c->usermode_gpfifo);
1332 }
1333 if (c->g->os_channel.free_usermode_buffers != NULL) {
1334 c->g->os_channel.free_usermode_buffers(c);
1330 } 1335 }
1331} 1336}
1332 1337
diff --git a/drivers/gpu/nvgpu/include/nvgpu/channel.h b/drivers/gpu/nvgpu/include/nvgpu/channel.h
index d7bf7816..7ca60fe3 100644
--- a/drivers/gpu/nvgpu/include/nvgpu/channel.h
+++ b/drivers/gpu/nvgpu/include/nvgpu/channel.h
@@ -95,7 +95,9 @@ struct nvgpu_setup_bind_args {
95 u32 num_gpfifo_entries; 95 u32 num_gpfifo_entries;
96 u32 num_inflight_jobs; 96 u32 num_inflight_jobs;
97 u32 userd_dmabuf_fd; 97 u32 userd_dmabuf_fd;
98 u64 userd_dmabuf_offset;
98 u32 gpfifo_dmabuf_fd; 99 u32 gpfifo_dmabuf_fd;
100 u64 gpfifo_dmabuf_offset;
99 u32 work_submit_token; 101 u32 work_submit_token;
100 u32 flags; 102 u32 flags;
101}; 103};
diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h
index feae7d23..873fa826 100644
--- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h
+++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h
@@ -1605,7 +1605,8 @@ struct gk20a {
1605 struct nvgpu_gpfifo_userdata userdata, 1605 struct nvgpu_gpfifo_userdata userdata,
1606 u32 start, u32 length); 1606 u32 start, u32 length);
1607 int (*alloc_usermode_buffers)(struct channel_gk20a *c, 1607 int (*alloc_usermode_buffers)(struct channel_gk20a *c,
1608 struct nvgpu_setup_bind_args *gpfifo_args); 1608 struct nvgpu_setup_bind_args *args);
1609 void (*free_usermode_buffers)(struct channel_gk20a *c);
1609 } os_channel; 1610 } os_channel;
1610 1611
1611 struct gk20a_scale_profile *scale_profile; 1612 struct gk20a_scale_profile *scale_profile;
diff --git a/drivers/gpu/nvgpu/os/linux/channel.h b/drivers/gpu/nvgpu/os/linux/channel.h
index 2210678d..e6326fad 100644
--- a/drivers/gpu/nvgpu/os/linux/channel.h
+++ b/drivers/gpu/nvgpu/os/linux/channel.h
@@ -63,6 +63,19 @@ struct nvgpu_os_fence_framework {
63 struct sync_timeline *timeline; 63 struct sync_timeline *timeline;
64}; 64};
65 65
66struct nvgpu_usermode_bufs_linux {
67 /*
68 * Common low level info of these is stored in nvgpu_mems in
69 * channel_gk20a; these hold lifetimes for the actual dmabuf and its
70 * dma mapping.
71 */
72 struct nvgpu_usermode_buf_linux {
73 struct dma_buf *dmabuf;
74 struct dma_buf_attachment *attachment;
75 struct sg_table *sgt;
76 } gpfifo, userd;
77};
78
66struct nvgpu_channel_linux { 79struct nvgpu_channel_linux {
67 struct channel_gk20a *ch; 80 struct channel_gk20a *ch;
68 81
@@ -72,6 +85,8 @@ struct nvgpu_channel_linux {
72 struct nvgpu_error_notifier error_notifier; 85 struct nvgpu_error_notifier error_notifier;
73 86
74 struct dma_buf *cyclestate_buffer_handler; 87 struct dma_buf *cyclestate_buffer_handler;
88
89 struct nvgpu_usermode_bufs_linux usermode;
75}; 90};
76 91
77u32 nvgpu_submit_gpfifo_user_flags_to_common_flags(u32 user_flags); 92u32 nvgpu_submit_gpfifo_user_flags_to_common_flags(u32 user_flags);
diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_channel.c b/drivers/gpu/nvgpu/os/linux/ioctl_channel.c
index d243c425..22177171 100644
--- a/drivers/gpu/nvgpu/os/linux/ioctl_channel.c
+++ b/drivers/gpu/nvgpu/os/linux/ioctl_channel.c
@@ -590,6 +590,9 @@ static u32 nvgpu_setup_bind_user_flags_to_common_flags(u32 user_flags)
590 if (user_flags & NVGPU_CHANNEL_SETUP_BIND_FLAGS_REPLAYABLE_FAULTS_ENABLE) 590 if (user_flags & NVGPU_CHANNEL_SETUP_BIND_FLAGS_REPLAYABLE_FAULTS_ENABLE)
591 flags |= NVGPU_SETUP_BIND_FLAGS_REPLAYABLE_FAULTS_ENABLE; 591 flags |= NVGPU_SETUP_BIND_FLAGS_REPLAYABLE_FAULTS_ENABLE;
592 592
593 if (user_flags & NVGPU_CHANNEL_SETUP_BIND_FLAGS_USERMODE_SUPPORT)
594 flags |= NVGPU_SETUP_BIND_FLAGS_USERMODE_SUPPORT;
595
593 return flags; 596 return flags;
594} 597}
595 598
@@ -601,6 +604,14 @@ static void nvgpu_get_setup_bind_args(
601 channel_setup_bind_args->num_gpfifo_entries; 604 channel_setup_bind_args->num_gpfifo_entries;
602 setup_bind_args->num_inflight_jobs = 605 setup_bind_args->num_inflight_jobs =
603 channel_setup_bind_args->num_inflight_jobs; 606 channel_setup_bind_args->num_inflight_jobs;
607 setup_bind_args->userd_dmabuf_fd =
608 channel_setup_bind_args->userd_dmabuf_fd;
609 setup_bind_args->userd_dmabuf_offset =
610 channel_setup_bind_args->userd_dmabuf_offset;
611 setup_bind_args->gpfifo_dmabuf_fd =
612 channel_setup_bind_args->gpfifo_dmabuf_fd;
613 setup_bind_args->gpfifo_dmabuf_offset =
614 channel_setup_bind_args->gpfifo_dmabuf_offset;
604 setup_bind_args->flags = nvgpu_setup_bind_user_flags_to_common_flags( 615 setup_bind_args->flags = nvgpu_setup_bind_user_flags_to_common_flags(
605 channel_setup_bind_args->flags); 616 channel_setup_bind_args->flags);
606} 617}
@@ -1156,6 +1167,8 @@ long gk20a_channel_ioctl(struct file *filp,
1156 break; 1167 break;
1157 } 1168 }
1158 err = nvgpu_channel_setup_bind(ch, &setup_bind_args); 1169 err = nvgpu_channel_setup_bind(ch, &setup_bind_args);
1170 channel_setup_bind_args->work_submit_token =
1171 setup_bind_args.work_submit_token;
1159 gk20a_idle(ch->g); 1172 gk20a_idle(ch->g);
1160 break; 1173 break;
1161 } 1174 }
diff --git a/drivers/gpu/nvgpu/os/linux/linux-channel.c b/drivers/gpu/nvgpu/os/linux/linux-channel.c
index 1fec3604..d035baf7 100644
--- a/drivers/gpu/nvgpu/os/linux/linux-channel.c
+++ b/drivers/gpu/nvgpu/os/linux/linux-channel.c
@@ -20,6 +20,7 @@
20#include <nvgpu/os_sched.h> 20#include <nvgpu/os_sched.h>
21#include <nvgpu/gk20a.h> 21#include <nvgpu/gk20a.h>
22#include <nvgpu/channel.h> 22#include <nvgpu/channel.h>
23#include <nvgpu/dma.h>
23 24
24/* 25/*
25 * This is required for nvgpu_vm_find_buf() which is used in the tracing 26 * This is required for nvgpu_vm_find_buf() which is used in the tracing
@@ -31,6 +32,7 @@
31#include "channel.h" 32#include "channel.h"
32#include "ioctl_channel.h" 33#include "ioctl_channel.h"
33#include "os_linux.h" 34#include "os_linux.h"
35#include "dmabuf.h"
34 36
35#include <nvgpu/hw/gk20a/hw_pbdma_gk20a.h> 37#include <nvgpu/hw/gk20a/hw_pbdma_gk20a.h>
36 38
@@ -383,6 +385,147 @@ static int nvgpu_channel_copy_user_gpfifo(struct nvgpu_gpfifo_entry *dest,
383 return n == 0 ? 0 : -EFAULT; 385 return n == 0 ? 0 : -EFAULT;
384} 386}
385 387
388int nvgpu_usermode_buf_from_dmabuf(struct gk20a *g, int dmabuf_fd,
389 struct nvgpu_mem *mem, struct nvgpu_usermode_buf_linux *buf)
390{
391 struct device *dev = dev_from_gk20a(g);
392 struct dma_buf *dmabuf;
393 struct sg_table *sgt;
394 struct dma_buf_attachment *attachment;
395 int err;
396
397 dmabuf = dma_buf_get(dmabuf_fd);
398 if (IS_ERR(dmabuf)) {
399 return PTR_ERR(dmabuf);
400 }
401
402 if (gk20a_dmabuf_aperture(g, dmabuf) == APERTURE_INVALID) {
403 err = -EINVAL;
404 goto put_dmabuf;
405 }
406
407 err = gk20a_dmabuf_alloc_drvdata(dmabuf, dev);
408 if (err != 0) {
409 goto put_dmabuf;
410 }
411
412 sgt = gk20a_mm_pin(dev, dmabuf, &attachment);
413 if (IS_ERR(sgt)) {
414 nvgpu_warn(g, "Failed to pin dma_buf!");
415 err = PTR_ERR(sgt);
416 goto put_dmabuf;
417 }
418
419 buf->dmabuf = dmabuf;
420 buf->attachment = attachment;
421 buf->sgt = sgt;
422
423 /*
424 * This mem is unmapped and freed in a common path; for Linux, we'll
425 * also need to unref the dmabuf stuff (above) but the sgt here is only
426 * borrowed, so it cannot be freed by nvgpu_mem_*.
427 */
428 mem->mem_flags = NVGPU_MEM_FLAG_FOREIGN_SGT;
429 mem->aperture = APERTURE_SYSMEM;
430 mem->skip_wmb = 0;
431 mem->size = dmabuf->size;
432
433 mem->priv.flags = 0;
434 mem->priv.pages = NULL;
435 mem->priv.sgt = sgt;
436
437 return 0;
438put_dmabuf:
439 dma_buf_put(dmabuf);
440 return err;
441}
442
443void nvgpu_channel_free_usermode_buffers(struct channel_gk20a *c)
444{
445 struct nvgpu_channel_linux *priv = c->os_priv;
446 struct gk20a *g = c->g;
447 struct device *dev = dev_from_gk20a(g);
448
449 if (priv->usermode.gpfifo.dmabuf != NULL) {
450 gk20a_mm_unpin(dev, priv->usermode.gpfifo.dmabuf,
451 priv->usermode.gpfifo.attachment,
452 priv->usermode.gpfifo.sgt);
453 dma_buf_put(priv->usermode.gpfifo.dmabuf);
454 priv->usermode.gpfifo.dmabuf = NULL;
455 }
456
457 if (priv->usermode.userd.dmabuf != NULL) {
458 gk20a_mm_unpin(dev, priv->usermode.userd.dmabuf,
459 priv->usermode.userd.attachment,
460 priv->usermode.userd.sgt);
461 dma_buf_put(priv->usermode.userd.dmabuf);
462 priv->usermode.userd.dmabuf = NULL;
463 }
464}
465
466static int nvgpu_channel_alloc_usermode_buffers(struct channel_gk20a *c,
467 struct nvgpu_setup_bind_args *args)
468{
469 struct nvgpu_channel_linux *priv = c->os_priv;
470 struct gk20a *g = c->g;
471 struct device *dev = dev_from_gk20a(g);
472 size_t gpfifo_size;
473 int err;
474
475 if (args->gpfifo_dmabuf_fd == 0 || args->userd_dmabuf_fd == 0) {
476 return -EINVAL;
477 }
478
479 if (args->gpfifo_dmabuf_offset != 0 ||
480 args->userd_dmabuf_offset != 0) {
481 /* TODO - not yet supported */
482 return -EINVAL;
483 }
484
485 err = nvgpu_usermode_buf_from_dmabuf(g, args->gpfifo_dmabuf_fd,
486 &c->usermode_gpfifo, &priv->usermode.gpfifo);
487 if (err < 0) {
488 return err;
489 }
490
491 gpfifo_size = max_t(u32, SZ_4K,
492 args->num_gpfifo_entries *
493 nvgpu_get_gpfifo_entry_size());
494
495 if (c->usermode_gpfifo.size < gpfifo_size) {
496 err = -EINVAL;
497 goto free_gpfifo;
498 }
499
500 c->usermode_gpfifo.gpu_va = nvgpu_gmmu_map(c->vm, &c->usermode_gpfifo,
501 c->usermode_gpfifo.size, 0, gk20a_mem_flag_none,
502 false, c->usermode_gpfifo.aperture);
503
504 if (c->usermode_gpfifo.gpu_va == 0) {
505 err = -ENOMEM;
506 goto unmap_free_gpfifo;
507 }
508
509 err = nvgpu_usermode_buf_from_dmabuf(g, args->userd_dmabuf_fd,
510 &c->usermode_userd, &priv->usermode.userd);
511 if (err < 0) {
512 goto unmap_free_gpfifo;
513 }
514
515 args->work_submit_token = g->fifo.channel_base + c->chid;
516
517 return 0;
518unmap_free_gpfifo:
519 nvgpu_dma_unmap_free(c->vm, &c->usermode_gpfifo);
520free_gpfifo:
521 gk20a_mm_unpin(dev, priv->usermode.gpfifo.dmabuf,
522 priv->usermode.gpfifo.attachment,
523 priv->usermode.gpfifo.sgt);
524 dma_buf_put(priv->usermode.gpfifo.dmabuf);
525 priv->usermode.gpfifo.dmabuf = NULL;
526 return err;
527}
528
386int nvgpu_init_channel_support_linux(struct nvgpu_os_linux *l) 529int nvgpu_init_channel_support_linux(struct nvgpu_os_linux *l)
387{ 530{
388 struct gk20a *g = &l->g; 531 struct gk20a *g = &l->g;
@@ -417,6 +560,12 @@ int nvgpu_init_channel_support_linux(struct nvgpu_os_linux *l)
417 g->os_channel.copy_user_gpfifo = 560 g->os_channel.copy_user_gpfifo =
418 nvgpu_channel_copy_user_gpfifo; 561 nvgpu_channel_copy_user_gpfifo;
419 562
563 g->os_channel.alloc_usermode_buffers =
564 nvgpu_channel_alloc_usermode_buffers;
565
566 g->os_channel.free_usermode_buffers =
567 nvgpu_channel_free_usermode_buffers;
568
420 return 0; 569 return 0;
421 570
422err_clean: 571err_clean:
diff --git a/include/uapi/linux/nvgpu.h b/include/uapi/linux/nvgpu.h
index 0fa04f6b..38139524 100644
--- a/include/uapi/linux/nvgpu.h
+++ b/include/uapi/linux/nvgpu.h
@@ -1514,8 +1514,24 @@ struct nvgpu_channel_setup_bind_args {
1514#define NVGPU_CHANNEL_SETUP_BIND_FLAGS_DETERMINISTIC (1 << 1) 1514#define NVGPU_CHANNEL_SETUP_BIND_FLAGS_DETERMINISTIC (1 << 1)
1515/* enable replayable gmmu faults for this channel */ 1515/* enable replayable gmmu faults for this channel */
1516#define NVGPU_CHANNEL_SETUP_BIND_FLAGS_REPLAYABLE_FAULTS_ENABLE (1 << 2) 1516#define NVGPU_CHANNEL_SETUP_BIND_FLAGS_REPLAYABLE_FAULTS_ENABLE (1 << 2)
1517/*
1518 * Enable usermode submits on this channel.
1519 *
1520 * Submits in usermode are supported in some environments. If supported and
1521 * this flag is set + USERD and GPFIFO buffers are provided here, a submit
1522 * token is passed back to be written in the doorbell register in the usermode
1523 * region to notify the GPU for new work on this channel. Usermode and
1524 * kernelmode submit modes are mutually exclusive; by passing this flag, the
1525 * SUBMIT_GPFIFO IOCTL cannot be used.
1526 */
1527#define NVGPU_CHANNEL_SETUP_BIND_FLAGS_USERMODE_SUPPORT (1 << 3)
1517 __u32 flags; 1528 __u32 flags;
1518 __u32 reserved[16]; 1529 __s32 userd_dmabuf_fd; /* in */
1530 __s32 gpfifo_dmabuf_fd; /* in */
1531 __u32 work_submit_token; /* out */
1532 __u64 userd_dmabuf_offset; /* in */
1533 __u64 gpfifo_dmabuf_offset; /* in */
1534 __u32 reserved[9];
1519}; 1535};
1520struct nvgpu_fence { 1536struct nvgpu_fence {
1521 __u32 id; /* syncpoint id or sync fence fd */ 1537 __u32 id; /* syncpoint id or sync fence fd */