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 Implement poll for reservations and dm...



details:   https://anonhg.NetBSD.org/src/rev/195233351dad
branches:  trunk
changeset: 366403:195233351dad
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Mon Aug 27 15:25:13 2018 +0000

description:
Implement poll for reservations and dma bufs.

diffstat:

 sys/external/bsd/drm2/include/linux/dma-buf.h     |    4 +-
 sys/external/bsd/drm2/include/linux/reservation.h |   25 +-
 sys/external/bsd/drm2/linux/linux_dma_buf.c       |   22 +-
 sys/external/bsd/drm2/linux/linux_reservation.c   |  269 +++++++++++++++++++++-
 4 files changed, 300 insertions(+), 20 deletions(-)

diffs (truncated from 439 to 300 lines):

diff -r ba513f55db3c -r 195233351dad sys/external/bsd/drm2/include/linux/dma-buf.h
--- a/sys/external/bsd/drm2/include/linux/dma-buf.h     Mon Aug 27 15:24:53 2018 +0000
+++ b/sys/external/bsd/drm2/include/linux/dma-buf.h     Mon Aug 27 15:25:13 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: dma-buf.h,v 1.3 2018/08/27 15:22:54 riastradh Exp $    */
+/*     $NetBSD: dma-buf.h,v 1.4 2018/08/27 15:25:13 riastradh Exp $    */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -88,7 +88,7 @@
 
        kmutex_t                        db_lock;
        volatile unsigned               db_refcnt;
-       struct selinfo                  db_selq;
+       struct reservation_poll         db_resv_poll;
        struct reservation_object       db_resv_int[];
 };
 
diff -r ba513f55db3c -r 195233351dad sys/external/bsd/drm2/include/linux/reservation.h
--- a/sys/external/bsd/drm2/include/linux/reservation.h Mon Aug 27 15:24:53 2018 +0000
+++ b/sys/external/bsd/drm2/include/linux/reservation.h Mon Aug 27 15:25:13 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: reservation.h,v 1.7 2018/08/27 14:01:14 riastradh Exp $        */
+/*     $NetBSD: reservation.h,v 1.8 2018/08/27 15:25:13 riastradh Exp $        */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -32,11 +32,10 @@
 #ifndef        _LINUX_RESERVATION_H_
 #define        _LINUX_RESERVATION_H_
 
+#include <linux/fence.h>
 #include <linux/rcupdate.h>
 #include <linux/ww_mutex.h>
 
-struct fence;
-
 struct reservation_object {
        struct ww_mutex         lock;
 
@@ -54,6 +53,14 @@
        struct fence __rcu      *shared[];
 };
 
+/* NetBSD addition */
+struct reservation_poll {
+       kmutex_t                rp_lock;
+       struct selinfo          rp_selq;
+       struct fence_cb         rp_fcb;
+       bool                    rp_claimed;
+};
+
 #define        reservation_object_add_excl_fence       linux_reservation_object_add_excl_fence
 #define        reservation_object_add_shared_fence     linux_reservation_object_add_shared_fence
 #define        reservation_object_fini                 linux_reservation_object_fini
@@ -62,9 +69,13 @@
 #define        reservation_object_get_list             linux_reservation_object_get_list
 #define        reservation_object_held                 linux_reservation_object_held
 #define        reservation_object_init                 linux_reservation_object_init
+#define        reservation_object_kqfilter             linux_reservation_object_kqfilter
+#define        reservation_object_poll                 linux_reservation_object_poll
 #define        reservation_object_reserve_shared       linux_reservation_object_reserve_shared
 #define        reservation_object_test_signaled_rcu    linux_reservation_object_test_signaled_rcu
 #define        reservation_object_wait_timeout_rcu     linux_reservation_object_wait_timeout_rcu
+#define        reservation_poll_fini                   linux_reservation_poll_fini
+#define        reservation_poll_init                   linux_reservation_poll_init
 #define        reservation_ww_class                    linux_reservation_ww_class
 
 extern struct ww_class reservation_ww_class;
@@ -90,4 +101,12 @@
 long   reservation_object_wait_timeout_rcu(struct reservation_object *,
            bool, bool, unsigned long);
 
