Module Name:    src
Committed By:   riastradh
Date:           Wed Jul 24 02:19:53 UTC 2013

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

Log Message:
Move OS-independent cruft from drm_drv.c to a new drm_fops.c.


To generate a diff of this commit:
cvs rdiff -u -r1.1.1.1.2.23 -r1.1.1.1.2.24 \
    src/sys/external/bsd/drm2/dist/include/drm/drmP.h
cvs rdiff -u -r1.1.2.1 -r1.1.2.2 src/sys/external/bsd/drm2/drm/drm_drv.c
cvs rdiff -u -r0 -r1.1.2.1 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/include/drm/drmP.h
diff -u src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.1.1.1.2.23 src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.1.1.1.2.24
--- src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.1.1.1.2.23	Wed Jul 24 02:18:42 2013
+++ src/sys/external/bsd/drm2/dist/include/drm/drmP.h	Wed Jul 24 02:19:53 2013
@@ -1369,14 +1369,22 @@ extern int drm_lastclose(struct drm_devi
 
 				/* Device support (drm_fops.h) */
 extern struct mutex drm_global_mutex;
-#ifndef __NetBSD__
+#ifdef __NetBSD__
+extern int drm_open_file(struct drm_file *, void *, struct drm_minor *);
+extern int drm_close_file(struct drm_file *);
+#  if 0				/* XXX */
+extern struct drm_pending_event *drm_dequeue_event(struct drm_file *, size_t);
+#  endif
+#else
 extern int drm_open(struct inode *inode, struct file *filp);
 extern int drm_stub_open(struct inode *inode, struct file *filp);
 extern int drm_fasync(int fd, struct file *filp, int on);
 extern ssize_t drm_read(struct file *filp, char __user *buffer,
 			size_t count, loff_t *offset);
 extern int drm_release(struct inode *inode, struct file *filp);
+#endif
 
+#ifndef __NetBSD__
 				/* Mapping support (drm_vm.h) */
 extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
 extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma);

