dma-buf: use new iterator in dma_resv_get_fences v3
authorChristian König <christian.koenig@amd.com>
Tue, 15 Jun 2021 13:25:22 +0000 (15:25 +0200)
committerChristian König <christian.koenig@amd.com>
Wed, 6 Oct 2021 07:48:48 +0000 (09:48 +0200)
This makes the function much simpler since the complex
retry logic is now handled elsewhere.

v2: use sizeof(void*) instead
v3: fix rebase bug

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20211005113742.1101-6-christian.koenig@amd.com
drivers/dma-buf/dma-resv.c

index 08e5b8c381f479e3411f663799a70e5c39176f00..5d4fe62cc13253378692be999fa3640ca341fddf 100644 (file)
@@ -489,99 +489,61 @@ EXPORT_SYMBOL(dma_resv_copy_fences);
  * dma_resv_get_fences - Get an object's shared and exclusive
  * fences without update side lock held
  * @obj: the reservation object
- * @pfence_excl: the returned exclusive fence (or NULL)
- * @pshared_count: the number of shared fences returned
- * @pshared: the array of shared fence ptrs returned (array is krealloc'd to
+ * @fence_excl: the returned exclusive fence (or NULL)
+ * @shared_count: the number of shared fences returned
+ * @shared: the array of shared fence ptrs returned (array is krealloc'd to
  * the required size, and must be freed by caller)
  *
  * Retrieve all fences from the reservation object. If the pointer for the
  * exclusive fence is not specified the fence is put into the array of the
  * shared fences as well. Returns either zero or -ENOMEM.
  */
-int dma_resv_get_fences(struct dma_resv *obj, struct dma_fence **pfence_excl,
-                       unsigned int *pshared_count,
-                       struct dma_fence ***pshared)
+int dma_resv_get_fences(struct dma_resv *obj, struct dma_fence **fence_excl,
+                       unsigned int *shared_count, struct dma_fence ***shared)
 {
-       struct dma_fence **shared = NULL;
-       struct dma_fence *fence_excl;
-       unsigned int shared_count;
-       int ret = 1;
-
-       do {
-               struct dma_resv_list *fobj;
-               unsigned int i, seq;
-               size_t sz = 0;
-
-               shared_count = i = 0;
-
-               rcu_read_lock();
-               seq = read_seqcount_begin(&obj->seq);
+       struct dma_resv_iter cursor;
+       struct dma_fence *fence;
 
-               fence_excl = dma_resv_excl_fence(obj);
-               if (fence_excl && !dma_fence_get_rcu(fence_excl))
-                       goto unlock;
+       *shared_count = 0;
+       *shared = NULL;
 
-               fobj = dma_resv_shared_list(obj);
-               if (fobj)
-                       sz += sizeof(*shared) * fobj->shared_max;
+       if (fence_excl)
+               *fence_excl = NULL;
 
-               if (!pfence_excl && fence_excl)
-                       sz += sizeof(*shared);
+       dma_resv_iter_begin(&cursor, obj, true);
+       dma_resv_for_each_fence_unlocked(&cursor, fence) {
 
-               if (sz) {
-                       struct dma_fence **nshared;
+               if (dma_resv_iter_is_restarted(&cursor)) {
+                       unsigned int count;
 
-                       nshared = krealloc(shared, sz,
-                                          GFP_NOWAIT | __GFP_NOWARN);
-                       if (!nshared) {
-                               rcu_read_unlock();
+                       while (*shared_count)
+                               dma_fence_put((*shared)[--(*shared_count)]);
 
-                               dma_fence_put(fence_excl);
-                               fence_excl = NULL;
+                       if (fence_excl)
+                               dma_fence_put(*fence_excl);
 
-                               nshared = krealloc(shared, sz, GFP_KERNEL);
-                               if (nshared) {
-                                       shared = nshared;
-                                       continue;
-                               }
+                       count = cursor.fences ? cursor.fences->shared_count : 0;
+                       count += fence_excl ? 0 : 1;
 
-                               ret = -ENOMEM;
-                               break;
+                       /* Eventually re-allocate the array */
+                       *shared = krealloc_array(*shared, count,
+                                                sizeof(void *),
+                                                GFP_KERNEL);
+                       if (count && !*shared) {
+                               dma_resv_iter_end(&cursor);
+                               return -ENOMEM;
                        }
-                       shared = nshared;
-                       shared_count = fobj ? fobj->shared_count : 0;
-                       for (i = 0; i < shared_count; ++i) {
-                               shared[i] = rcu_dereference(fobj->shared[i]);
-                               if (!dma_fence_get_rcu(shared[i]))
-                                       break;
-                       }
-               }
-
-               if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) {
-                       while (i--)
-                               dma_fence_put(shared[i]);
-                       dma_fence_put(fence_excl);
-                       goto unlock;
                }
 
-               ret = 0;
-unlock:
-               rcu_read_unlock();
-       } while (ret);
-
-       if (pfence_excl)
-               *pfence_excl = fence_excl;
-       else if (fence_excl)
-               shared[shared_count++] = fence_excl;
-
-       if (!shared_count) {
-               kfree(shared);
-               shared = NULL;
+               dma_fence_get(fence);
+               if (dma_resv_iter_is_exclusive(&cursor) && fence_excl)
+                       *fence_excl = fence;
+               else
+                       (*shared)[(*shared_count)++] = fence;
        }
+       dma_resv_iter_end(&cursor);
 
-       *pshared_count = shared_count;
-       *pshared = shared;
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(dma_resv_get_fences);