+/* NetBSD additions */
+void   reservation_poll_init(struct reservation_poll *);
+void   reservation_poll_fini(struct reservation_poll *);
+int    reservation_object_poll(struct reservation_object *, int,
+           struct reservation_poll *);
+int    reservation_object_kqfilter(struct reservation_object *,
+           struct knote *, struct reservation_poll *);
+
 #endif /* _LINUX_RESERVATION_H_ */
diff -r ba513f55db3c -r 195233351dad sys/external/bsd/drm2/linux/linux_dma_buf.c
--- a/sys/external/bsd/drm2/linux/linux_dma_buf.c       Mon Aug 27 15:24:53 2018 +0000
+++ b/sys/external/bsd/drm2/linux/linux_dma_buf.c       Mon Aug 27 15:25:13 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: linux_dma_buf.c,v 1.3 2018/08/27 15:24:40 riastradh Exp $      */
+/*     $NetBSD: linux_dma_buf.c,v 1.4 2018/08/27 15:25:13 riastradh Exp $      */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_dma_buf.c,v 1.3 2018/08/27 15:24:40 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_dma_buf.c,v 1.4 2018/08/27 15:25:13 riastradh Exp $");
 
 #include <sys/types.h>
 #include <sys/atomic.h>
@@ -87,6 +87,7 @@
 
        mutex_init(&dmabuf->db_lock, MUTEX_DEFAULT, IPL_NONE);
        dmabuf->db_refcnt = 1;
