hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/dma-buf/dma-fence-array.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * dma-fence-array: aggregate fences to be waited together
34 *
....@@ -6,20 +7,13 @@
67 * Authors:
78 * Gustavo Padovan <gustavo@padovan.org>
89 * Christian König <christian.koenig@amd.com>
9
- *
10
- * This program is free software; you can redistribute it and/or modify it
11
- * under the terms of the GNU General Public License version 2 as published by
12
- * the Free Software Foundation.
13
- *
14
- * This program is distributed in the hope that it will be useful, but WITHOUT
15
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17
- * more details.
1810 */
1911
2012 #include <linux/export.h>
2113 #include <linux/slab.h>
2214 #include <linux/dma-fence-array.h>
15
+
16
+#define PENDING_ERROR 1
2317
2418 static const char *dma_fence_array_get_driver_name(struct dma_fence *fence)
2519 {
....@@ -31,9 +25,28 @@
3125 return "unbound";
3226 }
3327
28
+static void dma_fence_array_set_pending_error(struct dma_fence_array *array,
29
+ int error)
30
+{
31
+ /*
32
+ * Propagate the first error reported by any of our fences, but only
33
+ * before we ourselves are signaled.
34
+ */
35
+ if (error)
36
+ cmpxchg(&array->base.error, PENDING_ERROR, error);
37
+}
38
+
39
+static void dma_fence_array_clear_pending_error(struct dma_fence_array *array)
40
+{
41
+ /* Clear the error flag if not actually set. */
42
+ cmpxchg(&array->base.error, PENDING_ERROR, 0);
43
+}
44
+
3445 static void irq_dma_fence_array_work(struct irq_work *wrk)
3546 {
3647 struct dma_fence_array *array = container_of(wrk, typeof(*array), work);
48
+
49
+ dma_fence_array_clear_pending_error(array);
3750
3851 dma_fence_signal(&array->base);
3952 dma_fence_put(&array->base);
....@@ -45,6 +58,8 @@
4558 struct dma_fence_array_cb *array_cb =
4659 container_of(cb, struct dma_fence_array_cb, cb);
4760 struct dma_fence_array *array = array_cb->array;
61
+
62
+ dma_fence_array_set_pending_error(array, f->error);
4863
4964 if (atomic_dec_and_test(&array->num_pending))
5065 irq_work_queue(&array->work);
....@@ -71,9 +86,14 @@
7186 dma_fence_get(&array->base);
7287 if (dma_fence_add_callback(array->fences[i], &cb[i].cb,
7388 dma_fence_array_cb_func)) {
89
+ int error = array->fences[i]->error;
90
+
91
+ dma_fence_array_set_pending_error(array, error);
7492 dma_fence_put(&array->base);
75
- if (atomic_dec_and_test(&array->num_pending))
93
+ if (atomic_dec_and_test(&array->num_pending)) {
94
+ dma_fence_array_clear_pending_error(array);
7695 return false;
96
+ }
7797 }
7898 }
7999
....@@ -84,7 +104,11 @@
84104 {
85105 struct dma_fence_array *array = to_dma_fence_array(fence);
86106
87
- return atomic_read(&array->num_pending) <= 0;
107
+ if (atomic_read(&array->num_pending) > 0)
108
+ return false;
109
+
110
+ dma_fence_array_clear_pending_error(array);
111
+ return true;
88112 }
89113
90114 static void dma_fence_array_release(struct dma_fence *fence)
....@@ -150,6 +174,8 @@
150174 atomic_set(&array->num_pending, signal_on_any ? 1 : num_fences);
151175 array->fences = fences;
152176
177
+ array->base.error = PENDING_ERROR;
178
+
153179 return array;
154180 }
155181 EXPORT_SYMBOL(dma_fence_array_create);