Source-Changes-HG archive

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

[src/riastradh-drm2]: src/sys/external/bsd/drm2 Hack up vblank events and mak...



details:   https://anonhg.NetBSD.org/src/rev/384d056baed3
branches:  riastradh-drm2
changeset: 788603:384d056baed3
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Wed Jan 15 21:25:29 2014 +0000

description:
Hack up vblank events and make them work.

diffstat:

 sys/external/bsd/drm2/dist/drm/drm_irq.c      |   31 ++++
 sys/external/bsd/drm2/dist/include/drm/drmP.h |    7 +-
 sys/external/bsd/drm2/drm/drm_drv.c           |  184 +++++++++++++++++++------
 sys/external/bsd/drm2/drm/drm_fops.c          |   38 +-----
 4 files changed, 171 insertions(+), 89 deletions(-)

diffs (truncated from 412 to 300 lines):

diff -r 02efba4bd201 -r 384d056baed3 sys/external/bsd/drm2/dist/drm/drm_irq.c
--- a/sys/external/bsd/drm2/dist/drm/drm_irq.c  Wed Jan 15 17:42:28 2014 +0000
+++ b/sys/external/bsd/drm2/dist/drm/drm_irq.c  Wed Jan 15 21:25:29 2014 +0000
@@ -50,6 +50,11 @@
 
 #include <asm/bug.h>
 
+#ifdef __NetBSD__              /* XXX hurk -- selnotify &c. */
+#include <sys/poll.h>
+#include <sys/select.h>
+#endif
+
 /* Access macro for slots in vblank timestamp ringbuffer. */
 #define vblanktimestamp(dev, crtc, count) ( \
        (dev)->_vblank_time[(crtc) * DRM_VBLANKTIME_RBSIZE + \
@@ -887,6 +892,8 @@
                      &e->base.file_priv->event_list);
 #ifdef __NetBSD__
        DRM_SPIN_WAKEUP_ONE(&e->base.file_priv->event_wait, &dev->event_lock);
+       selnotify(&e->base.file_priv->event_selq, (POLLIN | POLLRDNORM),
+           NOTE_SUBMIT);
 #else
        wake_up_interruptible(&e->base.file_priv->event_wait);
 #endif
@@ -1342,11 +1349,22 @@
                  vblwait->request.sequence, crtc);
        dev->last_vblank_wait[crtc] = vblwait->request.sequence;
 #ifdef __NetBSD__
