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