hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/gpu/drm/drm_gem.c
....@@ -38,10 +38,16 @@
3838 #include <linux/dma-buf.h>
3939 #include <linux/mem_encrypt.h>
4040 #include <linux/pagevec.h>
41
-#include <drm/drmP.h>
42
-#include <drm/drm_vma_manager.h>
41
+
42
+#include <drm/drm.h>
43
+#include <drm/drm_device.h>
44
+#include <drm/drm_drv.h>
45
+#include <drm/drm_file.h>
4346 #include <drm/drm_gem.h>
47
+#include <drm/drm_managed.h>
4448 #include <drm/drm_print.h>
49
+#include <drm/drm_vma_manager.h>
50
+
4551 #include "drm_internal.h"
4652
4753 /** @file drm_gem.c
....@@ -72,22 +78,11 @@
7278 * up at a later date, and as our interface with shmfs for memory allocation.
7379 */
7480
75
-/*
76
- * We make up offsets for buffer objects so we can recognize them at
77
- * mmap time.
78
- */
79
-
80
-/* pgoff in mmap is an unsigned long, so we need to make sure that
81
- * the faked up offset will fit
82
- */
83
-
84
-#if BITS_PER_LONG == 64
85
-#define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFFUL >> PAGE_SHIFT) + 1)
86
-#define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFFUL >> PAGE_SHIFT) * 16)
87
-#else
88
-#define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFUL >> PAGE_SHIFT) + 1)
89
-#define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFUL >> PAGE_SHIFT) * 16)
90
-#endif
81
+static void
82
+drm_gem_init_release(struct drm_device *dev, void *ptr)
83
+{
84
+ drm_vma_offset_manager_destroy(dev->vma_offset_manager);
85
+}
9186
9287 /**
9388 * drm_gem_init - Initialize the GEM device fields
....@@ -101,7 +96,8 @@
10196 mutex_init(&dev->object_name_lock);
10297 idr_init_base(&dev->object_name_idr, 1);
10398
104
- vma_offset_manager = kzalloc(sizeof(*vma_offset_manager), GFP_KERNEL);
99
+ vma_offset_manager = drmm_kzalloc(dev, sizeof(*vma_offset_manager),
100
+ GFP_KERNEL);
105101 if (!vma_offset_manager) {
106102 DRM_ERROR("out of memory\n");
107103 return -ENOMEM;
....@@ -112,16 +108,7 @@
112108 DRM_FILE_PAGE_OFFSET_START,
113109 DRM_FILE_PAGE_OFFSET_SIZE);
114110
115
- return 0;
116
-}
117
-
118
-void
119
-drm_gem_destroy(struct drm_device *dev)
120
-{
121
-
122
- drm_vma_offset_manager_destroy(dev->vma_offset_manager);
123
- kfree(dev->vma_offset_manager);
124
- dev->vma_offset_manager = NULL;
111
+ return drmm_add_action(dev, drm_gem_init_release, NULL);
125112 }
126113
127114 /**
....@@ -171,24 +158,13 @@
171158 kref_init(&obj->refcount);
172159 obj->handle_count = 0;
173160 obj->size = size;
161
+ dma_resv_init(&obj->_resv);
162
+ if (!obj->resv)
163
+ obj->resv = &obj->_resv;
164
+
174165 drm_vma_node_reset(&obj->vma_node);
175166 }
176167 EXPORT_SYMBOL(drm_gem_private_object_init);
177
-
178
-static void
179
-drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp)
180
-{
181
- /*
182
- * Note: obj->dma_buf can't disappear as long as we still hold a
183
- * handle reference in obj->handle_count.
184
- */
185
- mutex_lock(&filp->prime.lock);
186
- if (obj->dma_buf) {
187
- drm_prime_remove_buf_handle_locked(&filp->prime,
188
- obj->dma_buf);
189
- }
190
- mutex_unlock(&filp->prime.lock);
191
-}
192168
193169 /**
194170 * drm_gem_object_handle_free - release resources bound to userspace handles
....@@ -226,7 +202,7 @@
226202 struct drm_device *dev = obj->dev;
227203 bool final = false;
228204
229
- if (WARN_ON(obj->handle_count == 0))
205
+ if (WARN_ON(READ_ONCE(obj->handle_count) == 0))
230206 return;
231207
232208 /*
....@@ -244,7 +220,7 @@
244220 mutex_unlock(&dev->object_name_lock);
245221
246222 if (final)
247
- drm_gem_object_put_unlocked(obj);
223
+ drm_gem_object_put(obj);
248224 }
249225
250226 /*
....@@ -258,11 +234,12 @@
258234 struct drm_gem_object *obj = ptr;
259235 struct drm_device *dev = obj->dev;
260236
261
- if (dev->driver->gem_close_object)
237
+ if (obj->funcs && obj->funcs->close)
238
+ obj->funcs->close(obj, file_priv);
239
+ else if (dev->driver->gem_close_object)
262240 dev->driver->gem_close_object(obj, file_priv);
263241
264
- if (drm_core_check_feature(dev, DRIVER_PRIME))
265
- drm_gem_remove_prime_handles(obj, file_priv);
242
+ drm_prime_remove_buf_handle(&file_priv->prime, id);
266243 drm_vma_node_revoke(&obj->vma_node, file_priv);
267244
268245 drm_gem_object_handle_put_unlocked(obj);
....@@ -339,7 +316,7 @@
339316
340317 *offset = drm_vma_node_offset_addr(&obj->vma_node);
341318 out:
342
- drm_gem_object_put_unlocked(obj);
319
+ drm_gem_object_put(obj);
343320
344321 return ret;
345322 }
....@@ -411,7 +388,11 @@
411388 if (ret)
412389 goto err_remove;
413390
414
- if (dev->driver->gem_open_object) {
391
+ if (obj->funcs && obj->funcs->open) {
392
+ ret = obj->funcs->open(obj, file_priv);
393
+ if (ret)
394
+ goto err_revoke;
395
+ } else if (dev->driver->gem_open_object) {
415396 ret = dev->driver->gem_open_object(obj, file_priv);
416397 if (ret)
417398 goto err_revoke;
....@@ -435,7 +416,7 @@
435416 * drm_gem_handle_create - create a gem handle for an object
436417 * @file_priv: drm file-private structure to register the handle for
437418 * @obj: object to register
438
- * @handlep: pionter to return the created handle to the caller
419
+ * @handlep: pointer to return the created handle to the caller
439420 *
440421 * Create a handle for this object. This adds a handle reference to the object,
441422 * which includes a regular reference count. Callers will likely want to
....@@ -552,6 +533,10 @@
552533 * set during initialization. If you have special zone constraints, set them
553534 * after drm_gem_object_init() via mapping_set_gfp_mask(). shmem-core takes care
554535 * to keep pages in the required zone during swap-in.
536
+ *
537
+ * This function is only valid on objects initialized with
538
+ * drm_gem_object_init(), but not for those initialized with
539
+ * drm_gem_private_object_init() only.
555540 */
556541 struct page **drm_gem_get_pages(struct drm_gem_object *obj)
557542 {
....@@ -559,6 +544,10 @@
559544 struct page *p, **pages;
560545 struct pagevec pvec;
561546 int i, npages;
547
+
548
+
549
+ if (WARN_ON(!obj->filp))
550
+ return ERR_PTR(-EINVAL);
562551
563552 /* This is the shared memory object that backs the GEM resource */
564553 mapping = obj->filp->f_mapping;
....@@ -636,6 +625,9 @@
636625
637626 pagevec_init(&pvec);
638627 for (i = 0; i < npages; i++) {
628
+ if (!pages[i])
629
+ continue;
630
+
639631 if (dirty)
640632 set_page_dirty(pages[i]);
641633
....@@ -653,8 +645,87 @@
653645 }
654646 EXPORT_SYMBOL(drm_gem_put_pages);
655647
648
+static int objects_lookup(struct drm_file *filp, u32 *handle, int count,
649
+ struct drm_gem_object **objs)
650
+{
651
+ int i, ret = 0;
652
+ struct drm_gem_object *obj;
653
+
654
+ spin_lock(&filp->table_lock);
655
+
656
+ for (i = 0; i < count; i++) {
657
+ /* Check if we currently have a reference on the object */
658
+ obj = idr_find(&filp->object_idr, handle[i]);
659
+ if (!obj) {
660
+ ret = -ENOENT;
661
+ break;
662
+ }
663
+ drm_gem_object_get(obj);
664
+ objs[i] = obj;
665
+ }
666
+ spin_unlock(&filp->table_lock);
667
+
668
+ return ret;
669
+}
670
+
656671 /**
657
- * drm_gem_object_lookup - look up a GEM object from it's handle
672
+ * drm_gem_objects_lookup - look up GEM objects from an array of handles
673
+ * @filp: DRM file private date
674
+ * @bo_handles: user pointer to array of userspace handle
675
+ * @count: size of handle array
676
+ * @objs_out: returned pointer to array of drm_gem_object pointers
677
+ *
678
+ * Takes an array of userspace handles and returns a newly allocated array of
679
+ * GEM objects.
680
+ *
681
+ * For a single handle lookup, use drm_gem_object_lookup().
682
+ *
683
+ * Returns:
684
+ *
685
+ * @objs filled in with GEM object pointers. Returned GEM objects need to be
686
+ * released with drm_gem_object_put(). -ENOENT is returned on a lookup
687
+ * failure. 0 is returned on success.
688
+ *
689
+ */
690
+int drm_gem_objects_lookup(struct drm_file *filp, void __user *bo_handles,
691
+ int count, struct drm_gem_object ***objs_out)
692
+{
693
+ int ret;
694
+ u32 *handles;
695
+ struct drm_gem_object **objs;
696
+
697
+ if (!count)
698
+ return 0;
699
+
700
+ objs = kvmalloc_array(count, sizeof(struct drm_gem_object *),
701
+ GFP_KERNEL | __GFP_ZERO);
702
+ if (!objs)
703
+ return -ENOMEM;
704
+
705
+ *objs_out = objs;
706
+
707
+ handles = kvmalloc_array(count, sizeof(u32), GFP_KERNEL);
708
+ if (!handles) {
709
+ ret = -ENOMEM;
710
+ goto out;
711
+ }
712
+
713
+ if (copy_from_user(handles, bo_handles, count * sizeof(u32))) {
714
+ ret = -EFAULT;
715
+ DRM_DEBUG("Failed to copy in GEM handles\n");
716
+ goto out;
717
+ }
718
+
719
+ ret = objects_lookup(filp, handles, count, objs);
720
+out:
721
+ kvfree(handles);
722
+ return ret;
723
+
724
+}
725
+EXPORT_SYMBOL(drm_gem_objects_lookup);
726
+
727
+/**
728
+ * drm_gem_object_lookup - look up a GEM object from its handle
658729 * @filp: DRM file private date
659730 * @handle: userspace handle
660731 *
....@@ -662,24 +733,56 @@
662733 *
663734 * A reference to the object named by the handle if such exists on @filp, NULL
664735 * otherwise.
736
+ *
737
+ * If looking up an array of handles, use drm_gem_objects_lookup().
665738 */
666739 struct drm_gem_object *
667740 drm_gem_object_lookup(struct drm_file *filp, u32 handle)
668741 {
669
- struct drm_gem_object *obj;
742
+ struct drm_gem_object *obj = NULL;
670743
671
- spin_lock(&filp->table_lock);
672
-
673
- /* Check if we currently have a reference on the object */
674
- obj = idr_find(&filp->object_idr, handle);
675
- if (obj)
676
- drm_gem_object_get(obj);
677
-
678
- spin_unlock(&filp->table_lock);
679
-
744
+ objects_lookup(filp, &handle, 1, &obj);
680745 return obj;
681746 }
682747 EXPORT_SYMBOL(drm_gem_object_lookup);
748
+
749
+/**
750
+ * drm_gem_dma_resv_wait - Wait on GEM object's reservation's objects
751
+ * shared and/or exclusive fences.
752
+ * @filep: DRM file private date
753
+ * @handle: userspace handle
754
+ * @wait_all: if true, wait on all fences, else wait on just exclusive fence
755
+ * @timeout: timeout value in jiffies or zero to return immediately
756
+ *
757
+ * Returns:
758
+ *
759
+ * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or
760
+ * greater than 0 on success.
761
+ */
762
+long drm_gem_dma_resv_wait(struct drm_file *filep, u32 handle,
763
+ bool wait_all, unsigned long timeout)
764
+{
765
+ long ret;
766
+ struct drm_gem_object *obj;
767
+
768
+ obj = drm_gem_object_lookup(filep, handle);
769
+ if (!obj) {
770
+ DRM_DEBUG("Failed to look up GEM BO %d\n", handle);
771
+ return -EINVAL;
772
+ }
773
+
774
+ ret = dma_resv_wait_timeout_rcu(obj->resv, wait_all,
775
+ true, timeout);
776
+ if (ret == 0)
777
+ ret = -ETIME;
778
+ else if (ret > 0)
779
+ ret = 0;
780
+
781
+ drm_gem_object_put(obj);
782
+
783
+ return ret;
784
+}
785
+EXPORT_SYMBOL(drm_gem_dma_resv_wait);
683786
684787 /**
685788 * drm_gem_close_ioctl - implementation of the GEM_CLOSE ioctl
....@@ -697,7 +800,7 @@
697800 int ret;
698801
699802 if (!drm_core_check_feature(dev, DRIVER_GEM))
700
- return -ENODEV;
803
+ return -EOPNOTSUPP;
701804
702805 ret = drm_gem_handle_delete(file_priv, args->handle);
703806
....@@ -724,7 +827,7 @@
724827 int ret;
725828
726829 if (!drm_core_check_feature(dev, DRIVER_GEM))
727
- return -ENODEV;
830
+ return -EOPNOTSUPP;
728831
729832 obj = drm_gem_object_lookup(file_priv, args->handle);
730833 if (obj == NULL)
....@@ -750,7 +853,7 @@
750853
751854 err:
752855 mutex_unlock(&dev->object_name_lock);
753
- drm_gem_object_put_unlocked(obj);
856
+ drm_gem_object_put(obj);
754857 return ret;
755858 }
756859
....@@ -761,6 +864,9 @@
761864 * @file_priv: drm file-private structure
762865 *
763866 * Open an object using the global name, returning a handle and the size.
867
+ *
868
+ * This handle (of course) holds a reference to the object, so the object
869
+ * will not go away until the handle is deleted.
764870 */
765871 int
766872 drm_gem_open_ioctl(struct drm_device *dev, void *data,
....@@ -772,7 +878,7 @@
772878 u32 handle;
773879
774880 if (!drm_core_check_feature(dev, DRIVER_GEM))
775
- return -ENODEV;
881
+ return -EOPNOTSUPP;
776882
777883 mutex_lock(&dev->object_name_lock);
778884 obj = idr_find(&dev->object_name_idr, (int) args->name);
....@@ -792,7 +898,7 @@
792898 args->size = obj->size;
793899
794900 err:
795
- drm_gem_object_put_unlocked(obj);
901
+ drm_gem_object_put(obj);
796902 return ret;
797903 }
798904
....@@ -843,6 +949,7 @@
843949 if (obj->filp)
844950 fput(obj->filp);
845951
952
+ dma_resv_fini(&obj->_resv);
846953 drm_gem_free_mmap_offset(obj);
847954 }
848955 EXPORT_SYMBOL(drm_gem_object_release);
....@@ -852,7 +959,6 @@
852959 * @kref: kref of the object to free
853960 *
854961 * Called after the last reference to the object has been lost.
855
- * Must be called holding &drm_device.struct_mutex.
856962 *
857963 * Frees the object
858964 */
....@@ -863,48 +969,15 @@
863969 container_of(kref, struct drm_gem_object, refcount);
864970 struct drm_device *dev = obj->dev;
865971
866
- if (dev->driver->gem_free_object_unlocked) {
972
+ if (obj->funcs)
973
+ obj->funcs->free(obj);
974
+ else if (dev->driver->gem_free_object_unlocked)
867975 dev->driver->gem_free_object_unlocked(obj);
868
- } else if (dev->driver->gem_free_object) {
869
- WARN_ON(!mutex_is_locked(&dev->struct_mutex));
870
-
871
- dev->driver->gem_free_object(obj);
872
- }
873976 }
874977 EXPORT_SYMBOL(drm_gem_object_free);
875978
876979 /**
877
- * drm_gem_object_put_unlocked - drop a GEM buffer object reference
878
- * @obj: GEM buffer object
879
- *
880
- * This releases a reference to @obj. Callers must not hold the
881
- * &drm_device.struct_mutex lock when calling this function.
882
- *
883
- * See also __drm_gem_object_put().
884
- */
885
-void
886
-drm_gem_object_put_unlocked(struct drm_gem_object *obj)
887
-{
888
- struct drm_device *dev;
889
-
890
- if (!obj)
891
- return;
892
-
893
- dev = obj->dev;
894
-
895
- if (dev->driver->gem_free_object_unlocked) {
896
- kref_put(&obj->refcount, drm_gem_object_free);
897
- } else {
898
- might_lock(&dev->struct_mutex);
899
- if (kref_put_mutex(&obj->refcount, drm_gem_object_free,
900
- &dev->struct_mutex))
901
- mutex_unlock(&dev->struct_mutex);
902
- }
903
-}
904
-EXPORT_SYMBOL(drm_gem_object_put_unlocked);
905
-
906
-/**
907
- * drm_gem_object_put - release a GEM buffer object reference
980
+ * drm_gem_object_put_locked - release a GEM buffer object reference
908981 * @obj: GEM buffer object
909982 *
910983 * This releases a reference to @obj. Callers must hold the
....@@ -912,10 +985,10 @@
912985 * driver doesn't use &drm_device.struct_mutex for anything.
913986 *
914987 * For drivers not encumbered with legacy locking use
915
- * drm_gem_object_put_unlocked() instead.
988
+ * drm_gem_object_put() instead.
916989 */
917990 void
918
-drm_gem_object_put(struct drm_gem_object *obj)
991
+drm_gem_object_put_locked(struct drm_gem_object *obj)
919992 {
920993 if (obj) {
921994 WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
....@@ -923,7 +996,7 @@
923996 kref_put(&obj->refcount, drm_gem_object_free);
924997 }
925998 }
926
-EXPORT_SYMBOL(drm_gem_object_put);
999
+EXPORT_SYMBOL(drm_gem_object_put_locked);
9271000
9281001 /**
9291002 * drm_gem_vm_open - vma->ops->open implementation for GEM
....@@ -951,7 +1024,7 @@
9511024 {
9521025 struct drm_gem_object *obj = vma->vm_private_data;
9531026
954
- drm_gem_object_put_unlocked(obj);
1027
+ drm_gem_object_put(obj);
9551028 }
9561029 EXPORT_SYMBOL(drm_gem_vm_close);
9571030
....@@ -983,19 +1056,11 @@
9831056 struct vm_area_struct *vma)
9841057 {
9851058 struct drm_device *dev = obj->dev;
1059
+ int ret;
9861060
9871061 /* Check for valid size. */
9881062 if (obj_size < vma->vm_end - vma->vm_start)
9891063 return -EINVAL;
990
-
991
- if (!dev->driver->gem_vm_ops)
992
- return -EINVAL;
993
-
994
- vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
995
- vma->vm_ops = dev->driver->gem_vm_ops;
996
- vma->vm_private_data = obj;
997
- vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
998
- vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
9991064
10001065 /* Take a ref for this mapping of the object, so that the fault
10011066 * handler can dereference the mmap offset's pointer to the object.
....@@ -1004,6 +1069,30 @@
10041069 * by a vm_open due to mremap or partial unmap or whatever).
10051070 */
10061071 drm_gem_object_get(obj);
1072
+
1073
+ vma->vm_private_data = obj;
1074
+
1075
+ if (obj->funcs && obj->funcs->mmap) {
1076
+ ret = obj->funcs->mmap(obj, vma);
1077
+ if (ret) {
1078
+ drm_gem_object_put(obj);
1079
+ return ret;
1080
+ }
1081
+ WARN_ON(!(vma->vm_flags & VM_DONTEXPAND));
1082
+ } else {
1083
+ if (obj->funcs && obj->funcs->vm_ops)
1084
+ vma->vm_ops = obj->funcs->vm_ops;
1085
+ else if (dev->driver->gem_vm_ops)
1086
+ vma->vm_ops = dev->driver->gem_vm_ops;
1087
+ else {
1088
+ drm_gem_object_put(obj);
1089
+ return -EINVAL;
1090
+ }
1091
+
1092
+ vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
1093
+ vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
1094
+ vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
1095
+ }
10071096
10081097 return 0;
10091098 }
....@@ -1060,13 +1149,13 @@
10601149 return -EINVAL;
10611150
10621151 if (!drm_vma_node_is_allowed(node, priv)) {
1063
- drm_gem_object_put_unlocked(obj);
1152
+ drm_gem_object_put(obj);
10641153 return -EACCES;
10651154 }
10661155
10671156 if (node->readonly) {
10681157 if (vma->vm_flags & VM_WRITE) {
1069
- drm_gem_object_put_unlocked(obj);
1158
+ drm_gem_object_put(obj);
10701159 return -EINVAL;
10711160 }
10721161
....@@ -1076,7 +1165,7 @@
10761165 ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node) << PAGE_SHIFT,
10771166 vma);
10781167
1079
- drm_gem_object_put_unlocked(obj);
1168
+ drm_gem_object_put(obj);
10801169
10811170 return ret;
10821171 }
....@@ -1094,6 +1183,223 @@
10941183 drm_printf_indent(p, indent, "imported=%s\n",
10951184 obj->import_attach ? "yes" : "no");
10961185
1097
- if (obj->dev->driver->gem_print_info)
1098
- obj->dev->driver->gem_print_info(p, indent, obj);
1186
+ if (obj->funcs && obj->funcs->print_info)
1187
+ obj->funcs->print_info(p, indent, obj);
10991188 }
1189
+
1190
+int drm_gem_pin(struct drm_gem_object *obj)
1191
+{
1192
+ if (obj->funcs && obj->funcs->pin)
1193
+ return obj->funcs->pin(obj);
1194
+ else if (obj->dev->driver->gem_prime_pin)
1195
+ return obj->dev->driver->gem_prime_pin(obj);
1196
+ else
1197
+ return 0;
1198
+}
1199
+
1200
+void drm_gem_unpin(struct drm_gem_object *obj)
1201
+{
1202
+ if (obj->funcs && obj->funcs->unpin)
1203
+ obj->funcs->unpin(obj);
1204
+ else if (obj->dev->driver->gem_prime_unpin)
1205
+ obj->dev->driver->gem_prime_unpin(obj);
1206
+}
1207
+
1208
+void *drm_gem_vmap(struct drm_gem_object *obj)
1209
+{
1210
+ void *vaddr;
1211
+
1212
+ if (obj->funcs && obj->funcs->vmap)
1213
+ vaddr = obj->funcs->vmap(obj);
1214
+ else if (obj->dev->driver->gem_prime_vmap)
1215
+ vaddr = obj->dev->driver->gem_prime_vmap(obj);
1216
+ else
1217
+ vaddr = ERR_PTR(-EOPNOTSUPP);
1218
+
1219
+ if (!vaddr)
1220
+ vaddr = ERR_PTR(-ENOMEM);
1221
+
1222
+ return vaddr;
1223
+}
1224
+
1225
+void drm_gem_vunmap(struct drm_gem_object *obj, void *vaddr)
1226
+{
1227
+ if (!vaddr)
1228
+ return;
1229
+
1230
+ if (obj->funcs && obj->funcs->vunmap)
1231
+ obj->funcs->vunmap(obj, vaddr);
1232
+ else if (obj->dev->driver->gem_prime_vunmap)
1233
+ obj->dev->driver->gem_prime_vunmap(obj, vaddr);
1234
+}
1235
+
1236
+/**
1237
+ * drm_gem_lock_reservations - Sets up the ww context and acquires
1238
+ * the lock on an array of GEM objects.
1239
+ *
1240
+ * Once you've locked your reservations, you'll want to set up space
1241
+ * for your shared fences (if applicable), submit your job, then
1242
+ * drm_gem_unlock_reservations().
1243
+ *
1244
+ * @objs: drm_gem_objects to lock
1245
+ * @count: Number of objects in @objs
1246
+ * @acquire_ctx: struct ww_acquire_ctx that will be initialized as
1247
+ * part of tracking this set of locked reservations.
1248
+ */
1249
+int
1250
+drm_gem_lock_reservations(struct drm_gem_object **objs, int count,
1251
+ struct ww_acquire_ctx *acquire_ctx)
1252
+{
1253
+ int contended = -1;
1254
+ int i, ret;
1255
+
1256
+ ww_acquire_init(acquire_ctx, &reservation_ww_class);
1257
+
1258
+retry:
1259
+ if (contended != -1) {
1260
+ struct drm_gem_object *obj = objs[contended];
1261
+
1262
+ ret = dma_resv_lock_slow_interruptible(obj->resv,
1263
+ acquire_ctx);
1264
+ if (ret) {
1265
+ ww_acquire_fini(acquire_ctx);
1266
+ return ret;
1267
+ }
1268
+ }
1269
+
1270
+ for (i = 0; i < count; i++) {
1271
+ if (i == contended)
1272
+ continue;
1273
+
1274
+ ret = dma_resv_lock_interruptible(objs[i]->resv,
1275
+ acquire_ctx);
1276
+ if (ret) {
1277
+ int j;
1278
+
1279
+ for (j = 0; j < i; j++)
1280
+ dma_resv_unlock(objs[j]->resv);
1281
+
1282
+ if (contended != -1 && contended >= i)
1283
+ dma_resv_unlock(objs[contended]->resv);
1284
+
1285
+ if (ret == -EDEADLK) {
1286
+ contended = i;
1287
+ goto retry;
1288
+ }
1289
+
1290
+ ww_acquire_fini(acquire_ctx);
1291
+ return ret;
1292
+ }
1293
+ }
1294
+
1295
+ ww_acquire_done(acquire_ctx);
1296
+
1297
+ return 0;
1298
+}
1299
+EXPORT_SYMBOL(drm_gem_lock_reservations);
1300
+
1301
+void
1302
+drm_gem_unlock_reservations(struct drm_gem_object **objs, int count,
1303
+ struct ww_acquire_ctx *acquire_ctx)
1304
+{
1305
+ int i;
1306
+
1307
+ for (i = 0; i < count; i++)
1308
+ dma_resv_unlock(objs[i]->resv);
1309
+
1310
+ ww_acquire_fini(acquire_ctx);
1311
+}
1312
+EXPORT_SYMBOL(drm_gem_unlock_reservations);
1313
+
1314
+/**
1315
+ * drm_gem_fence_array_add - Adds the fence to an array of fences to be
1316
+ * waited on, deduplicating fences from the same context.
1317
+ *
1318
+ * @fence_array: array of dma_fence * for the job to block on.
1319
+ * @fence: the dma_fence to add to the list of dependencies.
1320
+ *
1321
+ * Returns:
1322
+ * 0 on success, or an error on failing to expand the array.
1323
+ */
1324
+int drm_gem_fence_array_add(struct xarray *fence_array,
1325
+ struct dma_fence *fence)
1326
+{
1327
+ struct dma_fence *entry;
1328
+ unsigned long index;
1329
+ u32 id = 0;
1330
+ int ret;
1331
+
1332
+ if (!fence)
1333
+ return 0;
1334
+
1335
+ /* Deduplicate if we already depend on a fence from the same context.
1336
+ * This lets the size of the array of deps scale with the number of
1337
+ * engines involved, rather than the number of BOs.
1338
+ */
1339
+ xa_for_each(fence_array, index, entry) {
1340
+ if (entry->context != fence->context)
1341
+ continue;
1342
+
1343
+ if (dma_fence_is_later(fence, entry)) {
1344
+ dma_fence_put(entry);
1345
+ xa_store(fence_array, index, fence, GFP_KERNEL);
1346
+ } else {
1347
+ dma_fence_put(fence);
1348
+ }
1349
+ return 0;
1350
+ }
1351
+
1352
+ ret = xa_alloc(fence_array, &id, fence, xa_limit_32b, GFP_KERNEL);
1353
+ if (ret != 0)
1354
+ dma_fence_put(fence);
1355
+
1356
+ return ret;
1357
+}
1358
+EXPORT_SYMBOL(drm_gem_fence_array_add);
1359
+
1360
+/**
1361
+ * drm_gem_fence_array_add_implicit - Adds the implicit dependencies tracked
1362
+ * in the GEM object's reservation object to an array of dma_fences for use in
1363
+ * scheduling a rendering job.
1364
+ *
1365
+ * This should be called after drm_gem_lock_reservations() on your array of
1366
+ * GEM objects used in the job but before updating the reservations with your
1367
+ * own fences.
1368
+ *
1369
+ * @fence_array: array of dma_fence * for the job to block on.
1370
+ * @obj: the gem object to add new dependencies from.
1371
+ * @write: whether the job might write the object (so we need to depend on
1372
+ * shared fences in the reservation object).
1373
+ */
1374
+int drm_gem_fence_array_add_implicit(struct xarray *fence_array,
1375
+ struct drm_gem_object *obj,
1376
+ bool write)
1377
+{
1378
+ int ret;
1379
+ struct dma_fence **fences;
1380
+ unsigned int i, fence_count;
1381
+
1382
+ if (!write) {
1383
+ struct dma_fence *fence =
1384
+ dma_resv_get_excl_rcu(obj->resv);
1385
+
1386
+ return drm_gem_fence_array_add(fence_array, fence);
1387
+ }
1388
+
1389
+ ret = dma_resv_get_fences_rcu(obj->resv, NULL,
1390
+ &fence_count, &fences);
1391
+ if (ret || !fence_count)
1392
+ return ret;
1393
+
1394
+ for (i = 0; i < fence_count; i++) {
1395
+ ret = drm_gem_fence_array_add(fence_array, fences[i]);
1396
+ if (ret)
1397
+ break;
1398
+ }
1399
+
1400
+ for (; i < fence_count; i++)
1401
+ dma_fence_put(fences[i]);
1402
+ kfree(fences);
1403
+ return ret;
1404
+}
1405
+EXPORT_SYMBOL(drm_gem_fence_array_add_implicit);