Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/external/bsd/drm2/linux drm: Draft dma-fence-array.



details:   https://anonhg.NetBSD.org/src/rev/043cf7d829ab
branches:  trunk
changeset: 1028883:043cf7d829ab
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sun Dec 19 12:23:50 2021 +0000

description:
drm: Draft dma-fence-array.

diffstat:

 sys/external/bsd/drm2/include/linux/dma-fence-array.h |   19 +-
 sys/external/bsd/drm2/linux/linux_dma_fence_array.c   |  149 +++++++++++++++++-
 2 files changed, 160 insertions(+), 8 deletions(-)

diffs (215 lines):

diff -r 93e9b3e6e6d5 -r 043cf7d829ab sys/external/bsd/drm2/include/linux/dma-fence-array.h
--- a/sys/external/bsd/drm2/include/linux/dma-fence-array.h     Sun Dec 19 12:23:42 2021 +0000
+++ b/sys/external/bsd/drm2/include/linux/dma-fence-array.h     Sun Dec 19 12:23:50 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: dma-fence-array.h,v 1.5 2021/12/19 12:01:40 riastradh Exp $    */
+/*     $NetBSD: dma-fence-array.h,v 1.6 2021/12/19 12:23:50 riastradh Exp $    */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -35,15 +35,26 @@
 #include <sys/stdbool.h>
 
 #include <linux/dma-fence.h>
+#include <linux/irq_work.h>
 
 #define        dma_fence_array_create          linux_dma_fence_array_create
 #define        dma_fence_is_array              linux_dma_fence_is_array
 #define        to_dma_fence_array              linux_to_dma_fence_array
 
+struct dma_fence_array_cb {
+       struct dma_fence_array  *dfac_array;
+       struct dma_fence_cb     dfac_cb;
+};
+
 struct dma_fence_array {
-       struct dma_fence        base;
-       struct dma_fence        **fences;
-       unsigned                num_fences;
+       struct dma_fence                base;
+       struct dma_fence                **fences;
+       unsigned                        num_fences;
+
+       spinlock_t                      dfa_lock;
+       int                             dfa_npending;
+       struct irq_work                 dfa_work;
+       struct dma_fence_array_cb       dfa_cb[];
 };
 
 struct dma_fence_array *
