summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/os
diff options
context:
space:
mode:
authorKonsta Holtta <kholtta@nvidia.com>2018-05-18 04:35:29 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2018-06-20 15:25:45 -0400
commit819f32bdf119ebf4d758a901c9a22c2c4a7d167a (patch)
tree0dd9760b4788cb3e287750c62a43e89366eb38b5 /drivers/gpu/nvgpu/os
parent0ca69a482d15ccf22bacccc4964606969df144f6 (diff)
gpu: nvgpu: abstract away ioctl gpfifo read
The biggest remaining Linuxism in the submit path is the copy_from_user() calls for reading the gpfifo entries to the HW-visible buffer. Abstract away the copy of one such segment starting at some offset and keep the wraparound logic and vidmem proxy in the core submit path. Jira NVGPU-705 Change-Id: I0c6438045c695e5e3f5da4fbc0c92d2c6e7f32cb Signed-off-by: Konsta Holtta <kholtta@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1730480 Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/os')
-rw-r--r--drivers/gpu/nvgpu/os/linux/channel.c99
-rw-r--r--drivers/gpu/nvgpu/os/linux/channel.h2
-rw-r--r--drivers/gpu/nvgpu/os/linux/ioctl_channel.c8
3 files changed, 69 insertions, 40 deletions
diff --git a/drivers/gpu/nvgpu/os/linux/channel.c b/drivers/gpu/nvgpu/os/linux/channel.c
index a84c5a1c..dd2b17ee 100644
--- a/drivers/gpu/nvgpu/os/linux/channel.c
+++ b/drivers/gpu/nvgpu/os/linux/channel.c
@@ -372,6 +372,18 @@ static bool nvgpu_channel_fence_framework_exists(struct channel_gk20a *ch)
372 return (fence_framework->timeline != NULL); 372 return (fence_framework->timeline != NULL);
373} 373}
374 374
375static int nvgpu_channel_copy_user_gpfifo(struct nvgpu_gpfifo_entry *dest,
376 struct nvgpu_gpfifo_userdata userdata, u32 start, u32 length)
377{
378 struct nvgpu_gpfifo_entry __user *user_gpfifo = userdata.entries;
379 unsigned long n;
380
381 n = copy_from_user(dest, user_gpfifo + start,
382 length * sizeof(struct nvgpu_gpfifo_entry));
383
384 return n == 0 ? 0 : -EFAULT;
385}
386
375int nvgpu_init_channel_support_linux(struct nvgpu_os_linux *l) 387int nvgpu_init_channel_support_linux(struct nvgpu_os_linux *l)
376{ 388{
377 struct gk20a *g = &l->g; 389 struct gk20a *g = &l->g;
@@ -403,6 +415,9 @@ int nvgpu_init_channel_support_linux(struct nvgpu_os_linux *l)
403 g->os_channel.destroy_os_fence_framework = 415 g->os_channel.destroy_os_fence_framework =
404 nvgpu_channel_destroy_os_fence_framework; 416 nvgpu_channel_destroy_os_fence_framework;
405 417
418 g->os_channel.copy_user_gpfifo =
419 nvgpu_channel_copy_user_gpfifo;
420
406 return 0; 421 return 0;
407 422
408err_clean: 423err_clean:
@@ -673,20 +688,20 @@ static void gk20a_submit_append_priv_cmdbuf(struct channel_gk20a *c,
673 */ 688 */
674static int gk20a_submit_append_gpfifo(struct channel_gk20a *c, 689static int gk20a_submit_append_gpfifo(struct channel_gk20a *c,
675 struct nvgpu_gpfifo_entry *kern_gpfifo, 690 struct nvgpu_gpfifo_entry *kern_gpfifo,
676 struct nvgpu_gpfifo_entry __user *user_gpfifo, 691 struct nvgpu_gpfifo_userdata userdata,
677 u32 num_entries) 692 u32 num_entries)
678{ 693{
679 /* byte offsets */ 694 struct gk20a *g = c->g;
680 u32 gpfifo_size = 695 u32 gpfifo_size = c->gpfifo.entry_num;
681 c->gpfifo.entry_num * sizeof(struct nvgpu_gpfifo_entry); 696 u32 len = num_entries;
682 u32 len = num_entries * sizeof(struct nvgpu_gpfifo_entry); 697 u32 start = c->gpfifo.put;
683 u32 start = c->gpfifo.put * sizeof(struct nvgpu_gpfifo_entry);
684 u32 end = start + len; /* exclusive */ 698 u32 end = start + len; /* exclusive */
685 struct nvgpu_mem *gpfifo_mem = &c->gpfifo.mem; 699 struct nvgpu_mem *gpfifo_mem = &c->gpfifo.mem;
686 struct nvgpu_gpfifo_entry *cpu_src; 700 struct nvgpu_gpfifo_entry *cpu_src;
687 int err; 701 int err;
688 702
689 if (user_gpfifo && !c->gpfifo.pipe) { 703 if (!kern_gpfifo && !c->gpfifo.pipe) {
704 struct nvgpu_gpfifo_entry *gpfifo_cpu = gpfifo_mem->cpu_va;
690 /* 705 /*
691 * This path (from userspace to sysmem) is special in order to 706 * This path (from userspace to sysmem) is special in order to
692 * avoid two copies unnecessarily (from user to pipe, then from 707 * avoid two copies unnecessarily (from user to pipe, then from
@@ -696,37 +711,45 @@ static int gk20a_submit_append_gpfifo(struct channel_gk20a *c,
696 /* wrap-around */ 711 /* wrap-around */
697 int length0 = gpfifo_size - start; 712 int length0 = gpfifo_size - start;
698 int length1 = len - length0; 713 int length1 = len - length0;
699 void __user *user2 = (u8 __user *)user_gpfifo + length0;
700 714
701 err = copy_from_user(gpfifo_mem->cpu_va + start, 715 err = g->os_channel.copy_user_gpfifo(
702 user_gpfifo, length0); 716 gpfifo_cpu + start, userdata,
717 0, length0);
703 if (err) 718 if (err)
704 return err; 719 return err;
705 720
706 err = copy_from_user(gpfifo_mem->cpu_va, 721 err = g->os_channel.copy_user_gpfifo(
707 user2, length1); 722 gpfifo_cpu, userdata,
723 length0, length1);
708 if (err) 724 if (err)
709 return err; 725 return err;
726
727 trace_write_pushbuffer_range(c, gpfifo_cpu, NULL,
728 start, length0);
729 trace_write_pushbuffer_range(c, gpfifo_cpu, NULL,
730 0, length1);
710 } else { 731 } else {
711 err = copy_from_user(gpfifo_mem->cpu_va + start, 732 err = g->os_channel.copy_user_gpfifo(
712 user_gpfifo, len); 733 gpfifo_cpu + start, userdata,
734 0, len);
713 if (err) 735 if (err)
714 return err; 736 return err;
715 }
716 737
717 trace_write_pushbuffer_range(c, NULL, user_gpfifo, 738 trace_write_pushbuffer_range(c, gpfifo_cpu, NULL,
718 0, num_entries); 739 start, len);
740 }
719 goto out; 741 goto out;
720 } else if (user_gpfifo) { 742 } else if (!kern_gpfifo) {
721 /* from userspace to vidmem, use the common copy path below */ 743 /* from userspace to vidmem, use the common copy path below */
722 err = copy_from_user(c->gpfifo.pipe, user_gpfifo, len); 744 err = g->os_channel.copy_user_gpfifo(c->gpfifo.pipe, userdata,
745 0, len);
723 if (err) 746 if (err)
724 return err; 747 return err;
725 748
726 cpu_src = c->gpfifo.pipe; 749 cpu_src = c->gpfifo.pipe;
727 } else { 750 } else {
728 /* from kernel to either sysmem or vidmem, don't need 751 /* from kernel to either sysmem or vidmem, don't need
729 * copy_from_user so use the common path below */ 752 * copy_user_gpfifo so use the common path below */
730 cpu_src = kern_gpfifo; 753 cpu_src = kern_gpfifo;
731 } 754 }
732 755
@@ -734,13 +757,18 @@ static int gk20a_submit_append_gpfifo(struct channel_gk20a *c,
734 /* wrap-around */ 757 /* wrap-around */
735 int length0 = gpfifo_size - start; 758 int length0 = gpfifo_size - start;
736 int length1 = len - length0; 759 int length1 = len - length0;
737 void *src2 = (u8 *)cpu_src + length0; 760 struct nvgpu_gpfifo_entry *src2 = cpu_src + length0;
761 int s_bytes = start * sizeof(struct nvgpu_gpfifo_entry);
762 int l0_bytes = length0 * sizeof(struct nvgpu_gpfifo_entry);
763 int l1_bytes = length1 * sizeof(struct nvgpu_gpfifo_entry);
738 764
739 nvgpu_mem_wr_n(c->g, gpfifo_mem, start, cpu_src, length0); 765 nvgpu_mem_wr_n(c->g, gpfifo_mem, s_bytes, cpu_src, l0_bytes);
740 nvgpu_mem_wr_n(c->g, gpfifo_mem, 0, src2, length1); 766 nvgpu_mem_wr_n(c->g, gpfifo_mem, 0, src2, l1_bytes);
741 } else { 767 } else {
742 nvgpu_mem_wr_n(c->g, gpfifo_mem, start, cpu_src, len); 768 nvgpu_mem_wr_n(c->g, gpfifo_mem,
743 769 start * sizeof(struct nvgpu_gpfifo_entry),
770 cpu_src,
771 len * sizeof(struct nvgpu_gpfifo_entry));
744 } 772 }
745 773
746 trace_write_pushbuffer_range(c, cpu_src, NULL, 0, num_entries); 774 trace_write_pushbuffer_range(c, cpu_src, NULL, 0, num_entries);
@@ -754,7 +782,7 @@ out:
754 782
755static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, 783static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
756 struct nvgpu_gpfifo_entry *gpfifo, 784 struct nvgpu_gpfifo_entry *gpfifo,
757 struct nvgpu_submit_gpfifo_args *args, 785 struct nvgpu_gpfifo_userdata userdata,
758 u32 num_entries, 786 u32 num_entries,
759 u32 flags, 787 u32 flags,
760 struct nvgpu_channel_fence *fence, 788 struct nvgpu_channel_fence *fence,
@@ -774,8 +802,6 @@ static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
774 int err = 0; 802 int err = 0;
775 bool need_job_tracking; 803 bool need_job_tracking;
776 bool need_deferred_cleanup = false; 804 bool need_deferred_cleanup = false;
777 struct nvgpu_gpfifo_entry __user *user_gpfifo = args ?
778 (struct nvgpu_gpfifo_entry __user *)(uintptr_t)args->gpfifo : NULL;
779 805
780 if (nvgpu_is_enabled(g, NVGPU_DRIVER_IS_DYING)) 806 if (nvgpu_is_enabled(g, NVGPU_DRIVER_IS_DYING))
781 return -ENODEV; 807 return -ENODEV;
@@ -795,9 +821,6 @@ static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
795 return -ENOMEM; 821 return -ENOMEM;
796 } 822 }
797 823
798 if (!gpfifo && !args)
799 return -EINVAL;
800
801 if ((flags & (NVGPU_SUBMIT_FLAGS_FENCE_WAIT | 824 if ((flags & (NVGPU_SUBMIT_FLAGS_FENCE_WAIT |
802 NVGPU_SUBMIT_FLAGS_FENCE_GET)) && 825 NVGPU_SUBMIT_FLAGS_FENCE_GET)) &&
803 !fence) 826 !fence)
@@ -964,9 +987,8 @@ static int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
964 if (wait_cmd) 987 if (wait_cmd)
965 gk20a_submit_append_priv_cmdbuf(c, wait_cmd); 988 gk20a_submit_append_priv_cmdbuf(c, wait_cmd);
966 989
967 if (gpfifo || user_gpfifo) 990 err = gk20a_submit_append_gpfifo(c, gpfifo, userdata,
968 err = gk20a_submit_append_gpfifo(c, gpfifo, user_gpfifo, 991 num_entries);
969 num_entries);
970 if (err) 992 if (err)
971 goto clean_up_job; 993 goto clean_up_job;
972 994
@@ -1020,14 +1042,14 @@ clean_up:
1020} 1042}
1021 1043
1022int gk20a_submit_channel_gpfifo_user(struct channel_gk20a *c, 1044int gk20a_submit_channel_gpfifo_user(struct channel_gk20a *c,
1023 struct nvgpu_submit_gpfifo_args *args, 1045 struct nvgpu_gpfifo_userdata userdata,
1024 u32 num_entries, 1046 u32 num_entries,
1025 u32 flags, 1047 u32 flags,
1026 struct nvgpu_channel_fence *fence, 1048 struct nvgpu_channel_fence *fence,
1027 struct gk20a_fence **fence_out, 1049 struct gk20a_fence **fence_out,
1028 struct fifo_profile_gk20a *profile) 1050 struct fifo_profile_gk20a *profile)
1029{ 1051{
1030 return gk20a_submit_channel_gpfifo(c, NULL, args, num_entries, 1052 return gk20a_submit_channel_gpfifo(c, NULL, userdata, num_entries,
1031 flags, fence, fence_out, profile); 1053 flags, fence, fence_out, profile);
1032} 1054}
1033 1055
@@ -1038,6 +1060,7 @@ int gk20a_submit_channel_gpfifo_kernel(struct channel_gk20a *c,
1038 struct nvgpu_channel_fence *fence, 1060 struct nvgpu_channel_fence *fence,
1039 struct gk20a_fence **fence_out) 1061 struct gk20a_fence **fence_out)
1040{ 1062{
1041 return gk20a_submit_channel_gpfifo(c, gpfifo, NULL, num_entries, flags, 1063 struct nvgpu_gpfifo_userdata userdata = { NULL, NULL };
1042 fence, fence_out, NULL); 1064 return gk20a_submit_channel_gpfifo(c, gpfifo, userdata, num_entries,
1065 flags, fence, fence_out, NULL);
1043} 1066}
diff --git a/drivers/gpu/nvgpu/os/linux/channel.h b/drivers/gpu/nvgpu/os/linux/channel.h
index 689ad8bf..43fa492b 100644
--- a/drivers/gpu/nvgpu/os/linux/channel.h
+++ b/drivers/gpu/nvgpu/os/linux/channel.h
@@ -85,7 +85,7 @@ struct channel_gk20a *gk20a_open_new_channel_with_cb(struct gk20a *g,
85 bool is_privileged_channel); 85 bool is_privileged_channel);
86 86
87int gk20a_submit_channel_gpfifo_user(struct channel_gk20a *c, 87int gk20a_submit_channel_gpfifo_user(struct channel_gk20a *c,
88 struct nvgpu_submit_gpfifo_args *args, 88 struct nvgpu_gpfifo_userdata userdata,
89 u32 num_entries, 89 u32 num_entries,
90 u32 flags, 90 u32 flags,
91 struct nvgpu_channel_fence *fence, 91 struct nvgpu_channel_fence *fence,
diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_channel.c b/drivers/gpu/nvgpu/os/linux/ioctl_channel.c
index ee4ef237..fa6a02d6 100644
--- a/drivers/gpu/nvgpu/os/linux/ioctl_channel.c
+++ b/drivers/gpu/nvgpu/os/linux/ioctl_channel.c
@@ -776,6 +776,7 @@ static int gk20a_ioctl_channel_submit_gpfifo(
776 u32 submit_flags = 0; 776 u32 submit_flags = 0;
777 int fd = -1; 777 int fd = -1;
778 struct gk20a *g = ch->g; 778 struct gk20a *g = ch->g;
779 struct nvgpu_gpfifo_userdata userdata;
779 780
780 int ret = 0; 781 int ret = 0;
781 nvgpu_log_fn(g, " "); 782 nvgpu_log_fn(g, " ");
@@ -798,7 +799,12 @@ static int gk20a_ioctl_channel_submit_gpfifo(
798 return fd; 799 return fd;
799 } 800 }
800 801
801 ret = gk20a_submit_channel_gpfifo_user(ch, args, args->num_entries, 802 userdata.entries = (struct nvgpu_gpfifo_entry __user*)
803 (uintptr_t)args->gpfifo;
804 userdata.context = NULL;
805
806 ret = gk20a_submit_channel_gpfifo_user(ch,
807 userdata, args->num_entries,
802 submit_flags, &fence, &fence_out, profile); 808 submit_flags, &fence, &fence_out, profile);
803 809
804 if (ret) { 810 if (ret) {