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