Module Name:    src
Committed By:   riastradh
Date:           Wed Jan 15 21:25:29 UTC 2014

Modified Files:
        src/sys/external/bsd/drm2/dist/drm [riastradh-drm2]: drm_irq.c
        src/sys/external/bsd/drm2/dist/include/drm [riastradh-drm2]: drmP.h
        src/sys/external/bsd/drm2/drm [riastradh-drm2]: drm_drv.c drm_fops.c

Log Message:
Hack up vblank events and make them work.


To generate a diff of this commit:
cvs rdiff -u -r1.1.1.1.2.10 -r1.1.1.1.2.11 \
    src/sys/external/bsd/drm2/dist/drm/drm_irq.c
cvs rdiff -u -r1.1.1.1.2.54 -r1.1.1.1.2.55 \
    src/sys/external/bsd/drm2/dist/include/drm/drmP.h
cvs rdiff -u -r1.1.2.24 -r1.1.2.25 src/sys/external/bsd/drm2/drm/drm_drv.c
cvs rdiff -u -r1.1.2.7 -r1.1.2.8 src/sys/external/bsd/drm2/drm/drm_fops.c

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/drm_irq.c
diff -u src/sys/external/bsd/drm2/dist/drm/drm_irq.c:1.1.1.1.2.10 src/sys/external/bsd/drm2/dist/drm/drm_irq.c:1.1.1.1.2.11
--- src/sys/external/bsd/drm2/dist/drm/drm_irq.c:1.1.1.1.2.10	Sun Sep  8 16:11:29 2013
+++ src/sys/external/bsd/drm2/dist/drm/drm_irq.c	Wed Jan 15 21:25:29 2014
@@ -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 @@ static void send_vblank_event(struct drm
 		      &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 @@ int drm_wait_vblank(struct drm_device *d
 		  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 @@ bool drm_handle_vblank(struct drm_device
 	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 @@ bool drm_handle_vblank(struct drm_device
 	/* 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 @@ bool drm_handle_vblank(struct drm_device
 	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);

Index: src/sys/external/bsd/drm2/dist/include/drm/drmP.h
diff -u src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.1.1.1.2.54 src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.1.1.1.2.55
--- src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.1.1.1.2.54	Wed Jan 15 13:53:53 2014
+++ src/sys/external/bsd/drm2/dist/include/drm/drmP.h	Wed Jan 15 21:25:29 2014
@@ -490,18 +490,13 @@ struct drm_file {
 
 #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;
 };
 

Index: src/sys/external/bsd/drm2/drm/drm_drv.c
diff -u src/sys/external/bsd/drm2/drm/drm_drv.c:1.1.2.24 src/sys/external/bsd/drm2/drm/drm_drv.c:1.1.2.25
--- src/sys/external/bsd/drm2/drm/drm_drv.c:1.1.2.24	Wed Jan 15 13:52:30 2014
+++ src/sys/external/bsd/drm2/drm/drm_drv.c	Wed Jan 15 21:25:29 2014
@@ -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 dev_type_open(drm_open);
 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 @@ static const struct fileops drm_fileops 
 	.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 @@ drm_close(struct file *fp)
 	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;
+
+		if (!first || ISSET(fp->f_flag, FNONBLOCK))
+			f |= FNONBLOCK;
 
-	for (;;) {
-		error = drm_dequeue_event(file, uio->uio_resid, &event);
+		/* 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 @@ drm_read(struct file *fp __unused, off_t
 
 		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;
+
+	if (!ISSET(events, (POLLIN | POLLRDNORM)))
+		return 0;
 
-	spin_lock_irqsave(&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);
 
-	if (events & (POLLIN | POLLRDNORM)) {
-		if (!list_empty(&file->event_list))
-			revents |= (events & (POLLIN | POLLRDNORM));
-	}
+	return revents;
+}
 
-	if (revents == 0) {
-		if (events & (POLLIN | POLLRDNORM))
-			selrecord(curlwp, &file->event_sel);
+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) {
+	case EVFILT_READ:
+		kn->kn_fop = &drm_filtops;
+		kn->kn_hook = file;
+		spin_lock_irqsave(&dev->event_lock, irqflags);
+		SLIST_INSERT_HEAD(&file->event_selq.sel_klist, kn, kn_selnext);
+		spin_unlock_irqrestore(&dev->event_lock, irqflags);
+		return 0;
+
+	case EVFILT_WRITE:
+	default:
+		return EINVAL;
 	}
+}
 
-	spin_unlock_irqrestore(&file->minor->dev->event_lock, flags);
+static void
+filt_drm_detach(struct knote *kn)
+{
+	struct drm_file *const file = kn->kn_hook;
+	struct drm_device *const dev = file->minor->dev;
+	unsigned long irqflags;
 
-	return revents;
-#endif
+	spin_lock_irqsave(&dev->event_lock, irqflags);
+	SLIST_REMOVE(&file->event_selq.sel_klist, kn, knote, kn_selnext);
+	spin_unlock_irqrestore(&dev->event_lock, irqflags);
+}
+
+static int
+filt_drm_event(struct knote *kn, long hint)
+{
+	struct drm_file *const file = kn->kn_hook;
+	struct drm_device *const dev = file->minor->dev;
+	unsigned long irqflags;
+	int ret;
+
+	if (hint == NOTE_SUBMIT)
+		KASSERT(spin_is_locked(&dev->event_lock));
+	else
+		spin_lock_irqsave(&dev->event_lock, irqflags);
+	if (list_empty(&file->event_list)) {
+		ret = 0;
+	} else {
+		struct drm_pending_event *const event =
+		    list_first_entry(&file->event_list,
+			struct drm_pending_event, link);
+		kn->kn_data = event->event->length;
+		ret = 1;
+	}
+	if (hint == NOTE_SUBMIT)
+		KASSERT(spin_is_locked(&dev->event_lock));
+	else
+		spin_unlock_irqrestore(&dev->event_lock, irqflags);
+
+	return ret;
 }
 
 static int

Index: src/sys/external/bsd/drm2/drm/drm_fops.c
diff -u src/sys/external/bsd/drm2/drm/drm_fops.c:1.1.2.7 src/sys/external/bsd/drm2/drm/drm_fops.c:1.1.2.8
--- src/sys/external/bsd/drm2/drm/drm_fops.c:1.1.2.7	Wed Jan 15 13:53:53 2014
+++ src/sys/external/bsd/drm2/drm/drm_fops.c	Wed Jan 15 21:25:29 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: drm_fops.c,v 1.1.2.7 2014/01/15 13:53:53 riastradh Exp $	*/
+/*	$NetBSD: drm_fops.c,v 1.1.2.8 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_fops.c,v 1.1.2.7 2014/01/15 13:53:53 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: drm_fops.c,v 1.1.2.8 2014/01/15 21:25:29 riastradh Exp $");
 
 #include <drm/drmP.h>
 
@@ -418,37 +418,3 @@ drm_lastclose_vma(struct drm_device *dev
 		kfree(vma);
 	}
 }
-
-#if 0				/* XXX drm event poll */
-int
-drm_dequeue_event(struct drm_file *file, size_t max_length,
-    struct drm_pending_event **eventp)
-{
-	struct drm_device *const dev = file->minor->dev;
-	struct drm_pending_event *event = NULL;
-	unsigned long flags;
-	int error;
-
-	spin_lock_irqsave(&dev->event_lock, flags);
-
-	DRM_SPIN_WAIT_UNTIL(error, &file->event_wait, &dev->event_lock,
-	    !list_empty(&file->event_list));
-	if (error)
-		goto out;
-
-	event = list_first_entry(&file->event_list, struct drm_pending_event,
-	    link);
-	if (event->event->length > max_length) {
-		error = 0;
-		goto out;
-	}
-
-	file->event_space += event->event->length;
-	list_del(&event->link);
-
-out:
-	spin_unlock_irqrestore(&dev->event_lock, flags);
-	*eventp = event;
-	return error;
-}
-#endif

Reply via email to