+    {
+       unsigned long irqflags;
+       spin_lock_irqsave(&dev->vbl_lock, irqflags);
        DRM_SPIN_TIMED_WAIT_UNTIL(ret, &dev->vbl_queue[crtc], &dev->vbl_lock,
            (3 * DRM_HZ),
            (((drm_vblank_count(dev, crtc) -
                    vblwait->request.sequence) <= (1 << 23)) ||
                !dev->irq_enabled));
+       spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+       if (0 < ret)
+               /*
+                * ret is ticks remaining on success in this case, but
+                * caller just wants 0 for success.
+                */
+               ret = 0;
+    }
 #else
        DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
                    (((drm_vblank_count(dev, crtc) -
@@ -1416,10 +1434,17 @@
        s64 diff_ns;
        struct timeval tvblank;
        unsigned long irqflags;
+#ifdef __NetBSD__              /* XXX vblank locking */
+       unsigned long irqflags_vbl_lock;
+#endif
 
        if (!dev->num_crtcs)
                return false;
 
+#ifdef __NetBSD__              /* XXX vblank locking */
+       spin_lock_irqsave(&dev->vbl_lock, irqflags_vbl_lock);
+#endif
+
        /* Need timestamp lock to prevent concurrent execution with
         * vblank enable/disable, as this would cause inconsistent
         * or corrupted timestamps and vblank counts.
@@ -1429,6 +1454,9 @@
        /* Vblank irq handling disabled. Nothing to do. */
        if (!dev->vblank_enabled[crtc]) {
                spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
+#ifdef __NetBSD__              /* XXX vblank locking */
+               spin_unlock_irqrestore(&dev->vbl_lock, irqflags_vbl_lock);
+#endif
                return false;
        }
 
@@ -1476,6 +1504,9 @@
        drm_handle_vblank_events(dev, crtc);
 
        spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
+#ifdef __NetBSD__              /* XXX vblank locking */
+       spin_unlock_irqrestore(&dev->vbl_lock, irqflags_vbl_lock);
+#endif
        return true;
 }
 EXPORT_SYMBOL(drm_handle_vblank);
diff -r 02efba4bd201 -r 384d056baed3 sys/external/bsd/drm2/dist/include/drm/drmP.h
--- a/sys/external/bsd/drm2/dist/include/drm/drmP.h     Wed Jan 15 17:42:28 2014 +0000
+++ b/sys/external/bsd/drm2/dist/include/drm/drmP.h     Wed Jan 15 21:25:29 2014 +0000
@@ -490,18 +490,13 @@
 
 #ifdef __NetBSD__
        drm_waitqueue_t event_wait;
+       struct selinfo event_selq;
 #else
        wait_queue_head_t event_wait;
 #endif
        struct list_head event_list;
        int event_space;
 
-#ifdef __NetBSD__
-#if 0                          /* XXX drm event poll */
-       struct selinfo event_sel;
-#endif
-#endif
-
        struct drm_prime_file_private prime;
 };
 
diff -r 02efba4bd201 -r 384d056baed3 sys/external/bsd/drm2/drm/drm_drv.c
--- a/sys/external/bsd/drm2/drm/drm_drv.c       Wed Jan 15 17:42:28 2014 +0000
+++ b/sys/external/bsd/drm2/drm/drm_drv.c       Wed Jan 15 21:25:29 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: drm_drv.c,v 1.1.2.24 2014/01/15 13:52:30 riastradh Exp $       */
+/*     $NetBSD: drm_drv.c,v 1.1.2.25 2014/01/15 21:25:29 riastradh Exp $       */
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.1.2.24 2014/01/15 13:52:30 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.1.2.25 2014/01/15 21:25:29 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -82,7 +82,10 @@
 static int     drm_close(struct file *);
 static int     drm_read(struct file *, off_t *, struct uio *, kauth_cred_t,
                    int);
+static int     drm_dequeue_event(struct drm_file *, size_t,
+                   struct drm_pending_event **, int);
 static int     drm_poll(struct file *, int);
+static int     drm_kqfilter(struct file *, struct knote *);
 static int     drm_stat(struct file *, struct stat *);
 static int     drm_ioctl(struct file *, unsigned long, void *);
 static int     drm_version_string(char *, size_t *, const char *);
@@ -238,7 +241,7 @@
        .fo_poll = drm_poll,
        .fo_stat = drm_stat,
        .fo_close = drm_close,
-       .fo_kqfilter = fnullop_kqfilter,
+       .fo_kqfilter = drm_kqfilter,
        .fo_restart = fnullop_restart,
 };
 
@@ -500,33 +503,27 @@
        return error;
 }
 
-/*
- * XXX According to the old drm port, doing nothing but succeeding in
- * drm_read and drm_poll is a kludge for compatibility with old X
- * servers.  However, it's not clear to me from the drm2 code that this
- * is the right thing; in fact, it looks like a load of bollocks.
- */
-
 static int
