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_ */