Index: src/sys/external/bsd/drm2/drm/drm_drv.c
diff -u src/sys/external/bsd/drm2/drm/drm_drv.c:1.1.2.1 src/sys/external/bsd/drm2/drm/drm_drv.c:1.1.2.2
--- src/sys/external/bsd/drm2/drm/drm_drv.c:1.1.2.1	Wed Jul 24 02:18:42 2013
+++ src/sys/external/bsd/drm2/drm/drm_drv.c	Wed Jul 24 02:19:53 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: drm_drv.c,v 1.1.2.1 2013/07/24 02:18:42 riastradh Exp $	*/
+/*	$NetBSD: drm_drv.c,v 1.1.2.2 2013/07/24 02:19:53 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.1 2013/07/24 02:18:42 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.1.2.2 2013/07/24 02:19:53 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -55,20 +55,6 @@ static int	drm_detach(device_t, int);
 
 static dev_type_open(drm_open);
 
-static int	drm_open_file(struct drm_file *, struct file *,
-		    struct drm_minor *);
-static int	drm_open_file_master(struct drm_file *);
-
-static int	drm_close_file(struct drm_file *);
-static void	drm_master_release(struct drm_file *);
-static void	drm_events_release(struct drm_file *);
-static void	drm_close_file_contexts(struct drm_file *);
-static void	drm_close_file_master(struct drm_file *);
-
-static void	drm_lastclose(struct drm_device *);
-static void	drm_lastclose_agp(struct drm_device *);
-static void	drm_lastclose_vma(struct drm_device *);
-
 static int	drm_close(struct file *);
 static int	drm_read(struct file *, off_t *, struct uio *, kauth_cred_t,
 		    int);
@@ -339,371 +325,6 @@ fail0:
 	return error;
 }
 
-/*
- * XXX BEGIN MISPLACED OS-INDEPENDENT CODE
- */
-
-static int
-drm_open_file(struct drm_file *file, struct file *fp, struct drm_minor *minor)
-{
-	struct drm_device *const dev = minor->dev;
-	int error;
-
-	atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
-	if ((dev->open_count++ == 0) && (dev->driver->firstopen != NULL)) {
-		error = (*dev->driver->firstopen)(dev);
-		if (error)
-			goto fail0;
-	}
-
-	file->authenticated = DRM_SUSER(); /* XXX */
-	file->magic = 0;
-	file->ioctl_count = 0;
-	INIT_LIST_HEAD(&file->lhead);
-	file->minor = minor;
-	file->lock_count = 0;
-	/* file->object_idr is initialized by drm_gem_open.  */
-	/* file->table_lock is initialized by drm_gem_open.  */
-	file->filp = fp;
-	file->driver_priv = NULL;
-	file->is_master = 0;
-	file->master = NULL;
-	INIT_LIST_HEAD(&file->fbs);
-	DRM_INIT_WAITQUEUE(&file->event_wait, "drmevent");
-	INIT_LIST_HEAD(&file->event_list);
-	file->event_space = 0x1000; /* XXX cargo-culted from Linux */
-
-	if (drm_core_check_feature(dev, DRIVER_GEM))
-		drm_gem_open(dev, file);
-
-	if (drm_core_check_feature(dev, DRIVER_PRIME))
-		drm_prime_init_file_private(&file->prime);
-
-	if (dev->driver->open) {
-		error = (*dev->driver->open)(dev, file);
-		if (error)
-			goto fail1;
-	}
-
-	error = drm_open_file_master(file);
-	if (error)
-		goto fail2;
-
-	/* Success!  */
-	return 0;
-
-fail2:
-	/*
-	 * XXX This error branch needs scrutiny, but Linux's error
-	 * branches are incomprehensible and look wronger.
-	 */
-	if (dev->driver->preclose)
-		(*dev->driver->preclose)(dev, file);
-	if (dev->driver->postclose)
-		(*dev->driver->postclose)(dev, file);
-
-fail1:
-	if (drm_core_check_feature(dev, DRIVER_PRIME))
-		drm_prime_destroy_file_private(&file->prime);
-
-	if (drm_core_check_feature(dev, DRIVER_GEM))
-		drm_gem_release(dev, file);
-
-	if (--dev->open_count == 0)
-		drm_lastclose(dev);
-
-fail0:
-	return error;
-}
-
-static int
-drm_open_file_master(struct drm_file *file)
-{
-	struct drm_device *const dev = file->minor->dev;
-	int error;
-
-	mutex_lock(&dev->struct_mutex);
-
-	if (file->minor->master != NULL) {
-		file->master = drm_master_get(file->minor->master);
-	} else {
-		file->minor->master = drm_master_create(file->minor);
-		if (file->minor->master == NULL) {
-			error = -ENOMEM;
-			goto fail0;
-		}
-
-		file->is_master = 1;
-		file->master = drm_master_get(file->minor->master);
-		file->authenticated = 1;
-
-		if (dev->driver->master_create) {
-			mutex_unlock(&dev->struct_mutex);
-			error = (*dev->driver->master_create)(dev,
-			    file->minor->master);
-			mutex_lock(&dev->struct_mutex);
-			if (error)
-				goto fail1;
-		}
-
-		if (dev->driver->master_set) {
-			error = (*dev->driver->master_set)(dev, file, true);
-			if (error)
-				goto fail1;
-		}
-	}
-	mutex_unlock(&dev->struct_mutex);
-
-	/* Success!  */
-	return 0;
-
-fail1:
-	/* drm_master_put handles calling master_destroy for us.  */
-	drm_master_put(&file->minor->master);
-	drm_master_put(&file->master);
-fail0:
-	mutex_unlock(&dev->struct_mutex);
-	return error;
-}
-
-static int
-drm_close_file(struct drm_file *file)
-{
-	struct drm_minor *const minor = file->minor;
-	struct drm_device *const dev = minor->dev;
-	int error;
-
-	mutex_lock(&drm_global_mutex);
-
-	/* XXX Not all users of ioctl_count take the global mutex!  */
-	if ((dev->open_count == 1) && (atomic_read(&dev->ioctl_count) != 0)) {
-		error = -EBUSY;
-		goto out;
-	}
-
-	if (dev->driver->preclose)
-		(*dev->driver->preclose)(dev, file);
-
-	if (file->magic)
-		(void)drm_remove_magic(file->master, file->magic);
-
-	if (file->minor->master)
-		drm_master_release(file);
-
-	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
-		drm_core_reclaim_buffers(dev, file);
-
-	drm_events_release(file);
-
-	if (drm_core_check_feature(dev, DRIVER_MODESET))
-		drm_fb_release(file);
-
-	if (drm_core_check_feature(dev, DRIVER_GEM))
-		drm_gem_release(dev, file);
-
-	drm_close_file_contexts(file);
-	drm_close_file_master(file);
-
-	mutex_lock(&dev->struct_mutex);
-	list_del(&file->lhead);
-	mutex_unlock(&dev->struct_mutex);
-
-	if (dev->driver->postclose)
-		(*dev->driver->postclose)(dev, file);
-
-	if (drm_core_check_feature(dev, DRIVER_PRIME))
-		drm_prime_destroy_file_private(&file->prime);
-
-	atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
-	if (--dev->open_count == 0) {
-		KASSERT(atomic_read(&dev->ioctl_count) == 0);
-		drm_lastclose(dev);
-	}
-
-	/* Success!  */
-	error = 0;
-
-out:
-	mutex_unlock(&drm_global_mutex);
-	return error;
-}
-
-static void
-drm_master_release(struct drm_file *file)
-{
-
-	if (drm_i_have_hw_lock(file->minor->dev, file))
-		drm_lock_free(&file->master->lock,
-		    _DRM_LOCKING_CONTEXT(file->master->lock.hw_lock->lock));
-}
-
-static void
-drm_events_release(struct drm_file *file)
-{
-	struct drm_device *const dev = file->minor->dev;
-	struct drm_pending_vblank_event *vblank, *vblank_next;
-	struct drm_pending_event *event, *event_next;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dev->event_lock, flags);
-
-	list_for_each_entry_safe(vblank, vblank_next, &dev->vblank_event_list,
-	    base.link) {
-		if (vblank->base.file_priv == file) {
-			list_del(&vblank->base.link);
-			drm_vblank_put(dev, vblank->pipe);
-			(*vblank->base.destroy)(&vblank->base);
-		}
-	}
-
-	list_for_each_entry_safe(event, event_next, &file->event_list, link) {
-		(*event->destroy)(event);
-	}
-
-	spin_unlock_irqrestore(&dev->event_lock, flags);
-}
-
-static void
-drm_close_file_contexts(struct drm_file *file)
-{
-	struct drm_device *const dev = file->minor->dev;
-
-	mutex_lock(&dev->ctxlist_mutex);
-	if (!list_empty(&dev->ctxlist)) {
-		struct drm_ctx_list *node, *next;
-
-		list_for_each_entry_safe(node, next, &dev->ctxlist, head) {
-			if (node->tag != file)
-				continue;
-
-			if (node->handle == DRM_KERNEL_CONTEXT)
-				continue;
-
-			if (dev->driver->context_dtor)
-				(*dev->driver->context_dtor)(dev,
-				    node->handle);
-			drm_ctxbitmap_free(dev, node->handle);
-			list_del(&node->head);
-			kfree(node);
-			dev->ctx_count--;
-		}
-	}
-	mutex_unlock(&dev->ctxlist_mutex);
-}
-
-static void
-drm_close_file_master(struct drm_file *file)
-{
-	struct drm_device *const dev = file->minor->dev;
-
-	mutex_lock(&dev->struct_mutex);
-
-	if (file->is_master) {
-		struct drm_master *const master = file->master;
-		struct drm_file *other_file;
-
-		list_for_each_entry(other_file, &dev->filelist, lhead) {
-			if (other_file == file)
-				continue;
-
-			if (other_file->master != file->master)
-				continue;
-
-			other_file->authenticated = 0;
-		}
-
-		if (master->lock.hw_lock) {
-			if (dev->sigdata.lock == master->lock.hw_lock)
-				dev->sigdata.lock = NULL;
-			master->lock.hw_lock = NULL;
-			master->lock.file_priv = NULL;
-			DRM_WAKEUP_ALL(&master->lock.lock_queue,
-			    &drm_global_mutex);
-		}
-
-		if (file->minor->master == file->master) {
-			if (dev->driver->master_drop)
-				(*dev->driver->master_drop)(dev, file, true);
-			drm_master_put(&file->minor->master);
-		}
-	}
-
-	/* XXX Need to close file->dev_mapping, whatever that means.  */
-
-	drm_master_put(&file->master);
-	file->is_master = 0;
-	mutex_unlock(&dev->struct_mutex);
-}
-
-static void
-drm_lastclose(struct drm_device *dev)
-{
-
-	if (dev->driver->lastclose)
-		(*dev->driver->lastclose)(dev);
-
-	if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET))
-		drm_irq_uninstall(dev);
-
-	mutex_lock(&dev->struct_mutex);
-
-	if (drm_core_has_AGP(dev) &&
-	    dev->agp &&
-	    !drm_core_check_feature(dev, DRIVER_MODESET))
-		drm_lastclose_agp(dev);
-
-	if (drm_core_check_feature(dev, DRIVER_SG) &&
-	    dev->sg &&
-	    !drm_core_check_feature(dev, DRIVER_MODESET)) {
-		drm_sg_cleanup(dev->sg);
-		dev->sg = NULL;
-	}
-
-	drm_lastclose_vma(dev);
-
-	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
-	    !drm_core_check_feature(dev, DRIVER_MODESET))
-		drm_dma_takedown(dev);
-
-	/* XXX clear the dev_mapping */
-	mutex_unlock(&dev->struct_mutex);
-}
-
-static void
-drm_lastclose_agp(struct drm_device *dev)
-{
-	struct drm_agp_mem *entry, *next;
-
-	list_for_each_entry_safe(entry, next, &dev->agp->memory, head) {
-		if (entry->bound)
-			drm_unbind_agp(entry->memory);
-		drm_free_agp(entry->memory, entry->pages);
-		kfree(entry);
-	}
-	INIT_LIST_HEAD(&dev->agp->memory); /* XXX seems kludgey */
-
-	if (dev->agp->acquired)
-		drm_agp_release(dev);
-
-	dev->agp->acquired = 0;
-	dev->agp->enabled = 0;
-}
-
-static void
-drm_lastclose_vma(struct drm_device *dev)
-{
-	struct drm_vma_entry *vma, *vma_next;
-
-	list_for_each_entry_safe(vma, vma_next, &dev->vmalist, head) {
-		list_del(&vma->head);
-		kfree(vma);
-	}
-}
-
-/*
- * XXX END MISPLACED OS-INDEPENDENT CODE
- */
-
 static int
 drm_close(struct file *fp)
 {
@@ -753,28 +374,6 @@ out:
 #endif
 }
 
