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