Branch data Line data Source code
1 : : /*
2 : : * SPDX-License-Identifier: MIT
3 : : *
4 : : * (C) Copyright 2016 Intel Corporation
5 : : */
6 : :
7 : : #include <linux/slab.h>
8 : : #include <linux/dma-fence.h>
9 : : #include <linux/irq_work.h>
10 : : #include <linux/dma-resv.h>
11 : :
12 : : #include "i915_sw_fence.h"
13 : : #include "i915_selftest.h"
14 : :
15 : : #if IS_ENABLED(CONFIG_DRM_I915_DEBUG)
16 : : #define I915_SW_FENCE_BUG_ON(expr) BUG_ON(expr)
17 : : #else
18 : : #define I915_SW_FENCE_BUG_ON(expr) BUILD_BUG_ON_INVALID(expr)
19 : : #endif
20 : :
21 : : #define I915_SW_FENCE_FLAG_ALLOC BIT(3) /* after WQ_FLAG_* for safety */
22 : :
23 : : static DEFINE_SPINLOCK(i915_sw_fence_lock);
24 : :
25 : : enum {
26 : : DEBUG_FENCE_IDLE = 0,
27 : : DEBUG_FENCE_NOTIFY,
28 : : };
29 : :
30 : 0 : static void *i915_sw_fence_debug_hint(void *addr)
31 : : {
32 : 0 : return (void *)(((struct i915_sw_fence *)addr)->flags & I915_SW_FENCE_MASK);
33 : : }
34 : :
35 : : #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS
36 : :
37 : : static struct debug_obj_descr i915_sw_fence_debug_descr = {
38 : : .name = "i915_sw_fence",
39 : : .debug_hint = i915_sw_fence_debug_hint,
40 : : };
41 : :
42 : : static inline void debug_fence_init(struct i915_sw_fence *fence)
43 : : {
44 : : debug_object_init(fence, &i915_sw_fence_debug_descr);
45 : : }
46 : :
47 : : static inline void debug_fence_init_onstack(struct i915_sw_fence *fence)
48 : : {
49 : : debug_object_init_on_stack(fence, &i915_sw_fence_debug_descr);
50 : : }
51 : :
52 : : static inline void debug_fence_activate(struct i915_sw_fence *fence)
53 : : {
54 : : debug_object_activate(fence, &i915_sw_fence_debug_descr);
55 : : }
56 : :
57 : : static inline void debug_fence_set_state(struct i915_sw_fence *fence,
58 : : int old, int new)
59 : : {
60 : : debug_object_active_state(fence, &i915_sw_fence_debug_descr, old, new);
61 : : }
62 : :
63 : : static inline void debug_fence_deactivate(struct i915_sw_fence *fence)
64 : : {
65 : : debug_object_deactivate(fence, &i915_sw_fence_debug_descr);
66 : : }
67 : :
68 : : static inline void debug_fence_destroy(struct i915_sw_fence *fence)
69 : : {
70 : : debug_object_destroy(fence, &i915_sw_fence_debug_descr);
71 : : }
72 : :
73 : : static inline void debug_fence_free(struct i915_sw_fence *fence)
74 : : {
75 : : debug_object_free(fence, &i915_sw_fence_debug_descr);
76 : : smp_wmb(); /* flush the change in state before reallocation */
77 : : }
78 : :
79 : : static inline void debug_fence_assert(struct i915_sw_fence *fence)
80 : : {
81 : : debug_object_assert_init(fence, &i915_sw_fence_debug_descr);
82 : : }
83 : :
84 : : #else
85 : :
86 : 0 : static inline void debug_fence_init(struct i915_sw_fence *fence)
87 : : {
88 : 0 : }
89 : :
90 : : static inline void debug_fence_init_onstack(struct i915_sw_fence *fence)
91 : : {
92 : : }
93 : :
94 : 0 : static inline void debug_fence_activate(struct i915_sw_fence *fence)
95 : : {
96 : 0 : }
97 : :
98 : 0 : static inline void debug_fence_set_state(struct i915_sw_fence *fence,
99 : : int old, int new)
100 : : {
101 : 0 : }
102 : :
103 : 0 : static inline void debug_fence_deactivate(struct i915_sw_fence *fence)
104 : : {
105 : 0 : }
106 : :
107 : 0 : static inline void debug_fence_destroy(struct i915_sw_fence *fence)
108 : : {
109 : 0 : }
110 : :
111 : : static inline void debug_fence_free(struct i915_sw_fence *fence)
112 : : {
113 : : }
114 : :
115 : 0 : static inline void debug_fence_assert(struct i915_sw_fence *fence)
116 : : {
117 : 0 : }
118 : :
119 : : #endif
120 : :
121 : 0 : static int __i915_sw_fence_notify(struct i915_sw_fence *fence,
122 : : enum i915_sw_fence_notify state)
123 : : {
124 : 0 : i915_sw_fence_notify_t fn;
125 : :
126 : 0 : fn = (i915_sw_fence_notify_t)(fence->flags & I915_SW_FENCE_MASK);
127 : 0 : return fn(fence, state);
128 : : }
129 : :
130 : : #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS
131 : : void i915_sw_fence_fini(struct i915_sw_fence *fence)
132 : : {
133 : : debug_fence_free(fence);
134 : : }
135 : : #endif
136 : :
137 : 0 : static void __i915_sw_fence_wake_up_all(struct i915_sw_fence *fence,
138 : : struct list_head *continuation)
139 : : {
140 : 0 : wait_queue_head_t *x = &fence->wait;
141 : 0 : wait_queue_entry_t *pos, *next;
142 : 0 : unsigned long flags;
143 : :
144 : 0 : debug_fence_deactivate(fence);
145 : 0 : atomic_set_release(&fence->pending, -1); /* 0 -> -1 [done] */
146 : :
147 : : /*
148 : : * To prevent unbounded recursion as we traverse the graph of
149 : : * i915_sw_fences, we move the entry list from this, the next ready
150 : : * fence, to the tail of the original fence's entry list
151 : : * (and so added to the list to be woken).
152 : : */
153 : :
154 : 0 : spin_lock_irqsave_nested(&x->lock, flags, 1 + !!continuation);
155 [ # # ]: 0 : if (continuation) {
156 [ # # ]: 0 : list_for_each_entry_safe(pos, next, &x->head, entry) {
157 [ # # ]: 0 : if (pos->func == autoremove_wake_function)
158 : 0 : pos->func(pos, TASK_NORMAL, 0, continuation);
159 : : else
160 : 0 : list_move_tail(&pos->entry, continuation);
161 : : }
162 : : } else {
163 : 0 : LIST_HEAD(extra);
164 : :
165 : 0 : do {
166 [ # # ]: 0 : list_for_each_entry_safe(pos, next, &x->head, entry) {
167 : 0 : pos->func(pos,
168 : : TASK_NORMAL, fence->error,
169 : : &extra);
170 : : }
171 : :
172 [ # # ]: 0 : if (list_empty(&extra))
173 : : break;
174 : :
175 [ # # ]: 0 : list_splice_tail_init(&extra, &x->head);
176 : : } while (1);
177 : : }
178 : 0 : spin_unlock_irqrestore(&x->lock, flags);
179 : :
180 : 0 : debug_fence_assert(fence);
181 : 0 : }
182 : :
183 : 0 : static void __i915_sw_fence_complete(struct i915_sw_fence *fence,
184 : : struct list_head *continuation)
185 : : {
186 : 0 : debug_fence_assert(fence);
187 : :
188 [ # # ]: 0 : if (!atomic_dec_and_test(&fence->pending))
189 : : return;
190 : :
191 : 0 : debug_fence_set_state(fence, DEBUG_FENCE_IDLE, DEBUG_FENCE_NOTIFY);
192 : :
193 [ # # ]: 0 : if (__i915_sw_fence_notify(fence, FENCE_COMPLETE) != NOTIFY_DONE)
194 : : return;
195 : :
196 : 0 : debug_fence_set_state(fence, DEBUG_FENCE_NOTIFY, DEBUG_FENCE_IDLE);
197 : :
198 : 0 : __i915_sw_fence_wake_up_all(fence, continuation);
199 : :
200 : 0 : debug_fence_destroy(fence);
201 : 0 : __i915_sw_fence_notify(fence, FENCE_FREE);
202 : : }
203 : :
204 : 0 : void i915_sw_fence_complete(struct i915_sw_fence *fence)
205 : : {
206 : 0 : debug_fence_assert(fence);
207 : :
208 [ # # # # ]: 0 : if (WARN_ON(i915_sw_fence_done(fence)))
209 : : return;
210 : :
211 : 0 : __i915_sw_fence_complete(fence, NULL);
212 : : }
213 : :
214 : 0 : void i915_sw_fence_await(struct i915_sw_fence *fence)
215 : : {
216 : 0 : debug_fence_assert(fence);
217 [ # # ]: 0 : WARN_ON(atomic_inc_return(&fence->pending) <= 1);
218 : 0 : }
219 : :
220 : 0 : void __i915_sw_fence_init(struct i915_sw_fence *fence,
221 : : i915_sw_fence_notify_t fn,
222 : : const char *name,
223 : : struct lock_class_key *key)
224 : : {
225 [ # # # # ]: 0 : BUG_ON(!fn || (unsigned long)fn & ~I915_SW_FENCE_MASK);
226 : :
227 : 0 : __init_waitqueue_head(&fence->wait, name, key);
228 : 0 : fence->flags = (unsigned long)fn;
229 : :
230 : 0 : i915_sw_fence_reinit(fence);
231 : 0 : }
232 : :
233 : 0 : void i915_sw_fence_reinit(struct i915_sw_fence *fence)
234 : : {
235 : 0 : debug_fence_init(fence);
236 : :
237 : 0 : atomic_set(&fence->pending, 1);
238 : 0 : fence->error = 0;
239 : :
240 : 0 : I915_SW_FENCE_BUG_ON(!fence->flags);
241 : 0 : I915_SW_FENCE_BUG_ON(!list_empty(&fence->wait.head));
242 : 0 : }
243 : :
244 : 0 : void i915_sw_fence_commit(struct i915_sw_fence *fence)
245 : : {
246 : 0 : debug_fence_activate(fence);
247 : 0 : i915_sw_fence_complete(fence);
248 : 0 : }
249 : :
250 : 0 : static int i915_sw_fence_wake(wait_queue_entry_t *wq, unsigned mode, int flags, void *key)
251 : : {
252 : 0 : i915_sw_fence_set_error_once(wq->private, flags);
253 : :
254 : 0 : list_del(&wq->entry);
255 : 0 : __i915_sw_fence_complete(wq->private, key);
256 : :
257 [ # # ]: 0 : if (wq->flags & I915_SW_FENCE_FLAG_ALLOC)
258 : 0 : kfree(wq);
259 : 0 : return 0;
260 : : }
261 : :
262 : : static bool __i915_sw_fence_check_if_after(struct i915_sw_fence *fence,
263 : : const struct i915_sw_fence * const signaler)
264 : : {
265 : : wait_queue_entry_t *wq;
266 : :
267 : : if (__test_and_set_bit(I915_SW_FENCE_CHECKED_BIT, &fence->flags))
268 : : return false;
269 : :
270 : : if (fence == signaler)
271 : : return true;
272 : :
273 : : list_for_each_entry(wq, &fence->wait.head, entry) {
274 : : if (wq->func != i915_sw_fence_wake)
275 : : continue;
276 : :
277 : : if (__i915_sw_fence_check_if_after(wq->private, signaler))
278 : : return true;
279 : : }
280 : :
281 : : return false;
282 : : }
283 : :
284 : : static void __i915_sw_fence_clear_checked_bit(struct i915_sw_fence *fence)
285 : : {
286 : : wait_queue_entry_t *wq;
287 : :
288 : : if (!__test_and_clear_bit(I915_SW_FENCE_CHECKED_BIT, &fence->flags))
289 : : return;
290 : :
291 : : list_for_each_entry(wq, &fence->wait.head, entry) {
292 : : if (wq->func != i915_sw_fence_wake)
293 : : continue;
294 : :
295 : : __i915_sw_fence_clear_checked_bit(wq->private);
296 : : }
297 : : }
298 : :
299 : 0 : static bool i915_sw_fence_check_if_after(struct i915_sw_fence *fence,
300 : : const struct i915_sw_fence * const signaler)
301 : : {
302 : 0 : unsigned long flags;
303 : 0 : bool err;
304 : :
305 : 0 : if (!IS_ENABLED(CONFIG_DRM_I915_SW_FENCE_CHECK_DAG))
306 : 0 : return false;
307 : :
308 : : spin_lock_irqsave(&i915_sw_fence_lock, flags);
309 : : err = __i915_sw_fence_check_if_after(fence, signaler);
310 : : __i915_sw_fence_clear_checked_bit(fence);
311 : : spin_unlock_irqrestore(&i915_sw_fence_lock, flags);
312 : :
313 : : return err;
314 : : }
315 : :
316 : 0 : static int __i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
317 : : struct i915_sw_fence *signaler,
318 : : wait_queue_entry_t *wq, gfp_t gfp)
319 : : {
320 : 0 : unsigned long flags;
321 : 0 : int pending;
322 : :
323 : 0 : debug_fence_assert(fence);
324 [ # # ]: 0 : might_sleep_if(gfpflags_allow_blocking(gfp));
325 : :
326 [ # # ]: 0 : if (i915_sw_fence_done(signaler)) {
327 : 0 : i915_sw_fence_set_error_once(fence, signaler->error);
328 : 0 : return 0;
329 : : }
330 : :
331 : 0 : debug_fence_assert(signaler);
332 : :
333 : : /* The dependency graph must be acyclic. */
334 : 0 : if (unlikely(i915_sw_fence_check_if_after(fence, signaler)))
335 : : return -EINVAL;
336 : :
337 : 0 : pending = 0;
338 [ # # ]: 0 : if (!wq) {
339 [ # # ]: 0 : wq = kmalloc(sizeof(*wq), gfp);
340 [ # # ]: 0 : if (!wq) {
341 [ # # ]: 0 : if (!gfpflags_allow_blocking(gfp))
342 : : return -ENOMEM;
343 : :
344 : 0 : i915_sw_fence_wait(signaler);
345 : 0 : i915_sw_fence_set_error_once(fence, signaler->error);
346 : 0 : return 0;
347 : : }
348 : :
349 : : pending |= I915_SW_FENCE_FLAG_ALLOC;
350 : : }
351 : :
352 : 0 : INIT_LIST_HEAD(&wq->entry);
353 : 0 : wq->flags = pending;
354 : 0 : wq->func = i915_sw_fence_wake;
355 : 0 : wq->private = fence;
356 : :
357 : 0 : i915_sw_fence_await(fence);
358 : :
359 : 0 : spin_lock_irqsave(&signaler->wait.lock, flags);
360 [ # # ]: 0 : if (likely(!i915_sw_fence_done(signaler))) {
361 : 0 : __add_wait_queue_entry_tail(&signaler->wait, wq);
362 : 0 : pending = 1;
363 : : } else {
364 : 0 : i915_sw_fence_wake(wq, 0, signaler->error, NULL);
365 : 0 : pending = 0;
366 : : }
367 : 0 : spin_unlock_irqrestore(&signaler->wait.lock, flags);
368 : :
369 : 0 : return pending;
370 : : }
371 : :
372 : 0 : int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
373 : : struct i915_sw_fence *signaler,
374 : : wait_queue_entry_t *wq)
375 : : {
376 : 0 : return __i915_sw_fence_await_sw_fence(fence, signaler, wq, 0);
377 : : }
378 : :
379 : 0 : int i915_sw_fence_await_sw_fence_gfp(struct i915_sw_fence *fence,
380 : : struct i915_sw_fence *signaler,
381 : : gfp_t gfp)
382 : : {
383 : 0 : return __i915_sw_fence_await_sw_fence(fence, signaler, NULL, gfp);
384 : : }
385 : :
386 : : struct i915_sw_dma_fence_cb_timer {
387 : : struct i915_sw_dma_fence_cb base;
388 : : struct dma_fence *dma;
389 : : struct timer_list timer;
390 : : struct irq_work work;
391 : : struct rcu_head rcu;
392 : : };
393 : :
394 : 0 : static void dma_i915_sw_fence_wake(struct dma_fence *dma,
395 : : struct dma_fence_cb *data)
396 : : {
397 : 0 : struct i915_sw_dma_fence_cb *cb = container_of(data, typeof(*cb), base);
398 : :
399 : 0 : i915_sw_fence_set_error_once(cb->fence, dma->error);
400 : 0 : i915_sw_fence_complete(cb->fence);
401 : 0 : kfree(cb);
402 : 0 : }
403 : :
404 : 0 : static void timer_i915_sw_fence_wake(struct timer_list *t)
405 : : {
406 : 0 : struct i915_sw_dma_fence_cb_timer *cb = from_timer(cb, t, timer);
407 : 0 : struct i915_sw_fence *fence;
408 : :
409 : 0 : fence = xchg(&cb->base.fence, NULL);
410 [ # # ]: 0 : if (!fence)
411 : : return;
412 : :
413 : 0 : pr_notice("Asynchronous wait on fence %s:%s:%llx timed out (hint:%pS)\n",
414 : : cb->dma->ops->get_driver_name(cb->dma),
415 : : cb->dma->ops->get_timeline_name(cb->dma),
416 : : cb->dma->seqno,
417 : : i915_sw_fence_debug_hint(fence));
418 : :
419 : 0 : i915_sw_fence_set_error_once(fence, -ETIMEDOUT);
420 : 0 : i915_sw_fence_complete(fence);
421 : : }
422 : :
423 : 0 : static void dma_i915_sw_fence_wake_timer(struct dma_fence *dma,
424 : : struct dma_fence_cb *data)
425 : : {
426 : 0 : struct i915_sw_dma_fence_cb_timer *cb =
427 : 0 : container_of(data, typeof(*cb), base.base);
428 : 0 : struct i915_sw_fence *fence;
429 : :
430 : 0 : fence = xchg(&cb->base.fence, NULL);
431 [ # # ]: 0 : if (fence) {
432 : 0 : i915_sw_fence_set_error_once(fence, dma->error);
433 : 0 : i915_sw_fence_complete(fence);
434 : : }
435 : :
436 : 0 : irq_work_queue(&cb->work);
437 : 0 : }
438 : :
439 : 0 : static void irq_i915_sw_fence_work(struct irq_work *wrk)
440 : : {
441 : 0 : struct i915_sw_dma_fence_cb_timer *cb =
442 : 0 : container_of(wrk, typeof(*cb), work);
443 : :
444 : 0 : del_timer_sync(&cb->timer);
445 : 0 : dma_fence_put(cb->dma);
446 : :
447 [ # # ]: 0 : kfree_rcu(cb, rcu);
448 : 0 : }
449 : :
450 : 0 : int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
451 : : struct dma_fence *dma,
452 : : unsigned long timeout,
453 : : gfp_t gfp)
454 : : {
455 : 0 : struct i915_sw_dma_fence_cb *cb;
456 : 0 : dma_fence_func_t func;
457 : 0 : int ret;
458 : :
459 : 0 : debug_fence_assert(fence);
460 [ # # ]: 0 : might_sleep_if(gfpflags_allow_blocking(gfp));
461 : :
462 [ # # ]: 0 : if (dma_fence_is_signaled(dma)) {
463 : 0 : i915_sw_fence_set_error_once(fence, dma->error);
464 : 0 : return 0;
465 : : }
466 : :
467 [ # # ]: 0 : cb = kmalloc(timeout ?
468 : : sizeof(struct i915_sw_dma_fence_cb_timer) :
469 : : sizeof(struct i915_sw_dma_fence_cb),
470 : : gfp);
471 [ # # ]: 0 : if (!cb) {
472 [ # # ]: 0 : if (!gfpflags_allow_blocking(gfp))
473 : : return -ENOMEM;
474 : :
475 : 0 : ret = dma_fence_wait(dma, false);
476 [ # # ]: 0 : if (ret)
477 : : return ret;
478 : :
479 : 0 : i915_sw_fence_set_error_once(fence, dma->error);
480 : 0 : return 0;
481 : : }
482 : :
483 : 0 : cb->fence = fence;
484 : 0 : i915_sw_fence_await(fence);
485 : :
486 : 0 : func = dma_i915_sw_fence_wake;
487 [ # # ]: 0 : if (timeout) {
488 : 0 : struct i915_sw_dma_fence_cb_timer *timer =
489 : 0 : container_of(cb, typeof(*timer), base);
490 : :
491 [ # # ]: 0 : timer->dma = dma_fence_get(dma);
492 : 0 : init_irq_work(&timer->work, irq_i915_sw_fence_work);
493 : :
494 : 0 : timer_setup(&timer->timer,
495 : : timer_i915_sw_fence_wake, TIMER_IRQSAFE);
496 : 0 : mod_timer(&timer->timer, round_jiffies_up(jiffies + timeout));
497 : :
498 : 0 : func = dma_i915_sw_fence_wake_timer;
499 : : }
500 : :
501 : 0 : ret = dma_fence_add_callback(dma, &cb->base, func);
502 [ # # ]: 0 : if (ret == 0) {
503 : : ret = 1;
504 : : } else {
505 : 0 : func(dma, &cb->base);
506 [ # # ]: 0 : if (ret == -ENOENT) /* fence already signaled */
507 : 0 : ret = 0;
508 : : }
509 : :
510 : : return ret;
511 : : }
512 : :
513 : 0 : static void __dma_i915_sw_fence_wake(struct dma_fence *dma,
514 : : struct dma_fence_cb *data)
515 : : {
516 : 0 : struct i915_sw_dma_fence_cb *cb = container_of(data, typeof(*cb), base);
517 : :
518 : 0 : i915_sw_fence_set_error_once(cb->fence, dma->error);
519 : 0 : i915_sw_fence_complete(cb->fence);
520 : 0 : }
521 : :
522 : 0 : int __i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
523 : : struct dma_fence *dma,
524 : : struct i915_sw_dma_fence_cb *cb)
525 : : {
526 : 0 : int ret;
527 : :
528 : 0 : debug_fence_assert(fence);
529 : :
530 [ # # ]: 0 : if (dma_fence_is_signaled(dma)) {
531 : 0 : i915_sw_fence_set_error_once(fence, dma->error);
532 : 0 : return 0;
533 : : }
534 : :
535 : 0 : cb->fence = fence;
536 : 0 : i915_sw_fence_await(fence);
537 : :
538 : 0 : ret = dma_fence_add_callback(dma, &cb->base, __dma_i915_sw_fence_wake);
539 [ # # ]: 0 : if (ret == 0) {
540 : : ret = 1;
541 : : } else {
542 : 0 : __dma_i915_sw_fence_wake(dma, &cb->base);
543 [ # # ]: 0 : if (ret == -ENOENT) /* fence already signaled */
544 : 0 : ret = 0;
545 : : }
546 : :
547 : : return ret;
548 : : }
549 : :
550 : 0 : int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
551 : : struct dma_resv *resv,
552 : : const struct dma_fence_ops *exclude,
553 : : bool write,
554 : : unsigned long timeout,
555 : : gfp_t gfp)
556 : : {
557 : 0 : struct dma_fence *excl;
558 : 0 : int ret = 0, pending;
559 : :
560 : 0 : debug_fence_assert(fence);
561 [ # # ]: 0 : might_sleep_if(gfpflags_allow_blocking(gfp));
562 : :
563 [ # # ]: 0 : if (write) {
564 : 0 : struct dma_fence **shared;
565 : 0 : unsigned int count, i;
566 : :
567 : 0 : ret = dma_resv_get_fences_rcu(resv, &excl, &count, &shared);
568 [ # # ]: 0 : if (ret)
569 : 0 : return ret;
570 : :
571 [ # # ]: 0 : for (i = 0; i < count; i++) {
572 [ # # ]: 0 : if (shared[i]->ops == exclude)
573 : 0 : continue;
574 : :
575 : 0 : pending = i915_sw_fence_await_dma_fence(fence,
576 : : shared[i],
577 : : timeout,
578 : : gfp);
579 [ # # ]: 0 : if (pending < 0) {
580 : : ret = pending;
581 : : break;
582 : : }
583 : :
584 : 0 : ret |= pending;
585 : : }
586 : :
587 [ # # ]: 0 : for (i = 0; i < count; i++)
588 : 0 : dma_fence_put(shared[i]);
589 : 0 : kfree(shared);
590 : : } else {
591 [ # # ]: 0 : excl = dma_resv_get_excl_rcu(resv);
592 : : }
593 : :
594 [ # # # # : 0 : if (ret >= 0 && excl && excl->ops != exclude) {
# # ]
595 : 0 : pending = i915_sw_fence_await_dma_fence(fence,
596 : : excl,
597 : : timeout,
598 : : gfp);
599 [ # # ]: 0 : if (pending < 0)
600 : : ret = pending;
601 : : else
602 : 0 : ret |= pending;
603 : : }
604 : :
605 : 0 : dma_fence_put(excl);
606 : :
607 : 0 : return ret;
608 : : }
609 : :
610 : : #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
611 : : #include "selftests/lib_sw_fence.c"
612 : : #include "selftests/i915_sw_fence.c"
613 : : #endif
|