-drm_read(struct file *fp __unused, off_t *off __unused,
-    struct uio *uio __unused, kauth_cred_t cred __unused, int flags __unused)
+drm_read(struct file *fp, off_t *off, struct uio *uio, kauth_cred_t cred,
+    int flags)
 {
-#if 1                          /* XXX drm event poll */
-       return 0;
-#else
-       /* XXX How do flags figure into this?  */
        struct drm_file *const file = fp->f_data;
        struct drm_pending_event *event;
-       int error;
+       bool first;
+       int error = 0;
 
-       if (off != 0)
-               return EINVAL;
+       for (first = true; ; first = false) {
+               int f = 0;
 
-       for (;;) {
-               error = drm_dequeue_event(file, uio->uio_resid, &event);
+               if (!first || ISSET(fp->f_flag, FNONBLOCK))
+                       f |= FNONBLOCK;
+
+               /* XXX errno Linux->NetBSD */
+               error = -drm_dequeue_event(file, uio->uio_resid, &event, f);
                if (error) {
-                       /* XXX errno Linux->NetBSD */
-                       return -error;
+                       if ((error == EWOULDBLOCK) && !first)
+                               error = 0;
+                       break;
                }
 
                if (event == NULL)
@@ -534,44 +531,137 @@
 
                error = uiomove(event->event, event->event->length, uio);
                if (error)      /* XXX Requeue the event?  */
-                       return error;
+                       break;
        }
 
        /* Success!  */
-       return 0;
-#endif
+       return error;
+}
+
+static int
+drm_dequeue_event(struct drm_file *file, size_t max_length,
+    struct drm_pending_event **eventp, int flags)
+{
+       struct drm_device *const dev = file->minor->dev;
+       struct drm_pending_event *event = NULL;
+       unsigned long irqflags;
+       int ret = 0;
+
+       spin_lock_irqsave(&dev->event_lock, irqflags);
+
+       if (ISSET(flags, FNONBLOCK)) {
+               if (list_empty(&file->event_list))
+                       ret = -EWOULDBLOCK;
+       } else {
+               DRM_SPIN_WAIT_UNTIL(ret, &file->event_wait, &dev->event_lock,
+                   !list_empty(&file->event_list));
+       }
+       if (ret)
+               goto out;
+
+       event = list_first_entry(&file->event_list, struct drm_pending_event,
+           link);
+       if (event->event->length > max_length) {
+               ret = 0;
+               goto out;
+       }
+
+       file->event_space += event->event->length;
+       list_del(&event->link);
+
+out:   spin_unlock_irqrestore(&dev->event_lock, irqflags);
+       *eventp = event;
+       return ret;
 }
 
 static int
 drm_poll(struct file *fp __unused, int events __unused)
 {
-#if 1                          /* XXX drm event poll */
-       /*
-        * XXX Let's worry about this later.  Notifiers need to be
-        * modified to call selnotify.
-        */
-       return 0;
-#else
        struct drm_file *const file = fp->f_data;
+       struct drm_device *const dev = file->minor->dev;
        int revents = 0;
-       unsigned long flags;
+       unsigned long irqflags;
 
-       spin_lock_irqsave(&file->minor->dev->event_lock, flags);
-
-       if (events & (POLLIN | POLLRDNORM)) {
-               if (!list_empty(&file->event_list))
-                       revents |= (events & (POLLIN | POLLRDNORM));
-       }
+       if (!ISSET(events, (POLLIN | POLLRDNORM)))
+               return 0;
 
-       if (revents == 0) {
-               if (events & (POLLIN | POLLRDNORM))
-                       selrecord(curlwp, &file->event_sel);
-       }
-
-       spin_unlock_irqrestore(&file->minor->dev->event_lock, flags);
+       spin_lock_irqsave(&dev->event_lock, irqflags);
+       if (list_empty(&file->event_list))
+               selrecord(curlwp, &file->event_selq);
+       else
+               revents |= (events & (POLLIN | POLLRDNORM));
+       spin_unlock_irqrestore(&dev->event_lock, irqflags);
 
        return revents;
-#endif
+}
+
+static void    filt_drm_detach(struct knote *);
+static int     filt_drm_event(struct knote *, long);
+
+static const struct filterops drm_filtops =
+       { 1, NULL, filt_drm_detach, filt_drm_event };
+
+static int
+drm_kqfilter(struct file *fp, struct knote *kn)
+{
+       struct drm_file *const file = fp->f_data;
+       struct drm_device *const dev = file->minor->dev;
+       unsigned long irqflags;
+
+       switch (kn->kn_filter) {



Home | Main Index | Thread Index | Old Index