-#if 0				/* XXX */
-static struct drm_pending_event *
-drm_dequeue_event(struct drm_file *file, size_t max_length)
-{
-
-	KASSERT(mutex_is_locked(&file->minor->dev->event_lock));
-
-	if (list_empty(&file->event_list))
-		return NULL;
-
-	struct drm_pending_event *const event =
-	    list_first_entry(&file->event_list, struct drm_pending_event,
-		link);
-	if (event->event->length > max_length)
-		return NULL;
-
-	file->event_space += event->event->length;
-	list_del(&event->link);
-	return event;
-}
-#endif
-
 static int
 drm_poll(struct file *fp __unused, int events __unused)
 {

Added files:

Index: src/sys/external/bsd/drm2/drm/drm_fops.c
diff -u /dev/null src/sys/external/bsd/drm2/drm/drm_fops.c:1.1.2.1
--- /dev/null	Wed Jul 24 02:19:53 2013
+++ src/sys/external/bsd/drm2/drm/drm_fops.c	Wed Jul 24 02:19:53 2013
@@ -0,0 +1,438 @@
+/*	$NetBSD: drm_fops.c,v 1.1.2.1 2013/07/24 02:19:53 riastradh Exp $	*/
+
+/*-
+ * Copyright (c) 2013 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Taylor R. Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: drm_fops.c,v 1.1.2.1 2013/07/24 02:19:53 riastradh Exp $");
+
+#include <drm/drmP.h>
+
+static int	drm_open_file_master(struct drm_file *);
+
+static void	drm_master_release(struct drm_file *);
+static void	drm_events_release(struct drm_file *);
+static void	drm_close_file_contexts(struct drm_file *);
+static void	drm_close_file_master(struct drm_file *);
+
+static void	drm_lastclose(struct drm_device *);
+static void	drm_lastclose_agp(struct drm_device *);
+static void	drm_lastclose_vma(struct drm_device *);
+
+int
+drm_open_file(struct drm_file *file, void *fp, struct drm_minor *minor)
+{
+	struct drm_device *const dev = minor->dev;
+	int error;
+
+	atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
+	if ((dev->open_count++ == 0) && (dev->driver->firstopen != NULL)) {
+		error = (*dev->driver->firstopen)(dev);
+		if (error)
+			goto fail0;
+	}
+
+	file->authenticated = DRM_SUSER(); /* XXX */
+	file->magic = 0;
+	file->ioctl_count = 0;
+	INIT_LIST_HEAD(&file->lhead);
+	file->minor = minor;
+	file->lock_count = 0;
+	/* file->object_idr is initialized by drm_gem_open.  */
+	/* file->table_lock is initialized by drm_gem_open.  */
+	file->filp = fp;
+	file->driver_priv = NULL;
+	file->is_master = 0;
+	file->master = NULL;
+	INIT_LIST_HEAD(&file->fbs);
+	DRM_INIT_WAITQUEUE(&file->event_wait, "drmevent");
+	INIT_LIST_HEAD(&file->event_list);
+	file->event_space = 0x1000; /* XXX cargo-culted from Linux */
+
+	if (drm_core_check_feature(dev, DRIVER_GEM))
+		drm_gem_open(dev, file);
+
+	if (drm_core_check_feature(dev, DRIVER_PRIME))
+		drm_prime_init_file_private(&file->prime);
+
+	if (dev->driver->open) {
+		error = (*dev->driver->open)(dev, file);
+		if (error)
+			goto fail1;
+	}
+
+	error = drm_open_file_master(file);
+	if (error)
+		goto fail2;
+
+	/* Success!  */
+	return 0;
+
+fail2:
+	/*
+	 * XXX This error branch needs scrutiny, but Linux's error
+	 * branches are incomprehensible and look wronger.
+	 */
+	if (dev->driver->preclose)
+		(*dev->driver->preclose)(dev, file);
+	if (dev->driver->postclose)
+		(*dev->driver->postclose)(dev, file);
+
+fail1:
+	if (drm_core_check_feature(dev, DRIVER_PRIME))
+		drm_prime_destroy_file_private(&file->prime);
+
+	if (drm_core_check_feature(dev, DRIVER_GEM))
+		drm_gem_release(dev, file);
+
+	if (--dev->open_count == 0)
+		drm_lastclose(dev);
+
+fail0:
+	return error;
+}
+
+static int
+drm_open_file_master(struct drm_file *file)
+{
+	struct drm_device *const dev = file->minor->dev;
+	int error;
+
+	mutex_lock(&dev->struct_mutex);
+
+	if (file->minor->master != NULL) {
+		file->master = drm_master_get(file->minor->master);
+	} else {
+		file->minor->master = drm_master_create(file->minor);
+		if (file->minor->master == NULL) {
+			error = -ENOMEM;
+			goto fail0;
+		}
+
+		file->is_master = 1;
+		file->master = drm_master_get(file->minor->master);
+		file->authenticated = 1;
+
+		if (dev->driver->master_create) {
+			mutex_unlock(&dev->struct_mutex);
+			error = (*dev->driver->master_create)(dev,
+			    file->minor->master);
+			mutex_lock(&dev->struct_mutex);
+			if (error)
+				goto fail1;
+		}
+
+		if (dev->driver->master_set) {
+			error = (*dev->driver->master_set)(dev, file, true);
+			if (error)
+				goto fail1;
+		}
+	}
+	mutex_unlock(&dev->struct_mutex);
+
+	/* Success!  */
+	return 0;
+
+fail1:
+	/* drm_master_put handles calling master_destroy for us.  */
+	drm_master_put(&file->minor->master);
+	drm_master_put(&file->master);
+fail0:
+	mutex_unlock(&dev->struct_mutex);
+	return error;
+}
+
+int
+drm_close_file(struct drm_file *file)
+{
+	struct drm_minor *const minor = file->minor;
+	struct drm_device *const dev = minor->dev;
+	int error;
+
+	mutex_lock(&drm_global_mutex);
+
+	/* XXX Not all users of ioctl_count take the global mutex!  */
+	if ((dev->open_count == 1) && (atomic_read(&dev->ioctl_count) != 0)) {
+		error = -EBUSY;
+		goto out;
+	}
+
+	if (dev->driver->preclose)
+		(*dev->driver->preclose)(dev, file);
+
+	if (file->magic)
+		(void)drm_remove_magic(file->master, file->magic);
+
+	if (file->minor->master)
+		drm_master_release(file);
+
+	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+		drm_core_reclaim_buffers(dev, file);
+
+	drm_events_release(file);
+
+	if (drm_core_check_feature(dev, DRIVER_MODESET))
+		drm_fb_release(file);
+
+	if (drm_core_check_feature(dev, DRIVER_GEM))
+		drm_gem_release(dev, file);
+
+	drm_close_file_contexts(file);
+	drm_close_file_master(file);
+
+	mutex_lock(&dev->struct_mutex);
+	list_del(&file->lhead);
+	mutex_unlock(&dev->struct_mutex);
+
+	if (dev->driver->postclose)
+		(*dev->driver->postclose)(dev, file);
+
+	if (drm_core_check_feature(dev, DRIVER_PRIME))
+		drm_prime_destroy_file_private(&file->prime);
+
+	atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
+	if (--dev->open_count == 0) {
+		KASSERT(atomic_read(&dev->ioctl_count) == 0);
+		drm_lastclose(dev);
+	}
+
+	/* Success!  */
+	error = 0;
+
+out:
+	mutex_unlock(&drm_global_mutex);
+	return error;
+}
+
+static void
+drm_master_release(struct drm_file *file)
+{
+
+	if (drm_i_have_hw_lock(file->minor->dev, file))
+		drm_lock_free(&file->master->lock,
+		    _DRM_LOCKING_CONTEXT(file->master->lock.hw_lock->lock));
+}
+
+static void
+drm_events_release(struct drm_file *file)
+{
+	struct drm_device *const dev = file->minor->dev;
+	struct drm_pending_vblank_event *vblank, *vblank_next;
+	struct drm_pending_event *event, *event_next;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+
+	list_for_each_entry_safe(vblank, vblank_next, &dev->vblank_event_list,
+	    base.link) {
+		if (vblank->base.file_priv == file) {
+			list_del(&vblank->base.link);
+			drm_vblank_put(dev, vblank->pipe);
+			(*vblank->base.destroy)(&vblank->base);
+		}
+	}
+
+	list_for_each_entry_safe(event, event_next, &file->event_list, link) {
+		(*event->destroy)(event);
+	}
+
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+static void
+drm_close_file_contexts(struct drm_file *file)
+{
+	struct drm_device *const dev = file->minor->dev;
+
+	mutex_lock(&dev->ctxlist_mutex);
+	if (!list_empty(&dev->ctxlist)) {
+		struct drm_ctx_list *node, *next;
+
+		list_for_each_entry_safe(node, next, &dev->ctxlist, head) {
+			if (node->tag != file)
+				continue;
+
+			if (node->handle == DRM_KERNEL_CONTEXT)
+				continue;
+
+			if (dev->driver->context_dtor)
+				(*dev->driver->context_dtor)(dev,
+				    node->handle);
+			drm_ctxbitmap_free(dev, node->handle);
+			list_del(&node->head);
+			kfree(node);
+			dev->ctx_count--;
+		}
+	}
+	mutex_unlock(&dev->ctxlist_mutex);
+}
+
+static void
+drm_close_file_master(struct drm_file *file)
+{
+	struct drm_device *const dev = file->minor->dev;
+
+	mutex_lock(&dev->struct_mutex);
+
+	if (file->is_master) {
+		struct drm_master *const master = file->master;
+		struct drm_file *other_file;
+
+		list_for_each_entry(other_file, &dev->filelist, lhead) {
+			if (other_file == file)
+				continue;
+
+			if (other_file->master != file->master)
+				continue;
+
+			other_file->authenticated = 0;
+		}
+
+		if (master->lock.hw_lock) {
+			/* XXX There is copypasta of this in drm_bufs.c.  */
+			if (dev->sigdata.lock == master->lock.hw_lock)
+				dev->sigdata.lock = NULL;
+			master->lock.hw_lock = NULL;
+			master->lock.file_priv = NULL;
+			DRM_WAKEUP_ALL(&master->lock.lock_queue,
+			    &drm_global_mutex);
+		}
+
+		if (file->minor->master == file->master) {
+			if (dev->driver->master_drop)
+				(*dev->driver->master_drop)(dev, file, true);
+			drm_master_put(&file->minor->master);
+		}
+	}
+
+	/* XXX Need to close file->dev_mapping, whatever that means.  */
+
+	drm_master_put(&file->master);
+	file->is_master = 0;
+	mutex_unlock(&dev->struct_mutex);
+}
+
+static void
+drm_lastclose(struct drm_device *dev)
+{
+
+	if (dev->driver->lastclose)
+		(*dev->driver->lastclose)(dev);
+
+	if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET))
+		drm_irq_uninstall(dev);
+
+	mutex_lock(&dev->struct_mutex);
+
+	if (drm_core_has_AGP(dev) &&
+	    dev->agp &&
+	    !drm_core_check_feature(dev, DRIVER_MODESET))
+		drm_lastclose_agp(dev);
+
+	if (drm_core_check_feature(dev, DRIVER_SG) &&
+	    dev->sg &&
+	    !drm_core_check_feature(dev, DRIVER_MODESET)) {
+		drm_sg_cleanup(dev->sg);
+		dev->sg = NULL;
+	}
+
+	drm_lastclose_vma(dev);
+
+	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
+	    !drm_core_check_feature(dev, DRIVER_MODESET))
+		drm_dma_takedown(dev);
+
+	/* XXX clear the dev_mapping */
+	mutex_unlock(&dev->struct_mutex);
+}
+
+static void
+drm_lastclose_agp(struct drm_device *dev)
+{
+	struct drm_agp_mem *entry, *next;
+
+	list_for_each_entry_safe(entry, next, &dev->agp->memory, head) {
+		if (entry->bound)
+			drm_unbind_agp(entry->memory);
+		drm_free_agp(entry->memory, entry->pages);
+		kfree(entry);
+	}
+	INIT_LIST_HEAD(&dev->agp->memory); /* XXX seems kludgey */
+
+	if (dev->agp->acquired)
+		drm_agp_release(dev);
+
+	dev->agp->acquired = 0;
+	dev->agp->enabled = 0;
+}
+
+static void
+drm_lastclose_vma(struct drm_device *dev)
+{
+	struct drm_vma_entry *vma, *vma_next;
+
+	list_for_each_entry_safe(vma, vma_next, &dev->vmalist, head) {
+		list_del(&vma->head);
+		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