aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorJason Ekstrand <jason@jlekstrand.net>2017-08-25 13:52:26 -0400
committerDave Airlie <airlied@redhat.com>2017-08-28 16:28:23 -0400
commit3e6fb72d6cef6a46f8531a01ed290785952fe25b (patch)
tree85e1a61b5e384970448b03a36b14d0e1a68193e9 /drivers/gpu
parente7aca5031a2fb51b6120864d0eff5478c95e6651 (diff)
drm/syncobj: Add a syncobj_array_find helper
The wait ioctl has a bunch of code to read an syncobj handle array from userspace and turn it into an array of syncobj pointers. We're about to add two new IOCTLs which will need to work with arrays of syncobj handles so let's make some helpers. Signed-off-by: Jason Ekstrand <jason@jlekstrand.net> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/drm_syncobj.c89
1 files changed, 58 insertions, 31 deletions
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index cccd3bd194c6..15e74ca61760 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -798,58 +798,43 @@ static int drm_syncobj_array_wait(struct drm_device *dev,
798 return 0; 798 return 0;
799} 799}
800 800
801int 801static int drm_syncobj_array_find(struct drm_file *file_private,
802drm_syncobj_wait_ioctl(struct drm_device *dev, void *data, 802 void *user_handles, uint32_t count_handles,
803 struct drm_file *file_private) 803 struct drm_syncobj ***syncobjs_out)
804{ 804{
805 struct drm_syncobj_wait *args = data; 805 uint32_t i, *handles;
806 uint32_t *handles;
807 struct drm_syncobj **syncobjs; 806 struct drm_syncobj **syncobjs;
808 int ret = 0; 807 int ret;
809 uint32_t i;
810
811 if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ))
812 return -ENODEV;
813
814 if (args->flags & ~(DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL |
815 DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT))
816 return -EINVAL;
817
818 if (args->count_handles == 0)
819 return -EINVAL;
820 808
821 /* Get the handles from userspace */ 809 handles = kmalloc_array(count_handles, sizeof(*handles), GFP_KERNEL);
822 handles = kmalloc_array(args->count_handles, sizeof(uint32_t),
823 GFP_KERNEL);
824 if (handles == NULL) 810 if (handles == NULL)
825 return -ENOMEM; 811 return -ENOMEM;
826 812
827 if (copy_from_user(handles, 813 if (copy_from_user(handles, user_handles,
828 u64_to_user_ptr(args->handles), 814 sizeof(uint32_t) * count_handles)) {
829 sizeof(uint32_t) * args->count_handles)) {
830 ret = -EFAULT; 815 ret = -EFAULT;
831 goto err_free_handles; 816 goto err_free_handles;
832 } 817 }
833 818
834 syncobjs = kcalloc(args->count_handles, 819 syncobjs = kmalloc_array(count_handles, sizeof(*syncobjs), GFP_KERNEL);
835 sizeof(struct drm_syncobj *), GFP_KERNEL); 820 if (syncobjs == NULL) {
836 if (!syncobjs) {
837 ret = -ENOMEM; 821 ret = -ENOMEM;
838 goto err_free_handles; 822 goto err_free_handles;
839 } 823 }
840 824
841 for (i = 0; i < args->count_handles; i++) { 825 for (i = 0; i < count_handles; i++) {
842 syncobjs[i] = drm_syncobj_find(file_private, handles[i]); 826 syncobjs[i] = drm_syncobj_find(file_private, handles[i]);
843 if (!syncobjs[i]) { 827 if (!syncobjs[i]) {
844 ret = -ENOENT; 828 ret = -ENOENT;
845 goto err_free_fence_array; 829 goto err_put_syncobjs;
846 } 830 }
847 } 831 }
848 832
849 ret = drm_syncobj_array_wait(dev, file_private, 833 kfree(handles);
850 args, syncobjs); 834 *syncobjs_out = syncobjs;
835 return 0;
851 836
852err_free_fence_array: 837err_put_syncobjs:
853 while (i-- > 0) 838 while (i-- > 0)
854 drm_syncobj_put(syncobjs[i]); 839 drm_syncobj_put(syncobjs[i]);
855 kfree(syncobjs); 840 kfree(syncobjs);
@@ -858,3 +843,45 @@ err_free_handles:
858 843
859 return ret; 844 return ret;
860} 845}
846
847static void drm_syncobj_array_free(struct drm_syncobj **syncobjs,
848 uint32_t count)
849{
850 uint32_t i;
851 for (i = 0; i < count; i++)
852 drm_syncobj_put(syncobjs[i]);
853 kfree(syncobjs);
854}
855
856int
857drm_syncobj_wait_ioctl(struct drm_device *dev, void *data,
858 struct drm_file *file_private)
859{
860 struct drm_syncobj_wait *args = data;
861 struct drm_syncobj **syncobjs;
862 int ret = 0;
863
864 if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ))
865 return -ENODEV;
866
867 if (args->flags & ~(DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL |
868 DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT))
869 return -EINVAL;
870
871 if (args->count_handles == 0)
872 return -EINVAL;
873
874 ret = drm_syncobj_array_find(file_private,
875 u64_to_user_ptr(args->handles),
876 args->count_handles,
877 &syncobjs);
878 if (ret < 0)
879 return ret;
880
881 ret = drm_syncobj_array_wait(dev, file_private,
882 args, syncobjs);
883
884 drm_syncobj_array_free(syncobjs, args->count_handles);
885
886 return ret;
887}