+       reservation_poll_init(&dmabuf->db_resv_poll);
 
        if (dmabuf->resv == NULL) {
                dmabuf->resv = &dmabuf->db_resv_int[0];
@@ -167,6 +168,7 @@
        if (atomic_dec_uint_nv(&dmabuf->db_refcnt) != 0)
                return;
 
+       reservation_poll_fini(&dmabuf->db_resv_poll);
        mutex_destroy(&dmabuf->db_lock);
        if (dmabuf->resv == &dmabuf->db_resv_int[0]) {
                reservation_object_fini(dmabuf->resv);
@@ -239,27 +241,21 @@
 static int
 dmabuf_fop_poll(struct file *file, int events)
 {
-#ifdef notyet
        struct dma_buf_file *dbf = file->f_data;
        struct dma_buf *dmabuf = dbf->dbf_dmabuf;
+       struct reservation_poll *rpoll = &dmabuf->db_resv_poll;
 
-       return reservation_object_poll(dmabuf->resv, events);
-#else
-       return -ENOSYS;
-#endif
+       return reservation_object_poll(dmabuf->resv, events, rpoll);
 }
 
 static int
-dmabuf_fop_kqfilter(struct file *file, struct knote *knote)
+dmabuf_fop_kqfilter(struct file *file, struct knote *kn)
 {
-#ifdef notyet
        struct dma_buf_file *dbf = file->f_data;
        struct dma_buf *dmabuf = dbf->dbf_dmabuf;
+       struct reservation_poll *rpoll = &dmabuf->db_resv_poll;
 
-       return reservation_object_kqfilter(dmabuf->resv, knote);
-#else
-       return -ENOSYS;
-#endif
+       return reservation_object_kqfilter(dmabuf->resv, kn, rpoll);
 }
 
 static int
diff -r ba513f55db3c -r 195233351dad sys/external/bsd/drm2/linux/linux_reservation.c
--- a/sys/external/bsd/drm2/linux/linux_reservation.c   Mon Aug 27 15:24:53 2018 +0000
+++ b/sys/external/bsd/drm2/linux/linux_reservation.c   Mon Aug 27 15:25:13 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: linux_reservation.c,v 1.7 2018/08/27 14:14:13 riastradh Exp $  */
+/*     $NetBSD: linux_reservation.c,v 1.8 2018/08/27 15:25:14 riastradh Exp $  */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,10 +30,15 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_reservation.c,v 1.7 2018/08/27 14:14:13 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_reservation.c,v 1.8 2018/08/27 15:25:14 riastradh Exp $");
+
+#include <sys/param.h>
+#include <sys/poll.h>
+#include <sys/select.h>
 
 #include <linux/fence.h>
 #include <linux/reservation.h>
+#include <linux/ww_mutex.h>
 
 DEFINE_WW_CLASS(reservation_ww_class __cacheline_aligned);
 
@@ -792,3 +797,263 @@
                return timeout;
        goto top;
 }
+
+/*
+ * reservation_poll_init(rpoll, lock)
+ *
+ *     Initialize reservation poll state.
+ */
+void
+reservation_poll_init(struct reservation_poll *rpoll)
+{
+
+       mutex_init(&rpoll->rp_lock, MUTEX_DEFAULT, IPL_VM);
+       selinit(&rpoll->rp_selq);
+       rpoll->rp_claimed = 0;
+}
+
+/*
+ * reservation_poll_fini(rpoll)
+ *
+ *     Release any resource associated with reservation poll state.
+ */
+void
+reservation_poll_fini(struct reservation_poll *rpoll)
+{
+
+       KASSERT(rpoll->rp_claimed == 0);
+       seldestroy(&rpoll->rp_selq);
+       mutex_destroy(&rpoll->rp_lock);
+}
+
+/*
+ * reservation_poll_cb(fence, fcb)
+ *
+ *     Callback to notify a reservation poll that a fence has
+ *     completed.  Notify any waiters and allow the next poller to
+ *     claim the callback.
+ *
+ *     If one thread is waiting for the exclusive fence only, and we
+ *     spuriously notify them about a shared fence, tough.
+ */
+static void
+reservation_poll_cb(struct fence *fence, struct fence_cb *fcb)
+{
+       struct reservation_poll *rpoll = container_of(fcb,
+           struct reservation_poll, rp_fcb);
+
+       mutex_enter(&rpoll->rp_lock);
+       selnotify(&rpoll->rp_selq, 0, NOTE_SUBMIT);
+       rpoll->rp_claimed = 0;
+       mutex_exit(&rpoll->rp_lock);
+}
+
+/*
+ * reservation_object_poll(robj, events, rpoll)
+ *
+ *     POLLOUT         wait for all fences shared and exclusive
+ *     POLLIN          wait for the exclusive fence
+ */
+int
+reservation_object_poll(struct reservation_object *robj, int events,
+    struct reservation_poll *rpoll)
+{
+       struct reservation_object_read_ticket ticket;
+       struct reservation_object_list *list;
+       struct fence *fence;
+       uint32_t i, shared_count;
+       int revents;
+       bool recorded = false;  /* curlwp is on the selq */
+       bool claimed = false;   /* we claimed the callback */
+       bool callback = false;  /* we requested a callback */
+
+       /*
+        * Start with the maximal set of events that could be ready.
+        * We will eliminate the events that are definitely not ready
+        * as we go at the same time as we add callbacks to notify us
+        * that they may be ready.
+        */
+       revents = events & (POLLIN|POLLOUT);
+       if (revents == 0)
+               return 0;
+
+top:
+       /* Enter an RCU read section and get a read ticket.  */
+       rcu_read_lock();
+       reservation_object_read_begin(robj, &ticket);
+
+       /* If we want to wait for all fences, get the shared list.  */
+       if ((events & POLLOUT) && (list = robj->robj_list) != NULL) do {
+               /* Make sure the content of the list has been published.  */
+               membar_datadep_consumer();
+
+               /* Find out how long it is.  */
+               shared_count = list->shared_count;
+
+               /*
+                * Make sure we saw a consistent snapshot of the list
+                * pointer and length.
+                */
+               if (!reservation_object_read_valid(robj, &ticket))
+                       goto restart;
+
+               /*
+                * For each fence, if it is going away, restart.
+                * Otherwise, acquire a reference to it to test whether
+                * it is signalled.  Stop and request a callback if we
+                * find any that is not signalled.
+                */
+               for (i = 0; i < shared_count; i++) {
+                       fence = fence_get_rcu(list->shared[i]);
+                       if (fence == NULL)
+                               goto restart;
+                       if (!fence_is_signaled(fence)) {
+                               fence_put(fence);
+                               break;
+                       }
+                       fence_put(fence);
+               }
+
+               /* If all shared fences have been signalled, move on.  */
+               if (i == shared_count)
+                       break;
+



Home | Main Index | Thread Index | Old Index