diff -r 93e9b3e6e6d5 -r 043cf7d829ab sys/external/bsd/drm2/linux/linux_dma_fence_array.c
--- a/sys/external/bsd/drm2/linux/linux_dma_fence_array.c       Sun Dec 19 12:23:42 2021 +0000
+++ b/sys/external/bsd/drm2/linux/linux_dma_fence_array.c       Sun Dec 19 12:23:50 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: linux_dma_fence_array.c,v 1.1 2021/12/19 11:50:09 riastradh Exp $      */
+/*     $NetBSD: linux_dma_fence_array.c,v 1.2 2021/12/19 12:23:50 riastradh Exp $      */
 
 /*-
  * Copyright (c) 2021 The NetBSD Foundation, Inc.
@@ -30,22 +30,163 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_dma_fence_array.c,v 1.1 2021/12/19 11:50:09 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_dma_fence_array.c,v 1.2 2021/12/19 12:23:50 riastradh Exp $");
 
 #include <sys/systm.h>
 
 #include <linux/dma-fence-array.h>
 
+static const char *
+dma_fence_array_driver_name(struct dma_fence *fence)
+{
+       return "dma-fence-array";
+}
+
+static const char *
+dma_fence_array_timeline_name(struct dma_fence *fence)
+{
+       return "dma-fence-array-timeline";
+}
+
+static void
+dma_fence_array_done1(struct dma_fence *fence, struct dma_fence_cb *cb)
+{
+       struct dma_fence_array_cb *C =
+           container_of(cb, struct dma_fence_array_cb, dfac_cb);
+       struct dma_fence_array *A = C->dfac_array;
+
+       KASSERT(spin_is_locked(&A->dfa_lock));
+
+       if (fence->error && A->base.error == 1) {
+               KASSERT(fence->error != 1);
+               A->base.error = fence->error;
+       }
+       if (--A->dfa_npending) {
+               dma_fence_put(&A->base);
+               return;
+       }
+
+       /* Last one out, hit the lights -- dma_fence_array_done.  */
+       irq_work_queue(&A->dfa_work);
+}
+
+static void
+dma_fence_array_done(struct irq_work *W)
+{
+       struct dma_fence_array *A = container_of(W, struct dma_fence_array,
+           dfa_work);
+
+       spin_lock(&A->dfa_lock);
+       if (A->base.error == 1)
+               A->base.error = 0;
+       dma_fence_signal_locked(&A->base);
+       spin_unlock(&A->dfa_lock);
+
+       dma_fence_put(&A->base);
+}
+
+static bool
+dma_fence_array_enable_signaling(struct dma_fence *fence)
+{
+       struct dma_fence_array *A = to_dma_fence_array(fence);
+       struct dma_fence_array_cb *C;
+       unsigned i;
+       int error;
+
+       KASSERT(spin_is_locked(&A->dfa_lock));
+
+       for (i = 0; i < A->num_fences; i++) {
+               C = &A->dfa_cb[i];
+               C->dfac_array = A;
+               dma_fence_get(&A->base);
+               if (dma_fence_add_callback(A->fences[i], &C->dfac_cb,
+                       dma_fence_array_done1)) {
+                       error = A->fences[i]->error;
+                       if (error) {
+                               KASSERT(error != 1);
+                               if (A->base.error == 1)
+                                       A->base.error = error;
+                       }
+                       dma_fence_put(&A->base);
+                       if (--A->dfa_npending == 0) {
+                               if (A->base.error == 1)
+                                       A->base.error = 0;
+                               return false;
+                       }
+               }
+       }
+
+       return true;
+}
+
+static bool
+dma_fence_array_signaled(struct dma_fence *fence)
+{
+       struct dma_fence_array *A = to_dma_fence_array(fence);
+
+       KASSERT(spin_is_locked(&A->dfa_lock));
+
+       return A->dfa_npending == 0;
+}
+
+static void
+dma_fence_array_release(struct dma_fence *fence)
+{
+       struct dma_fence_array *A = to_dma_fence_array(fence);
+       unsigned i;
+
+       for (i = 0; i < A->num_fences; i++)
+               dma_fence_put(A->fences[i]);
+
+       kfree(A->fences);
+       dma_fence_free(fence);
+}
+
+static const struct dma_fence_ops dma_fence_array_ops = {
+       .get_driver_name = dma_fence_array_driver_name,
+       .get_timeline_name = dma_fence_array_timeline_name,
+       .enable_signaling = dma_fence_array_enable_signaling,
+       .signaled = dma_fence_array_signaled,
+       .release = dma_fence_array_release,
+};
+
+struct dma_fence_array *
+dma_fence_array_create(int num_fences, struct dma_fence **fences,
+    unsigned context, unsigned seqno, bool signal_on_any)
+{
+       struct dma_fence_array *A;
+
+       /*
+        * Must be allocated with kmalloc or equivalent because
+        * dma-fence will free it with kfree.
+        */
+       A = kzalloc(struct_size(A, dfa_cb, num_fences), GFP_KERNEL);
+       if (A == NULL)
+               return NULL;
+
+       A->fences = fences;
+       A->num_fences = num_fences;
+       A->dfa_npending = signal_on_any ? 1 : num_fences;
+
+       spin_lock_init(&A->dfa_lock);
+       dma_fence_init(&A->base, &dma_fence_array_ops, &A->dfa_lock,
+           context, seqno);
+       init_irq_work(&A->dfa_work, dma_fence_array_done);
+
+       return A;
+}
+
 bool
 dma_fence_is_array(struct dma_fence *fence)
 {
 
-       return false;
+       return fence->ops == &dma_fence_array_ops;
 }
 
 struct dma_fence_array *
 to_dma_fence_array(struct dma_fence *fence)
 {
 
-       panic("NYI");
+       KASSERT(dma_fence_is_array(fence));
+       return container_of(fence, struct dma_fence_array, base);
 }



Home | Main Index | Thread Index | Old Index