Module Name: src Committed By: riastradh Date: Sun Dec 19 11:52:08 UTC 2021
Modified Files: src/sys/external/bsd/drm2/dist/drm/i915: i915_active.c i915_active_types.h src/sys/external/bsd/drm2/dist/drm/i915/gt: intel_engine_pm.c src/sys/external/bsd/drm2/i915drm: files.i915drmkms src/sys/external/bsd/drm2/include/linux: llist.h refcount.h spinlock.h Log Message: i915: intel_engine_pm.c and i915_active.c ...with a little less heinous abuse of C, and an attempt to disentangle the tentacular abstraction violations rampant in these components To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 \ src/sys/external/bsd/drm2/dist/drm/i915/i915_active.c cvs rdiff -u -r1.2 -r1.3 \ src/sys/external/bsd/drm2/dist/drm/i915/i915_active_types.h cvs rdiff -u -r1.2 -r1.3 \ src/sys/external/bsd/drm2/dist/drm/i915/gt/intel_engine_pm.c cvs rdiff -u -r1.82 -r1.83 src/sys/external/bsd/drm2/i915drm/files.i915drmkms cvs rdiff -u -r1.5 -r1.6 src/sys/external/bsd/drm2/include/linux/llist.h cvs rdiff -u -r1.2 -r1.3 src/sys/external/bsd/drm2/include/linux/refcount.h cvs rdiff -u -r1.13 -r1.14 src/sys/external/bsd/drm2/include/linux/spinlock.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/external/bsd/drm2/dist/drm/i915/i915_active.c diff -u src/sys/external/bsd/drm2/dist/drm/i915/i915_active.c:1.3 src/sys/external/bsd/drm2/dist/drm/i915/i915_active.c:1.4 --- src/sys/external/bsd/drm2/dist/drm/i915/i915_active.c:1.3 Sun Dec 19 01:44:57 2021 +++ src/sys/external/bsd/drm2/dist/drm/i915/i915_active.c Sun Dec 19 11:52:07 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: i915_active.c,v 1.3 2021/12/19 01:44:57 riastradh Exp $ */ +/* $NetBSD: i915_active.c,v 1.4 2021/12/19 11:52:07 riastradh Exp $ */ /* * SPDX-License-Identifier: MIT @@ -7,7 +7,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: i915_active.c,v 1.3 2021/12/19 01:44:57 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: i915_active.c,v 1.4 2021/12/19 11:52:07 riastradh Exp $"); #include <linux/debugobjects.h> @@ -19,6 +19,8 @@ __KERNEL_RCSID(0, "$NetBSD: i915_active. #include "i915_active.h" #include "i915_globals.h" +#include <linux/nbsd-namespace.h> + /* * Active refs memory management * @@ -36,6 +38,7 @@ struct active_node { struct i915_active *ref; struct rb_node node; u64 timeline; + struct intel_engine_cs *engine; }; static inline struct active_node * @@ -54,13 +57,13 @@ static inline bool is_barrier(const stru static inline struct llist_node *barrier_to_ll(struct active_node *node) { GEM_BUG_ON(!is_barrier(&node->base)); - return (struct llist_node *)&node->base.cb.node; + return &node->base.llist; } static inline struct intel_engine_cs * __barrier_to_engine(struct active_node *node) { - return (struct intel_engine_cs *)READ_ONCE(node->base.cb.node.prev); + return READ_ONCE(node->engine); } static inline struct intel_engine_cs * @@ -72,8 +75,7 @@ barrier_to_engine(struct active_node *no static inline struct active_node *barrier_from_ll(struct llist_node *x) { - return container_of((struct list_head *)x, - struct active_node, base.cb.node); + return container_of(x, struct active_node, base.llist); } #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) && IS_ENABLED(CONFIG_DEBUG_OBJECTS) @@ -129,6 +131,42 @@ static inline void debug_active_assert(s #endif +#ifdef __NetBSD__ + +static int +compare_nodes(void *cookie, const void *va, const void *vb) +{ + const struct active_node *a = va; + const struct active_node *b = vb; + + if (a->timeline < b->timeline) + return -1; + if (a->timeline > b->timeline) + return +1; + return 0; +} + +static int +compare_node_key(void *cookie, const void *vn, const void *vk) +{ + const struct active_node *a = vn; + const uint64_t *k = vk; + + if (a->timeline < *k) + return -1; + if (a->timeline > *k) + return +1; + return 0; +} + +static const rb_tree_ops_t active_rb_ops = { + .rbto_compare_nodes = compare_nodes, + .rbto_compare_key = compare_node_key, + .rbto_node_offset = offsetof(struct active_node, node), +}; + +#endif + static void __active_retire(struct i915_active *ref) { @@ -146,9 +184,15 @@ __active_retire(struct i915_active *ref) debug_active_deactivate(ref); root = ref->tree; +#ifdef __NetBSD__ + rb_tree_init(&ref->tree.rbr_tree, &active_rb_ops); +#else ref->tree = RB_ROOT; +#endif ref->cache = NULL; + DRM_SPIN_WAKEUP_ALL(&ref->tree_wq, &ref->tree_lock); + spin_unlock_irqrestore(&ref->tree_lock, flags); /* After the final retire, the entire struct may be freed */ @@ -156,7 +200,6 @@ __active_retire(struct i915_active *ref) ref->retire(ref); /* ... except if you wait on it, you must manage your own references! */ - wake_up_var(ref); rbtree_postorder_for_each_entry_safe(it, n, &root, node) { GEM_BUG_ON(i915_active_fence_isset(&it->base)); @@ -249,7 +292,7 @@ active_instance(struct i915_active *ref, #ifdef __NetBSD__ __USE(parent); __USE(p); - node = rb_tree_find_node(&vma->active.rbr_tree, &idx); + node = rb_tree_find_node(&ref->tree.rbr_tree, &idx); if (node) { KASSERT(node->timeline == idx); goto out; @@ -279,8 +322,8 @@ active_instance(struct i915_active *ref, node->timeline = idx; #ifdef __NetBSD__ - struct i915_vma_active *collision __diagused; - collision = rb_tree_insert_node(&vma->active.rbr_tree, node); + struct active_node *collision __diagused; + collision = rb_tree_insert_node(&ref->tree.rbr_tree, node); KASSERT(collision == node); #else rb_link_node(&node->node, parent, p); @@ -295,40 +338,6 @@ out: return &node->base; } -#ifdef __NetBSD__ -static int -compare_active(void *cookie, const void *va, const void *vb) -{ - const struct i915_active *a = va; - const struct i915_active *b = vb; - - if (a->timeline < b->timeline) - return -1; - if (a->timeline > b->timeline) - return +1; - return 0; -} - -static int -compare_active_key(void *cookie, const void *vn, const void *vk) -{ - const struct i915_active *a = vn; - const uint64_t *k = vk; - - if (a->timeline < *k) - return -1; - if (a->timeline > *k) - return +1; - return 0; -} - -static const rb_tree_ops_t active_rb_ops = { - .rbto_compare_nodes = compare_active, - .rbto_compare_key = compare_active_key, - .rbto_node_offset = offsetof(struct i915_active, node), -}; -#endif - void __i915_active_init(struct i915_active *ref, int (*active)(struct i915_active *ref), void (*retire)(struct i915_active *ref), @@ -346,8 +355,9 @@ void __i915_active_init(struct i915_acti ref->flags |= I915_ACTIVE_RETIRE_SLEEPS; spin_lock_init(&ref->tree_lock); + DRM_INIT_WAITQUEUE(&ref->tree_wq, "i915act"); #ifdef __NetBSD__ - rb_tree_init(&vma->active.rbr_tree, &active_rb_ops); + rb_tree_init(&ref->tree.rbr_tree, &active_rb_ops); #else ref->tree = RB_ROOT; #endif @@ -533,8 +543,12 @@ int i915_active_wait(struct i915_active if (err) return err; - if (wait_var_event_interruptible(ref, i915_active_is_idle(ref))) - return -EINTR; + spin_lock(&ref->tree_lock); + DRM_SPIN_WAIT_UNTIL(err, &ref->tree_wq, &ref->tree_lock, + i915_active_is_idle(ref)); + spin_unlock(&ref->tree_lock); + if (err) + return err; flush_work(&ref->work); return 0; @@ -599,6 +613,21 @@ static struct active_node *reuse_idle_ba goto match; } +#ifdef __NetBSD__ + { + struct active_node *node = + rb_tree_find_node_leq(&ref->tree.rbr_tree, &idx); + if (node) { + if (node->timeline == idx && is_idle_barrier(node, idx)) { + p = &node->node; + goto match; + } + prev = &node->node; + } else { + prev = NULL; + } + } +#else prev = NULL; p = ref->tree.rb_node; while (p) { @@ -614,6 +643,7 @@ static struct active_node *reuse_idle_ba else p = p->rb_left; } +#endif /* * No quick match, but we did find the leftmost rb_node for the @@ -621,7 +651,7 @@ static struct active_node *reuse_idle_ba * any idle-barriers on this timeline that we missed, or just use * the first pending barrier. */ - for (p = prev; p; p = rb_next(p)) { + for (p = prev; p; p = rb_next2(&ref->tree, p)) { struct active_node *node = rb_entry(p, struct active_node, node); struct intel_engine_cs *engine; @@ -712,7 +742,7 @@ int i915_active_acquire_preallocate_barr * for our tracking of the pending barrier. */ RCU_INIT_POINTER(node->base.fence, ERR_PTR(-EAGAIN)); - node->base.cb.node.prev = (void *)engine; + node->engine = engine; atomic_inc(&ref->count); } GEM_BUG_ON(rcu_access_pointer(node->base.fence) != ERR_PTR(-EAGAIN)); @@ -764,6 +794,13 @@ void i915_active_acquire_barrier(struct spin_lock_irqsave_nested(&ref->tree_lock, flags, SINGLE_DEPTH_NESTING); +#ifdef __NetBSD__ + __USE(p); + __USE(parent); + struct active_node *collision __diagused; + collision = rb_tree_insert_node(&ref->tree.rbr_tree, node); + KASSERT(collision == node); +#else parent = NULL; p = &ref->tree.rb_node; while (*p) { @@ -779,6 +816,7 @@ void i915_active_acquire_barrier(struct } rb_link_node(&node->node, parent, p); rb_insert_color(&node->node, &ref->tree); +#endif spin_unlock_irqrestore(&ref->tree_lock, flags); GEM_BUG_ON(!intel_engine_pm_is_awake(engine)); @@ -814,7 +852,18 @@ void i915_request_add_active_barriers(st llist_for_each_safe(node, next, node) { /* serialise with reuse_idle_barrier */ smp_store_mb(*ll_to_fence_slot(node), &rq->fence); +#ifdef __NetBSD__ + spin_unlock(&rq->lock); + struct i915_active_fence *fence = + container_of(node, struct i915_active_fence, llist); + /* XXX something bad went wrong in making this code */ + KASSERT(fence->cb.func == node_retire); + (void)dma_fence_add_callback(fence->fence, &fence->cb, + node_retire); + spin_lock(&rq->lock); +#else list_add_tail((struct list_head *)node, &rq->fence.cb_list); +#endif } spin_unlock_irqrestore(&rq->lock, flags); } @@ -867,14 +916,26 @@ __i915_active_fence_set(struct i915_acti prev = xchg(__active_fence_slot(active), fence); if (prev) { GEM_BUG_ON(prev == fence); +#ifdef __NetBSD__ + KASSERT(active->cb.func == node_retire); + (void)dma_fence_remove_callback(prev, &active->cb); +#else spin_lock_nested(prev->lock, SINGLE_DEPTH_NESTING); __list_del_entry(&active->cb.node); spin_unlock(prev->lock); /* serialise with prev->cb_list */ +#endif } GEM_BUG_ON(rcu_access_pointer(active->fence) != fence); +#ifndef __NetBSD__ list_add_tail(&active->cb.node, &fence->cb_list); +#endif spin_unlock_irqrestore(fence->lock, flags); +#ifdef __NetBSD__ + KASSERT(active->cb.func == node_retire); + dma_fence_add_callback(fence, &active->cb, node_retire); +#endif + return prev; } Index: src/sys/external/bsd/drm2/dist/drm/i915/i915_active_types.h diff -u src/sys/external/bsd/drm2/dist/drm/i915/i915_active_types.h:1.2 src/sys/external/bsd/drm2/dist/drm/i915/i915_active_types.h:1.3 --- src/sys/external/bsd/drm2/dist/drm/i915/i915_active_types.h:1.2 Sat Dec 18 23:45:28 2021 +++ src/sys/external/bsd/drm2/dist/drm/i915/i915_active_types.h Sun Dec 19 11:52:07 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: i915_active_types.h,v 1.2 2021/12/18 23:45:28 riastradh Exp $ */ +/* $NetBSD: i915_active_types.h,v 1.3 2021/12/19 11:52:07 riastradh Exp $ */ /* * SPDX-License-Identifier: MIT @@ -17,11 +17,14 @@ #include <linux/rcupdate.h> #include <linux/workqueue.h> +#include <drm/drm_wait_netbsd.h> /* XXX */ + #include "i915_utils.h" struct i915_active_fence { struct dma_fence __rcu *fence; struct dma_fence_cb cb; + struct llist_node llist; }; struct active_node; @@ -36,6 +39,7 @@ struct i915_active { struct mutex mutex; spinlock_t tree_lock; + drm_waitqueue_t tree_wq; struct active_node *cache; struct rb_root tree; Index: src/sys/external/bsd/drm2/dist/drm/i915/gt/intel_engine_pm.c diff -u src/sys/external/bsd/drm2/dist/drm/i915/gt/intel_engine_pm.c:1.2 src/sys/external/bsd/drm2/dist/drm/i915/gt/intel_engine_pm.c:1.3 --- src/sys/external/bsd/drm2/dist/drm/i915/gt/intel_engine_pm.c:1.2 Sat Dec 18 23:45:30 2021 +++ src/sys/external/bsd/drm2/dist/drm/i915/gt/intel_engine_pm.c Sun Dec 19 11:52:07 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: intel_engine_pm.c,v 1.2 2021/12/18 23:45:30 riastradh Exp $ */ +/* $NetBSD: intel_engine_pm.c,v 1.3 2021/12/19 11:52:07 riastradh Exp $ */ /* * SPDX-License-Identifier: MIT @@ -7,7 +7,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: intel_engine_pm.c,v 1.2 2021/12/18 23:45:30 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: intel_engine_pm.c,v 1.3 2021/12/19 11:52:07 riastradh Exp $"); #include "i915_drv.h" @@ -229,11 +229,10 @@ static void call_idle_barriers(struct in struct llist_node *node, *next; llist_for_each_safe(node, next, llist_del_all(&engine->barrier_tasks)) { - struct dma_fence_cb *cb = - container_of((struct list_head *)node, - typeof(*cb), node); + struct i915_active_fence *fence = + container_of(node, struct i915_active_fence, llist); - cb->func(ERR_PTR(-EAGAIN), cb); + fence->cb.func(ERR_PTR(-EAGAIN), &fence->cb); } } Index: src/sys/external/bsd/drm2/i915drm/files.i915drmkms diff -u src/sys/external/bsd/drm2/i915drm/files.i915drmkms:1.82 src/sys/external/bsd/drm2/i915drm/files.i915drmkms:1.83 --- src/sys/external/bsd/drm2/i915drm/files.i915drmkms:1.82 Sun Dec 19 11:51:59 2021 +++ src/sys/external/bsd/drm2/i915drm/files.i915drmkms Sun Dec 19 11:52:07 2021 @@ -1,4 +1,4 @@ -# $NetBSD: files.i915drmkms,v 1.82 2021/12/19 11:51:59 riastradh Exp $ +# $NetBSD: files.i915drmkms,v 1.83 2021/12/19 11:52:07 riastradh Exp $ version 20180827 @@ -169,7 +169,7 @@ file external/bsd/drm2/dist/drm/i915/gt/ file external/bsd/drm2/dist/drm/i915/gt/intel_context.c i915drmkms file external/bsd/drm2/dist/drm/i915/gt/intel_engine_cs.c i915drmkms file external/bsd/drm2/dist/drm/i915/gt/intel_engine_heartbeat.c i915drmkms -#file external/bsd/drm2/dist/drm/i915/gt/intel_engine_pm.c i915drmkms +file external/bsd/drm2/dist/drm/i915/gt/intel_engine_pm.c i915drmkms file external/bsd/drm2/dist/drm/i915/gt/intel_engine_pool.c i915drmkms file external/bsd/drm2/dist/drm/i915/gt/intel_engine_user.c i915drmkms file external/bsd/drm2/dist/drm/i915/gt/intel_ggtt.c i915drmkms @@ -202,7 +202,7 @@ file external/bsd/drm2/dist/drm/i915/gt/ file external/bsd/drm2/dist/drm/i915/gt/uc/intel_huc_fw.c i915drmkms file external/bsd/drm2/dist/drm/i915/gt/uc/intel_uc.c i915drmkms file external/bsd/drm2/dist/drm/i915/gt/uc/intel_uc_fw.c i915drmkms -#file external/bsd/drm2/dist/drm/i915/i915_active.c i915drmkms +file external/bsd/drm2/dist/drm/i915/i915_active.c i915drmkms file external/bsd/drm2/dist/drm/i915/i915_buddy.c i915drmkms file external/bsd/drm2/dist/drm/i915/i915_cmd_parser.c i915drmkms file external/bsd/drm2/dist/drm/i915/i915_drv.c i915drmkms Index: src/sys/external/bsd/drm2/include/linux/llist.h diff -u src/sys/external/bsd/drm2/include/linux/llist.h:1.5 src/sys/external/bsd/drm2/include/linux/llist.h:1.6 --- src/sys/external/bsd/drm2/include/linux/llist.h:1.5 Sun Dec 19 11:39:24 2021 +++ src/sys/external/bsd/drm2/include/linux/llist.h Sun Dec 19 11:52:08 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: llist.h,v 1.5 2021/12/19 11:39:24 riastradh Exp $ */ +/* $NetBSD: llist.h,v 1.6 2021/12/19 11:52:08 riastradh Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -76,6 +76,20 @@ llist_add(struct llist_node *node, struc return first == NULL; } +static inline bool +llist_add_batch(struct llist_node *first, struct llist_node *last, + struct llist_head *head) +{ + struct llist_node *next; + + do { + next = atomic_load_consume(&head->first); + last->next = next; + } while (atomic_cas_ptr(&head->first, next, first) != next); + + return next == NULL; +} + static inline struct llist_node * llist_del_all(struct llist_head *head) { Index: src/sys/external/bsd/drm2/include/linux/refcount.h diff -u src/sys/external/bsd/drm2/include/linux/refcount.h:1.2 src/sys/external/bsd/drm2/include/linux/refcount.h:1.3 --- src/sys/external/bsd/drm2/include/linux/refcount.h:1.2 Sun Dec 19 10:48:37 2021 +++ src/sys/external/bsd/drm2/include/linux/refcount.h Sun Dec 19 11:52:08 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: refcount.h,v 1.2 2021/12/19 10:48:37 riastradh Exp $ */ +/* $NetBSD: refcount.h,v 1.3 2021/12/19 11:52:08 riastradh Exp $ */ /*- * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -84,24 +84,8 @@ static inline bool __must_check refcount_dec_and_lock_irqsave(struct refcount *rc, struct spinlock *lock, unsigned long *flagsp) { - unsigned old, new; - do { - old = atomic_read(&rc->rc_count); - KASSERT(old); - if (old == 1) { - spin_lock_irqsave(lock, *flagsp); - if (atomic_dec_return(&rc->rc_count) == 0) - return true; - spin_unlock_irqrestore(lock, *flagsp); - return false; - } - new = old - 1; - } while (atomic_cmpxchg(&rc->rc_count, old, new) != old); - - KASSERT(old != 1); - KASSERT(new != 0); - return false; + return atomic_dec_and_lock_irqsave(&rc->rc_count, lock, *flagsp); } static inline bool __must_check Index: src/sys/external/bsd/drm2/include/linux/spinlock.h diff -u src/sys/external/bsd/drm2/include/linux/spinlock.h:1.13 src/sys/external/bsd/drm2/include/linux/spinlock.h:1.14 --- src/sys/external/bsd/drm2/include/linux/spinlock.h:1.13 Sun Dec 19 11:47:55 2021 +++ src/sys/external/bsd/drm2/include/linux/spinlock.h Sun Dec 19 11:52:08 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: spinlock.h,v 1.13 2021/12/19 11:47:55 riastradh Exp $ */ +/* $NetBSD: spinlock.h,v 1.14 2021/12/19 11:52:08 riastradh Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -37,6 +37,7 @@ #include <machine/limits.h> +#include <linux/atomic.h> #include <linux/irqflags.h> #include <linux/lockdep.h> #include <linux/preempt.h> @@ -201,4 +202,31 @@ local_bh_enable(void) { } +#define atomic_dec_and_lock_irqsave(A, L, F) \ + _atomic_dec_and_lock_irqsave(A, L, &(F)) + +static inline bool __must_check +_atomic_dec_and_lock_irqsave(atomic_t *atomic, spinlock_t *lock, + unsigned long *flagsp) +{ + unsigned old, new; + + do { + old = atomic_read(atomic); + KASSERT(old); + if (old == 1) { + spin_lock_irqsave(lock, *flagsp); + if (atomic_dec_return(atomic) == 0) + return true; + spin_unlock_irqrestore(lock, *flagsp); + return false; + } + new = old - 1; + } while (atomic_cmpxchg(atomic, old, new) != old); + + KASSERT(old != 1); + KASSERT(new != 0); + return false; +} + #endif /* _LINUX_SPINLOCK_H_ */