drm: Handle drm masters and minors like Linux
authorFrançois Tigeot <ftigeot@wolfpond.org>
Sat, 10 Jan 2015 20:06:46 +0000 (21:06 +0100)
committerFrançois Tigeot <ftigeot@wolfpond.org>
Sun, 11 Jan 2015 20:58:43 +0000 (21:58 +0100)
* Make drm data structures more like their Linux versions

* Reduce differences with Linux 3.9.11 and use the same
  idr-based mechanisms when possible

* Create devices with the right minor numbers

* Use the same struct file.private_data mechanism Linux uses to pass
  drm_file information, removing the need for the FreeBSD-originated
  devfs cdevpriv code.

21 files changed:
sys/dev/drm/drm_auth.c
sys/dev/drm/drm_bufs.c
sys/dev/drm/drm_context.c
sys/dev/drm/drm_crtc.c
sys/dev/drm/drm_drv.c
sys/dev/drm/drm_fops.c
sys/dev/drm/drm_ioctl.c
sys/dev/drm/drm_lock.c
sys/dev/drm/drm_stub.c
sys/dev/drm/drm_sysctl.c
sys/dev/drm/i915/i915_dma.c
sys/dev/drm/i915/i915_drv.c
sys/dev/drm/i915/intel_display.c
sys/dev/drm/include/drm/drmP.h
sys/dev/drm/radeon/r300_cmdbuf.c
sys/dev/drm/radeon/r600_blit.c
sys/dev/drm/radeon/r600_cp.c
sys/dev/drm/radeon/radeon_cp.c
sys/dev/drm/radeon/radeon_drv.h
sys/dev/drm/radeon/radeon_state.c
sys/sys/file.h

index dd8c833..a1042f2 100644 (file)
@@ -1,4 +1,14 @@
-/*-
+/**
+ * \file drm_auth.c
+ * IOCTLs for authentication
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
+ *
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  * All Rights Reserved.
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- *
- * $FreeBSD: src/sys/dev/drm2/drm_auth.c,v 1.1 2012/05/22 11:07:44 kib Exp $
- */
-
-/** @file drm_auth.c
- * Implementation of the get/authmagic ioctls implementing the authentication
- * scheme between the master and clients.
  */
 
 #include <drm/drmP.h>
 
-static int drm_hash_magic(drm_magic_t magic)
-{
-       return magic & (DRM_HASH_SIZE-1);
-}
-
 /**
- * Returns the file private associated with the given magic number.
+ * Find the file with the given magic number.
+ *
+ * \param dev DRM device.
+ * \param magic magic number.
+ *
+ * Searches in drm_device::magiclist within all files with the same hash key
+ * the one with matching magic number, while holding the drm_device::struct_mutex
+ * lock.
  */
-static struct drm_file *drm_find_file(struct drm_device *dev, drm_magic_t magic)
+static struct drm_file *drm_find_file(struct drm_master *master, drm_magic_t magic)
 {
-       drm_magic_entry_t *pt;
-       int hash = drm_hash_magic(magic);
-
-       DRM_LOCK_ASSERT(dev);
-
-       for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
-               if (pt->magic == magic) {
-                       return pt->priv;
-               }
+       struct drm_file *retval = NULL;
+       struct drm_magic_entry *pt;
+       struct drm_hash_item *hash;
+       struct drm_device *dev = master->minor->dev;
+
+       mutex_lock(&dev->struct_mutex);
+       if (!drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) {
+               pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
+               retval = pt->priv;
        }
-
-       return NULL;
+       mutex_unlock(&dev->struct_mutex);
+       return retval;
 }
 
 /**
- * Inserts the given magic number into the hash table of used magic number
- * lists.
+ * Adds a magic number.
+ *
+ * \param dev DRM device.
+ * \param priv file private data.
+ * \param magic magic number.
+ *
+ * Creates a drm_magic_entry structure and appends to the linked list
+ * associated the magic number hash key in drm_device::magiclist, while holding
+ * the drm_device::struct_mutex lock.
  */
-static int drm_add_magic(struct drm_device *dev, struct drm_file *priv,
+static int drm_add_magic(struct drm_master *master, struct drm_file *priv,
                         drm_magic_t magic)
 {
-       int               hash;
-       drm_magic_entry_t *entry;
-
+       struct drm_magic_entry *entry;
+       struct drm_device *dev = master->minor->dev;
        DRM_DEBUG("%d\n", magic);
 
-       DRM_LOCK_ASSERT(dev);
-
-       hash = drm_hash_magic(magic);
-       entry = kmalloc(sizeof(*entry), M_DRM, M_ZERO | M_WAITOK | M_NULLOK);
+       entry = kmalloc(sizeof(*entry), M_DRM, M_WAITOK | M_ZERO);
        if (!entry)
-               return ENOMEM;
-       entry->magic = magic;
-       entry->priv  = priv;
-       entry->next  = NULL;
-
-       if (dev->magiclist[hash].tail) {
-               dev->magiclist[hash].tail->next = entry;
-               dev->magiclist[hash].tail       = entry;
-       } else {
-               dev->magiclist[hash].head       = entry;
-               dev->magiclist[hash].tail       = entry;
-       }
+               return -ENOMEM;
+       entry->priv = priv;
+       entry->hash_item.key = (unsigned long)magic;
+       mutex_lock(&dev->struct_mutex);
+       drm_ht_insert_item(&master->magiclist, &entry->hash_item);
+       list_add_tail(&entry->head, &master->magicfree);
+       mutex_unlock(&dev->struct_mutex);
 
        return 0;
 }
 
 /**
- * Removes the given magic number from the hash table of used magic number
- * lists.
+ * Remove a magic number.
+ *
+ * \param dev DRM device.
+ * \param magic magic number.
+ *
+ * Searches and unlinks the entry in drm_device::magiclist with the magic
+ * number hash key, while holding the drm_device::struct_mutex lock.
  */
-static int drm_remove_magic(struct drm_device *dev, drm_magic_t magic)
+int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
 {
-       drm_magic_entry_t *prev = NULL;
-       drm_magic_entry_t *pt;
-       int               hash;
-
-       DRM_LOCK_ASSERT(dev);
+       struct drm_magic_entry *pt;
+       struct drm_hash_item *hash;
+       struct drm_device *dev = master->minor->dev;
 
        DRM_DEBUG("%d\n", magic);
-       hash = drm_hash_magic(magic);
-
-       for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
-               if (pt->magic == magic) {
-                       if (dev->magiclist[hash].head == pt) {
-                               dev->magiclist[hash].head = pt->next;
-                       }
-                       if (dev->magiclist[hash].tail == pt) {
-                               dev->magiclist[hash].tail = prev;
-                       }
-                       if (prev) {
-                               prev->next = pt->next;
-                       }
-                       drm_free(pt, M_DRM);
-                       return 0;
-               }
+
+       mutex_lock(&dev->struct_mutex);
+       if (drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) {
+               mutex_unlock(&dev->struct_mutex);
+               return -EINVAL;
        }
+       pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
+       drm_ht_remove_item(&master->magiclist, hash);
+       list_del(&pt->head);
+       mutex_unlock(&dev->struct_mutex);
 
-       return EINVAL;
+       kfree(pt, M_DRM);
+
+       return 0;
 }
 
 /**
- * Called by the client, this returns a unique magic number to be authorized
- * by the master.
+ * Get a unique magic number (ioctl).
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a resulting drm_auth structure.
+ * \return zero on success, or a negative number on failure.
  *
- * The master may use its own knowledge of the client (such as the X
- * connection that the magic is passed over) to determine if the magic number
- * should be authenticated.
+ * If there is a magic number in drm_file::magic then use it, otherwise
+ * searches an unique non-zero magic number and add it associating it with \p
+ * file_priv.
+ * This ioctl needs protection by the drm_global_mutex, which protects
+ * struct drm_file::magic and struct drm_magic_entry::priv.
  */
 int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        static drm_magic_t sequence = 0;
+       static struct lock lock;
+       LOCK_SYSINIT(lock, &lock, "dgmag", LK_CANRECURSE);
        struct drm_auth *auth = data;
 
        /* Find unique magic */
        if (file_priv->magic) {
                auth->magic = file_priv->magic;
        } else {
-               DRM_LOCK(dev);
                do {
-                       int old = sequence;
-
-                       auth->magic = old+1;
-
-                       if (!atomic_cmpset_int(&sequence, old, auth->magic))
-                               continue;
-               } while (drm_find_file(dev, auth->magic));
+                       mutex_lock(&lock);
+                       if (!sequence)
+                               ++sequence;     /* reserve 0 */
+                       auth->magic = sequence++;
+                       mutex_unlock(&lock);
+               } while (drm_find_file(file_priv->master, auth->magic));
                file_priv->magic = auth->magic;
-               drm_add_magic(dev, file_priv, auth->magic);
-               DRM_UNLOCK(dev);
+               drm_add_magic(file_priv->master, file_priv, auth->magic);
        }
 
        DRM_DEBUG("%u\n", auth->magic);
@@ -164,25 +167,29 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
 }
 
 /**
- * Marks the client associated with the given magic number as authenticated.
+ * Authenticate with a magic.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a drm_auth structure.
+ * \return zero if authentication successed, or a negative number otherwise.
+ *
+ * Checks if \p file_priv is associated with the magic number passed in \arg.
+ * This ioctl needs protection by the drm_global_mutex, which protects
+ * struct drm_file::magic and struct drm_magic_entry::priv.
  */
 int drm_authmagic(struct drm_device *dev, void *data,
                  struct drm_file *file_priv)
 {
        struct drm_auth *auth = data;
-       struct drm_file *priv;
+       struct drm_file *file;
 
        DRM_DEBUG("%u\n", auth->magic);
-
-       DRM_LOCK(dev);
-       priv = drm_find_file(dev, auth->magic);
-       if (priv != NULL) {
-               priv->authenticated = 1;
-               drm_remove_magic(dev, auth->magic);
-               DRM_UNLOCK(dev);
+       if ((file = drm_find_file(file_priv->master, auth->magic))) {
+               file->authenticated = 1;
+               drm_remove_magic(file_priv->master, auth->magic);
                return 0;
-       } else {
-               DRM_UNLOCK(dev);
-               return EINVAL;
        }
+       return -EINVAL;
 }
index ef45766..ce9b2cf 100644 (file)
@@ -180,15 +180,12 @@ int drm_addmap(struct drm_device * dev, resource_size_t offset,
                map->offset = (unsigned long)map->handle;
                if (map->flags & _DRM_CONTAINS_LOCK) {
                        /* Prevent a 2nd X Server from creating a 2nd lock */
-                       DRM_LOCK(dev);
-                       if (dev->lock.hw_lock != NULL) {
-                               DRM_UNLOCK(dev);
+                       if (dev->primary->master->lock.hw_lock != NULL) {
                                drm_free(map->handle, M_DRM);
                                drm_free(map, M_DRM);
-                               return EBUSY;
+                               return -EBUSY;
                        }
-                       dev->lock.hw_lock = map->handle; /* Pointer to lock */
-                       DRM_UNLOCK(dev);
+                       dev->sigdata.lock = dev->primary->master->lock.hw_lock = map->handle;   /* Pointer to lock */
                }
                break;
        case _DRM_AGP:
@@ -282,11 +279,10 @@ int drm_addmap_ioctl(struct drm_device *dev, void *data,
        if (!DRM_SUSER(DRM_CURPROC) && request->type != _DRM_AGP)
                return EACCES;
 
-       DRM_LOCK(dev);
        err = drm_addmap(dev, request->offset, request->size, request->type,
            request->flags, &map);
-       DRM_UNLOCK(dev);
-       if (err != 0)
+
+       if (err)
                return err;
 
        request->offset = map->offset;
@@ -299,29 +295,38 @@ int drm_addmap_ioctl(struct drm_device *dev, void *data,
        return 0;
 }
 
-void drm_rmmap(struct drm_device *dev, struct drm_local_map *map)
+/**
+ * Remove a map private from list and deallocate resources if the mapping
+ * isn't in use.
+ *
+ * Searches the map on drm_device::maplist, removes it from the list, see if
+ * its being used, and free any associate resource (such as MTRR's) if it's not
+ * being on use.
+ *
+ * \sa drm_addmap
+ */
+int drm_rmmap_locked(struct drm_device *dev, struct drm_local_map *map)
 {
        struct drm_map_list *r_list = NULL, *list_t;
        drm_dma_handle_t dmah;
        int found = 0;
-
-       DRM_LOCK_ASSERT(dev);
-
-       if (map == NULL)
-               return;
+       struct drm_master *master;
 
        /* Find the list entry for the map and remove it */
        list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
                if (r_list->map == map) {
+                       master = r_list->master;
                        list_del(&r_list->head);
-                       drm_free(r_list, M_DRM);
+                       drm_ht_remove_key(&dev->map_hash,
+                                         r_list->user_token >> PAGE_SHIFT);
+                       kfree(r_list, M_DRM);
                        found = 1;
                        break;
                }
        }
 
        if (!found)
-               return;
+               return -EINVAL;
 
        switch (map->type) {
        case _DRM_REGISTERS:
@@ -329,15 +334,20 @@ void drm_rmmap(struct drm_device *dev, struct drm_local_map *map)
                /* FALLTHROUGH */
        case _DRM_FRAME_BUFFER:
                if (map->mtrr) {
-                       int __unused retcode;
-                       
-                       retcode = drm_mtrr_del(0, map->offset, map->size,
-                           DRM_MTRR_WC);
-                       DRM_DEBUG("mtrr_del = %d\n", retcode);
+                       int retcode;
+                       retcode = drm_mtrr_del(0, map->offset, map->size, DRM_MTRR_WC);
+                       DRM_DEBUG("mtrr_del=%d\n", retcode);
                }
                break;
        case _DRM_SHM:
                drm_free(map->handle, M_DRM);
+               if (master) {
+                       if (dev->sigdata.lock == master->lock.hw_lock)
+                               dev->sigdata.lock = NULL;
+                       master->lock.hw_lock = NULL;   /* SHM removed */
+                       master->lock.file_priv = NULL;
+                       wake_up_interruptible_all(&master->lock.lock_queue);
+               }
                break;
        case _DRM_AGP:
        case _DRM_SCATTER_GATHER:
@@ -347,13 +357,27 @@ void drm_rmmap(struct drm_device *dev, struct drm_local_map *map)
                dmah.busaddr = map->offset;
                drm_pci_free(dev, &dmah);
                break;
-       default:
-               DRM_ERROR("Bad map type %d\n", map->type);
+       case _DRM_GEM:
+               DRM_ERROR("tried to rmmap GEM object\n");
                break;
        }
-
        drm_free(map, M_DRM);
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_rmmap_locked);
+
+int drm_rmmap(struct drm_device *dev, struct drm_local_map *map)
+{
+       int ret;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = drm_rmmap_locked(dev, map);
+       mutex_unlock(&dev->struct_mutex);
+
+       return ret;
 }
+EXPORT_SYMBOL(drm_rmmap);
 
 /* The rmmap ioctl appears to be unnecessary.  All mappings are torn down on
  * the last close of the device, and this is necessary for cleanup when things
index a590de2..3ed10b1 100644 (file)
@@ -1,4 +1,14 @@
-/*-
+/**
+ * \file drm_context.c
+ * IOCTLs for generic contexts
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
+ *
  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  * All Rights Reserved.
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- *
- * $FreeBSD: src/sys/dev/drm2/drm_context.c,v 1.1 2012/05/22 11:07:44 kib Exp $
  */
 
-/** @file drm_context.c
- * Implementation of the context management ioctls.
+/*
+ * ChangeLog:
+ *  2001-11-16 Torsten Duwe <duwe@caldera.de>
+ *             added context constructor/destructor hooks,
+ *             needed by SiS driver's memory management.
  */
 
 #include <drm/drmP.h>
 
-/* ================================================================
- * Context bitmap support
- */
+/******************************************************************/
+/** \name Context bitmap support */
+/*@{*/
 
-void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle)
+/**
+ * Free a handle from the context bitmap.
+ *
+ * \param dev DRM device.
+ * \param ctx_handle context handle.
+ *
+ * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
+ * in drm_device::ctx_idr, while holding the drm_device::struct_mutex
+ * lock.
+ */
+void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
 {
-       if (ctx_handle < 0 || ctx_handle >= DRM_MAX_CTXBITMAP || 
-           dev->ctx_bitmap == NULL) {
-               DRM_ERROR("Attempt to free invalid context handle: %d\n",
-                  ctx_handle);
-               return;
-       }
-
-       DRM_LOCK(dev);
-       clear_bit(ctx_handle, dev->ctx_bitmap);
-       dev->context_sareas[ctx_handle] = NULL;
-       DRM_UNLOCK(dev);
-       return;
+       mutex_lock(&dev->struct_mutex);
+       idr_remove(&dev->ctx_idr, ctx_handle);
+       mutex_unlock(&dev->struct_mutex);
 }
 
-int drm_ctxbitmap_next(struct drm_device *dev)
+/**
+ * Context bitmap allocation.
+ *
+ * \param dev DRM device.
+ * \return (non-negative) context handle on success or a negative number on failure.
+ *
+ * Allocate a new idr from drm_device::ctx_idr while holding the
+ * drm_device::struct_mutex lock.
+ */
+static int drm_ctxbitmap_next(struct drm_device * dev)
 {
-       int bit;
+       int new_id;
+       int ret;
 
-       if (dev->ctx_bitmap == NULL)
-               return -1;
-
-       DRM_LOCK(dev);
-       bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP);
-       if (bit >= DRM_MAX_CTXBITMAP) {
-               DRM_UNLOCK(dev);
-               return -1;
+again:
+       if (idr_pre_get(&dev->ctx_idr, GFP_KERNEL) == 0) {
+               DRM_ERROR("Out of memory expanding drawable idr\n");
+               return -ENOMEM;
        }
-
-       set_bit(bit, dev->ctx_bitmap);
-       DRM_DEBUG("bit : %d\n", bit);
-       if ((bit+1) > dev->max_context) {
-               drm_local_map_t **ctx_sareas;
-               int max_ctx = (bit+1);
-
-               ctx_sareas = krealloc(dev->context_sareas,
-                   max_ctx * sizeof(*dev->context_sareas),
-                   M_DRM, M_WAITOK | M_NULLOK);
-               if (ctx_sareas == NULL) {
-                       clear_bit(bit, dev->ctx_bitmap);
-                       DRM_DEBUG("failed to allocate bit : %d\n", bit);
-                       DRM_UNLOCK(dev);
-                       return -1;
-               }
-               dev->max_context = max_ctx;
-               dev->context_sareas = ctx_sareas;
-               dev->context_sareas[bit] = NULL;
-       }
-       DRM_UNLOCK(dev);
-       return bit;
+       mutex_lock(&dev->struct_mutex);
+       ret = idr_get_new_above(&dev->ctx_idr, NULL,
+                               DRM_RESERVED_CONTEXTS, &new_id);
+       mutex_unlock(&dev->struct_mutex);
+       if (ret == -EAGAIN)
+               goto again;
+       else if (ret)
+               return ret;
+
+       return new_id;
 }
 
-int drm_ctxbitmap_init(struct drm_device *dev)
+/**
+ * Context bitmap initialization.
+ *
+ * \param dev DRM device.
+ *
+ * Initialise the drm_device::ctx_idr
+ */
+int drm_ctxbitmap_init(struct drm_device * dev)
 {
-       int i;
-       int temp;
-
-       DRM_LOCK(dev);
-       dev->ctx_bitmap = kmalloc(PAGE_SIZE, M_DRM,
-                                 M_WAITOK | M_NULLOK | M_ZERO);
-       if (dev->ctx_bitmap == NULL) {
-               DRM_UNLOCK(dev);
-               return ENOMEM;
-       }
-       dev->context_sareas = NULL;
-       dev->max_context = -1;
-       DRM_UNLOCK(dev);
-
-       for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
-               temp = drm_ctxbitmap_next(dev);
-               DRM_DEBUG("drm_ctxbitmap_init : %d\n", temp);
-       }
-
+       idr_init(&dev->ctx_idr);
        return 0;
 }
 
-void drm_ctxbitmap_cleanup(struct drm_device *dev)
+/**
+ * Context bitmap cleanup.
+ *
+ * \param dev DRM device.
+ *
+ * Free all idr members using drm_ctx_sarea_free helper function
+ * while holding the drm_device::struct_mutex lock.
+ */
+void drm_ctxbitmap_cleanup(struct drm_device * dev)
 {
-       DRM_LOCK(dev);
-       if (dev->context_sareas != NULL)
-               drm_free(dev->context_sareas, M_DRM);
-       drm_free(dev->ctx_bitmap, M_DRM);
-       DRM_UNLOCK(dev);
+       mutex_lock(&dev->struct_mutex);
+       idr_destroy(&dev->ctx_idr);
+       mutex_unlock(&dev->struct_mutex);
 }
 
-/* ================================================================
- * Per Context SAREA Support
- */
+/*@}*/
+
+/******************************************************************/
+/** \name Per Context SAREA Support */
+/*@{*/
 
+/**
+ * Get per-context SAREA.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx_priv_map structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Gets the map from drm_device::ctx_idr with the handle specified and
+ * returns its handle.
+ */
 int drm_getsareactx(struct drm_device *dev, void *data,
                    struct drm_file *file_priv)
 {
        struct drm_ctx_priv_map *request = data;
-       drm_local_map_t *map;
+       struct drm_local_map *map;
+       struct drm_map_list *_entry;
+
+       mutex_lock(&dev->struct_mutex);
 
-       DRM_LOCK(dev);
-       if (dev->max_context < 0 ||
-           request->ctx_id >= (unsigned) dev->max_context) {
-               DRM_UNLOCK(dev);
-               return EINVAL;
+       map = idr_find(&dev->ctx_idr, request->ctx_id);
+       if (!map) {
+               mutex_unlock(&dev->struct_mutex);
+               return -EINVAL;
        }
 
-       map = dev->context_sareas[request->ctx_id];
-       DRM_UNLOCK(dev);
+       request->handle = NULL;
+       list_for_each_entry(_entry, &dev->maplist, head) {
+               if (_entry->map == map) {
+                       request->handle =
+                           (void *)(unsigned long)_entry->user_token;
+                       break;
+               }
+       }
 
-       request->handle = (void *)map->handle;
+       mutex_unlock(&dev->struct_mutex);
+
+       if (request->handle == NULL)
+               return -EINVAL;
 
        return 0;
 }
@@ -169,24 +191,27 @@ int drm_setsareactx(struct drm_device *dev, void *data,
        struct drm_local_map *map = NULL;
        struct drm_map_list *r_list = NULL;
 
-       DRM_LOCK(dev);
+       mutex_lock(&dev->struct_mutex);
        list_for_each_entry(r_list, &dev->maplist, head) {
                if (r_list->map
-                   && r_list->map->handle == request->handle) {
-                       if (dev->max_context < 0)
-                               goto bad;
-                       if (request->ctx_id >= (unsigned) dev->max_context)
-                               goto bad;
-                       map = r_list->map;
-                       dev->context_sareas[request->ctx_id] = map;
-                       DRM_UNLOCK(dev);
-                       return 0;
-               }
+                   && r_list->user_token == (unsigned long) request->handle)
+                       goto found;
        }
+      bad:
+       mutex_unlock(&dev->struct_mutex);
+       return -EINVAL;
+
+      found:
+       map = r_list->map;
+       if (!map)
+               goto bad;
 
-bad:
-       DRM_UNLOCK(dev);
-       return EINVAL;
+       if (IS_ERR(idr_replace(&dev->ctx_idr, map, request->ctx_id)))
+               goto bad;
+
+       mutex_unlock(&dev->struct_mutex);
+
+       return 0;
 }
 
 /*@}*/
@@ -233,11 +258,13 @@ static int drm_context_switch(struct drm_device * dev, int old, int new)
  * hardware lock is held, clears the drm_device::context_flag and wakes up
  * drm_device::context_wait.
  */
-static int drm_context_switch_complete(struct drm_device *dev, int new)
+static int drm_context_switch_complete(struct drm_device *dev,
+                                      struct drm_file *file_priv, int new)
 {
-       dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
+       dev->last_context = new;        /* PRE/POST: This is the _only_ writer. */
+       dev->last_switch = jiffies;
 
-       if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+       if (!_DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock)) {
                DRM_ERROR("Lock isn't held after context switch\n");
        }
 
@@ -245,23 +272,33 @@ static int drm_context_switch_complete(struct drm_device *dev, int new)
           when the kernel holds the lock, release
           that lock here. */
        clear_bit(0, &dev->context_flag);
+       wake_up(&dev->context_wait);
 
        return 0;
 }
 
-int drm_resctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
+/**
+ * Reserve contexts.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx_res structure.
+ * \return zero on success or a negative number on failure.
+ */
+int drm_resctx(struct drm_device *dev, void *data,
+              struct drm_file *file_priv)
 {
        struct drm_ctx_res *res = data;
        struct drm_ctx ctx;
        int i;
 
        if (res->count >= DRM_RESERVED_CONTEXTS) {
-               bzero(&ctx, sizeof(ctx));
+               memset(&ctx, 0, sizeof(ctx));
                for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
                        ctx.handle = i;
-                       if (DRM_COPY_TO_USER(&res->contexts[i],
-                           &ctx, sizeof(ctx)))
-                               return EFAULT;
+                       if (copy_to_user(&res->contexts[i], &ctx, sizeof(ctx)))
+                               return -EFAULT;
                }
        }
        res->count = DRM_RESERVED_CONTEXTS;
@@ -269,8 +306,21 @@ int drm_resctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
        return 0;
 }
 
-int drm_addctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
+/**
+ * Add context.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Get a new handle for the context and copy to userspace.
+ */
+int drm_addctx(struct drm_device *dev, void *data,
+              struct drm_file *file_priv)
 {
+       struct drm_ctx_list *ctx_entry;
        struct drm_ctx *ctx = data;
 
        ctx->handle = drm_ctxbitmap_next(dev);
@@ -282,15 +332,24 @@ int drm_addctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
        if (ctx->handle == -1) {
                DRM_DEBUG("Not enough free contexts.\n");
                /* Should this return -EBUSY instead? */
-               return ENOMEM;
+               return -ENOMEM;
        }
 
-       if (dev->driver->context_ctor && ctx->handle != DRM_KERNEL_CONTEXT) {
-               DRM_LOCK(dev);
-               dev->driver->context_ctor(dev, ctx->handle);
-               DRM_UNLOCK(dev);
+       ctx_entry = kmalloc(sizeof(*ctx_entry), M_DRM, M_WAITOK);
+       if (!ctx_entry) {
+               DRM_DEBUG("out of memory\n");
+               return -ENOMEM;
        }
 
+       INIT_LIST_HEAD(&ctx_entry->head);
+       ctx_entry->handle = ctx->handle;
+       ctx_entry->tag = file_priv;
+
+       mutex_lock(&dev->ctxlist_mutex);
+       list_add(&ctx_entry->head, &dev->ctxlist);
+       ++dev->ctx_count;
+       mutex_unlock(&dev->ctxlist_mutex);
+
        return 0;
 }
 
@@ -300,6 +359,15 @@ int drm_modctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
        return 0;
 }
 
+/**
+ * Get context.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ */
 int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        struct drm_ctx *ctx = data;
@@ -310,6 +378,17 @@ int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
        return 0;
 }
 
+/**
+ * Switch context.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls context_switch().
+ */
 int drm_switchctx(struct drm_device *dev, void *data,
                  struct drm_file *file_priv)
 {
@@ -319,30 +398,66 @@ int drm_switchctx(struct drm_device *dev, void *data,
        return drm_context_switch(dev, dev->last_context, ctx->handle);
 }
 
-int drm_newctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
+/**
+ * New context.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls context_switch_complete().
+ */
+int drm_newctx(struct drm_device *dev, void *data,
+              struct drm_file *file_priv)
 {
        struct drm_ctx *ctx = data;
 
        DRM_DEBUG("%d\n", ctx->handle);
-       drm_context_switch_complete(dev, ctx->handle);
+       drm_context_switch_complete(dev, file_priv, ctx->handle);
 
        return 0;
 }
 
-int drm_rmctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
+/**
+ * Remove context.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * If not the special kernel context, calls ctxbitmap_free() to free the specified context.
+ */
+int drm_rmctx(struct drm_device *dev, void *data,
+             struct drm_file *file_priv)
 {
        struct drm_ctx *ctx = data;
 
        DRM_DEBUG("%d\n", ctx->handle);
        if (ctx->handle != DRM_KERNEL_CONTEXT) {
-               if (dev->driver->context_dtor) {
-                       DRM_LOCK(dev);
+               if (dev->driver->context_dtor)
                        dev->driver->context_dtor(dev, ctx->handle);
-                       DRM_UNLOCK(dev);
-               }
-
                drm_ctxbitmap_free(dev, ctx->handle);
        }
 
+       mutex_lock(&dev->ctxlist_mutex);
+       if (!list_empty(&dev->ctxlist)) {
+               struct drm_ctx_list *pos, *n;
+
+               list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
+                       if (pos->handle == ctx->handle) {
+                               list_del(&pos->head);
+                               kfree(pos, M_DRM);
+                               --dev->ctx_count;
+                       }
+               }
+       }
+       mutex_unlock(&dev->ctxlist_mutex);
+
        return 0;
 }
+
+/*@}*/
index 3353cf1..2a06ae8 100644 (file)
@@ -2635,10 +2635,7 @@ out_err1:
 
 /**
  * drm_fb_release - remove and free the FBs on this file
- * @filp: file * from the ioctl
- *
- * LOCKING:
- * Takes mode config lock.
+ * @priv: drm file for the ioctl
  *
  * Destroy all the FBs associated with @filp.
  *
@@ -2649,18 +2646,23 @@ out_err1:
  */
 void drm_fb_release(struct drm_file *priv)
 {
-#if 1
-       struct drm_device *dev = priv->dev;
-#else
        struct drm_device *dev = priv->minor->dev;
-#endif
        struct drm_framebuffer *fb, *tfb;
 
-       lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
+       mutex_lock(&priv->fbs_lock);
        list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
+
+               mutex_lock(&dev->mode_config.fb_lock);
+               /* Mark fb as reaped, we still have a ref from fpriv->fbs. */
+               __drm_framebuffer_unregister(dev, fb);
+               mutex_unlock(&dev->mode_config.fb_lock);
+
+               list_del_init(&fb->filp_head);
+
+               /* This will also drop the fpriv->fbs reference. */
                drm_framebuffer_remove(fb);
        }
-       lockmgr(&dev->mode_config.mutex, LK_RELEASE);
+       mutex_unlock(&priv->fbs_lock);
 }
 
 struct drm_property *drm_property_create(struct drm_device *dev, int flags,
index 672dbed..f968017 100644 (file)
  * open/close, and ioctl dispatch.
  */
 
-#include <sys/devfs.h>
-#include <machine/limits.h>
+#include <sys/file.h>
+
+#include <linux/export.h>
 
 #include <drm/drmP.h>
 #include <drm/drm_core.h>
 
-#ifdef DRM_DEBUG_DEFAULT_ON
-int drm_debug = (DRM_DEBUGBITS_DEBUG | DRM_DEBUGBITS_KMS |
-    DRM_DEBUGBITS_FAILED_IOCTL);
-#else
-int drm_debug = 0;
-#endif
 int drm_notyet_flag = 0;
 
-unsigned int drm_vblank_offdelay = 5000;    /* Default to 5000 msecs. */
-unsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */
-
 static int drm_load(struct drm_device *dev);
 drm_pci_id_list_t *drm_find_description(int vendor, int device,
     drm_pci_id_list_t *idlist);
@@ -179,7 +171,7 @@ static drm_ioctl_desc_t               drm_ioctls[256] = {
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 };
 
-static struct dev_ops drm_cdevsw = {
+struct dev_ops drm_cdevsw = {
        { "drm", 0, D_TRACKCLOSE | D_MPSAFE },
        .d_open =       drm_open,
        .d_close =      drm_close,
@@ -313,10 +305,6 @@ int drm_attach(device_t kdev, drm_pci_id_list_t *idlist)
        if (error)
                goto error;
 
-       error = drm_create_cdevs(kdev);
-       if (error)
-               goto error;
-
        return (error);
 error:
        if (dev->irqr) {
@@ -329,23 +317,6 @@ error:
        return (error);
 }
 
-int
-drm_create_cdevs(device_t kdev)
-{
-       struct drm_device *dev;
-       int error, unit;
-
-       unit = device_get_unit(kdev);
-       dev = device_get_softc(kdev);
-
-       dev->devnode = make_dev(&drm_cdevsw, unit, DRM_DEV_UID, DRM_DEV_GID,
-                               DRM_DEV_MODE, "dri/card%d", unit);
-       error = 0;
-       if (error == 0)
-               dev->devnode->si_drv1 = dev;
-       return (error);
-}
-
 #ifndef DRM_DEV_NAME
 #define DRM_DEV_NAME "drm"
 #endif
@@ -378,31 +349,17 @@ drm_pci_id_list_t *drm_find_description(int vendor, int device,
  */
 int drm_lastclose(struct drm_device * dev)
 {
-       drm_magic_entry_t *pt, *next;
-       int i;
 
        DRM_DEBUG("\n");
 
        if (dev->driver->lastclose != NULL)
                dev->driver->lastclose(dev);
+       DRM_DEBUG("driver lastclose completed\n");
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET) && dev->irq_enabled)
+       if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET))
                drm_irq_uninstall(dev);
 
-       DRM_LOCK(dev);
-       if (dev->unique) {
-               drm_free(dev->unique, M_DRM);
-               dev->unique = NULL;
-               dev->unique_len = 0;
-       }
-       /* Clear pid list */
-       for (i = 0; i < DRM_HASH_SIZE; i++) {
-               for (pt = dev->magiclist[i].head; pt; pt = next) {
-                       next = pt->next;
-                       drm_free(pt, M_DRM);
-               }
-               dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
-       }
+       mutex_lock(&dev->struct_mutex);
 
        /* Clear AGP information */
        if (dev->agp) {
@@ -433,12 +390,10 @@ int drm_lastclose(struct drm_device * dev)
        }
 
        drm_dma_takedown(dev);
-       if (dev->lock.hw_lock) {
-               dev->lock.hw_lock = NULL; /* SHM removed */
-               dev->lock.file_priv = NULL;
-               DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
-       }
-       DRM_UNLOCK(dev);
+
+       mutex_unlock(&dev->struct_mutex);
+
+       DRM_DEBUG("lastclose completed\n");
 
        return 0;
 }
@@ -573,116 +528,25 @@ int drm_close(struct dev_close_args *ap)
        return 0;
 }
 
-void drm_cdevpriv_dtor(void *cd)
-{
-       struct drm_file *file_priv = cd;
-       struct drm_device *dev = file_priv->dev;
-       int retcode = 0;
-
-       DRM_DEBUG("open_count = %d\n", dev->open_count);
-
-       DRM_LOCK(dev);
-
-       if (dev->driver->preclose != NULL)
-               dev->driver->preclose(dev, file_priv);
-
-       /* ========================================================
-        * Begin inline drm_release
-        */
-
-       DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
-           DRM_CURRENTPID, (long)dev->dev, dev->open_count);
-
-       if (dev->driver->driver_features & DRIVER_GEM)
-               drm_gem_release(dev, file_priv);
-
-       if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
-           && dev->lock.file_priv == file_priv) {
-               DRM_DEBUG("Process %d dead, freeing lock for context %d\n",
-                         DRM_CURRENTPID,
-                         _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-               if (dev->driver->reclaim_buffers_locked != NULL)
-                       dev->driver->reclaim_buffers_locked(dev, file_priv);
-
-               drm_lock_free(&dev->lock,
-                   _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-
-                               /* FIXME: may require heavy-handed reset of
-                                   hardware at this point, possibly
-                                   processed via a callback to the X
-                                   server. */
-       } else if (dev->driver->reclaim_buffers_locked != NULL &&
-           dev->lock.hw_lock != NULL) {
-               /* The lock is required to reclaim buffers */
-               for (;;) {
-                       if (!dev->lock.hw_lock) {
-                               /* Device has been unregistered */
-                               retcode = EINTR;
-                               break;
-                       }
-                       if (drm_lock_take(&dev->lock, DRM_KERNEL_CONTEXT)) {
-                               dev->lock.file_priv = file_priv;
-                               dev->lock.lock_time = jiffies;
-                               atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
-                               break;  /* Got lock */
-                       }
-                       /* Contention */
-                       retcode = DRM_LOCK_SLEEP(dev, &dev->lock.lock_queue,
-                           PCATCH, "drmlk2", 0);
-                       if (retcode)
-                               break;
-               }
-               if (retcode == 0) {
-                       dev->driver->reclaim_buffers_locked(dev, file_priv);
-                       drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT);
-               }
-       }
-
-       if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
-           !dev->driver->reclaim_buffers_locked)
-               drm_reclaim_buffers(dev, file_priv);
-
-       funsetown(&dev->buf_sigio);
-
-       if (dev->driver->postclose != NULL)
-               dev->driver->postclose(dev, file_priv);
-       list_del(&file_priv->lhead);
-
-
-       /* ========================================================
-        * End inline drm_release
-        */
-
-       atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
-       device_unbusy(dev->dev);
-       if (--dev->open_count == 0) {
-               retcode = drm_lastclose(dev);
-       }
-
-       DRM_UNLOCK(dev);
-}
-
 /* drm_ioctl is called whenever a process performs an ioctl on /dev/drm.
  */
 int drm_ioctl(struct dev_ioctl_args *ap)
 {
-       struct cdev *kdev = ap->a_head.a_dev;
+       struct file *filp = ap->a_fp;
+       struct drm_file *file_priv = filp->private_data;
+       struct drm_device *dev;
        u_long cmd = ap->a_cmd;
        caddr_t data = ap->a_data;
        struct thread *p = curthread;
-       struct drm_device *dev = drm_get_device_from_kdev(kdev);
        int retcode = 0;
        drm_ioctl_desc_t *ioctl;
        int (*func)(struct drm_device *dev, void *data, struct drm_file *file_priv);
        int nr = DRM_IOCTL_NR(cmd);
        int is_driver_ioctl = 0;
-       struct drm_file *file_priv;
 
-       retcode = devfs_get_cdevpriv(ap->a_fp, (void **)&file_priv);
-       if (retcode !=0) {
-               DRM_ERROR("can't find authenticator\n");
-               return EINVAL;
-       }
+       dev = file_priv->minor->dev;
+       if (!dev)
+               return -EINVAL;
 
        atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
        ++file_priv->ioctl_count;
@@ -795,14 +659,13 @@ drm_add_busid_modesetting(struct drm_device *dev, struct sysctl_ctx_list *ctx,
 int
 drm_mmap_single(struct dev_mmap_single_args *ap)
 {
-       struct drm_device *dev;
        struct cdev *kdev = ap->a_head.a_dev;
+       struct drm_device *dev = drm_get_device_from_kdev(kdev);
        vm_ooffset_t *offset = ap->a_offset;
        vm_size_t size = ap->a_size;
        struct vm_object **obj_res = ap->a_object;
        int nprot = ap->a_nprot;
 
-       dev = drm_get_device_from_kdev(kdev);
        if (dev->drm_ttm_bdev != NULL) {
                return (ttm_bo_mmap_single(dev->drm_ttm_bdev, offset, size,
                    obj_res, nprot));
@@ -853,6 +716,7 @@ drm_core_init(void *arg)
 {
 
        drm_global_init();
+       idr_init(&drm_minors_idr);
 
 #if DRM_LINUX
        linux_ioctl_register_handler(&drm_handler);
@@ -872,6 +736,7 @@ drm_core_exit(void *arg)
 #endif /* DRM_LINUX */
 
        drm_global_release();
+       idr_destroy(&drm_minors_idr);
 }
 
 SYSINIT(drm_register, SI_SUB_DRIVERS, SI_ORDER_MIDDLE,
index a0f3586..6ea62aa 100644 (file)
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * $FreeBSD: src/sys/dev/drm2/drm_fops.c,v 1.1 2012/05/22 11:07:44 kib Exp $
  */
 
-#include <sys/types.h>
-#include <sys/conf.h>
 #include <sys/devfs.h>
+#include <sys/file.h>
 
 #include <drm/drmP.h>
+#include <linux/module.h>
 
-extern drm_pci_id_list_t *drm_find_description(int vendor, int device,
-    drm_pci_id_list_t *idlist);
-extern devclass_t drm_devclass;
+static int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
+                   struct drm_device *dev, struct file *fp);
 
 static int drm_setup(struct drm_device *dev)
 {
        drm_local_map_t *map;
        int i;
-
-       DRM_LOCK_ASSERT(dev);
+       int ret;
 
        /* prebuild the SAREA */
        i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM,
@@ -59,77 +55,128 @@ static int drm_setup(struct drm_device *dev)
        if (i != 0)
                return i;
 
-       if (dev->driver->firstopen)
-               dev->driver->firstopen(dev);
+       if (dev->driver->firstopen) {
+               ret = dev->driver->firstopen(dev);
+               if (ret != 0)
+                       return ret;
+       }
 
-       dev->buf_use = 0;
+       if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
+           !drm_core_check_feature(dev, DRIVER_MODESET)) {
+               dev->buf_use = 0;
+               atomic_set(&dev->buf_alloc, 0);
 
-       if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) {
                i = drm_dma_setup(dev);
                if (i != 0)
                        return i;
        }
 
-       for (i = 0; i < DRM_HASH_SIZE; i++) {
-               dev->magiclist[i].head = NULL;
-               dev->magiclist[i].tail = NULL;
-       }
+       for (i = 0; i < ARRAY_SIZE(dev->counts); i++)
+               atomic_set(&dev->counts[i], 0);
+
+       dev->sigdata.lock = NULL;
 
-       init_waitqueue_head(&dev->lock.lock_queue);
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               dev->irq_enabled = 0;
        dev->context_flag = 0;
+       dev->interrupt_flag = 0;
+       dev->dma_flag = 0;
        dev->last_context = 0;
+       dev->last_switch = 0;
+       dev->last_checked = 0;
+       init_waitqueue_head(&dev->context_wait);
        dev->if_version = 0;
 
-       dev->buf_sigio = NULL;
+       dev->ctx_start = 0;
+       dev->lck_start = 0;
+
+       dev->buf_async = NULL;
+       init_waitqueue_head(&dev->buf_readers);
+       init_waitqueue_head(&dev->buf_writers);
 
        DRM_DEBUG("\n");
 
+       /*
+        * The kernel's context could be created here, but is now created
+        * in drm_dma_enqueue.  This is more resource-efficient for
+        * hardware that does not do DMA, but may mean that
+        * drm_select_queue fails between the time the interrupt is
+        * initialized and the time the queues are initialized.
+        */
+
        return 0;
 }
 
 #define DRIVER_SOFTC(unit) \
        ((struct drm_device *)devclass_get_softc(drm_devclass, unit))
 
-int
-drm_open(struct dev_open_args *ap)
+/**
+ * Open file.
+ *
+ * \param inode device inode
+ * \param filp file pointer.
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches the DRM device with the same minor number, calls open_helper(), and
+ * increments the device open count. If the open count was previous at zero,
+ * i.e., it's the first that the device is open, then calls setup().
+ */
+int drm_open(struct dev_open_args *ap)
 {
        struct cdev *kdev = ap->a_head.a_dev;
+       struct file *filp = ap->a_fp;
+       struct drm_device *dev = NULL;
+       int minor_id = minor(kdev);
+       struct drm_minor *minor;
+       int retcode = 0;
+       int need_setup = 0;
+/* old dfly variables below */
        int flags = ap->a_oflags;
        int fmt = 0;
        struct thread *p = curthread;
-       struct drm_device *dev;
-       int retcode;
 
-       dev = DRIVER_SOFTC(minor(kdev));
-       if (dev == NULL)
-               return (ENXIO);
+       minor = idr_find(&drm_minors_idr, minor_id);
+       if (!minor)
+               return -ENODEV;
 
-       DRM_DEBUG("open_count = %d\n", dev->open_count);
+       if (!(dev = minor->dev))
+               return -ENODEV;
 
-       retcode = drm_open_helper(kdev, flags, fmt, p, dev, ap->a_fp);
+       if (!dev->open_count++)
+               need_setup = 1;
 
-       if (retcode == 0) {
-               atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
-               DRM_LOCK(dev);
-               device_busy(dev->dev);
-               if (!dev->open_count++)
-                       retcode = drm_setup(dev);
-               DRM_UNLOCK(dev);
+       retcode = drm_open_helper(kdev, flags, fmt, p, dev, filp);
+       if (retcode)
+               goto err_undo;
+       atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
+       if (need_setup) {
+               retcode = drm_setup(dev);
+               if (retcode)
+                       goto err_undo;
        }
+       return 0;
 
-       DRM_DEBUG("return %d\n", retcode);
-
-       return (retcode);
+err_undo:
+       dev->open_count--;
+       return retcode;
 }
+EXPORT_SYMBOL(drm_open);
 
-/* drm_open_helper is called whenever a process opens /dev/drm. */
-int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
-                   struct drm_device *dev, struct file *fp)
+/**
+ * Called whenever a process opens /dev/drm.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param dev device.
+ * \return zero on success or a negative number on failure.
+ *
+ * Creates and initializes a drm_file structure for the file private data in \p
+ * filp and add it into the double linked list in \p dev.
+ */
+static int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
+                   struct drm_device *dev, struct file *filp)
 {
+       int minor_id = 0;
        struct drm_file *priv;
-       int retcode;
+       int ret;
 
        if (flags & O_EXCL)
                return EBUSY; /* No exclusive opens */
@@ -138,20 +185,22 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
        DRM_DEBUG("pid = %d, device = %s\n", DRM_CURRENTPID, devtoname(kdev));
 
        priv = kmalloc(sizeof(*priv), M_DRM, M_WAITOK | M_NULLOK | M_ZERO);
-       if (priv == NULL) {
-               return ENOMEM;
-       }
-       
-       DRM_LOCK(dev);
-       priv->dev               = dev;
+       if (!priv)
+               return -ENOMEM;
+
+       filp->private_data = priv;
+       priv->filp = filp;
        priv->uid               = p->td_proc->p_ucred->cr_svuid;
        priv->pid               = p->td_proc->p_pid;
-       priv->ioctl_count       = 0;
-
+       priv->minor = idr_find(&drm_minors_idr, minor_id);
+       priv->ioctl_count = 0;
        /* for compatibility root is always authenticated */
        priv->authenticated     = DRM_SUSER(p);
+       priv->lock_count = 0;
 
+       INIT_LIST_HEAD(&priv->lhead);
        INIT_LIST_HEAD(&priv->fbs);
+       lockinit(&priv->fbs_lock, "dfbsl", 0, LK_CANRECURSE);
        INIT_LIST_HEAD(&priv->event_list);
        init_waitqueue_head(&priv->event_wait);
        priv->event_space = 4096; /* set aside 4k for event buffer */
@@ -160,27 +209,67 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
                drm_gem_open(dev, priv);
 
        if (dev->driver->open) {
-               /* shared code returns -errno */
-               retcode = -dev->driver->open(dev, priv);
-               if (retcode != 0) {
-                       drm_free(priv, M_DRM);
-                       DRM_UNLOCK(dev);
-                       return retcode;
-               }
+               ret = dev->driver->open(dev, priv);
+               if (ret != 0)
+                       goto out_free;
        }
 
-       /* first opener automatically becomes master */
-       priv->master = list_empty(&dev->filelist);
+       /* if there is no current master make this fd it */
+       mutex_lock(&dev->struct_mutex);
+       if (!priv->minor->master) {
+               /* create a new master */
+               priv->minor->master = drm_master_create(priv->minor);
+               if (!priv->minor->master) {
+                       mutex_unlock(&dev->struct_mutex);
+                       ret = -ENOMEM;
+                       goto out_free;
+               }
 
-       list_add(&priv->lhead, &dev->filelist);
-       DRM_UNLOCK(dev);
-       kdev->si_drv1 = dev;
+               priv->is_master = 1;
+               /* take another reference for the copy in the local file priv */
+               priv->master = drm_master_get(priv->minor->master);
+
+               priv->authenticated = 1;
+
+               mutex_unlock(&dev->struct_mutex);
+               if (dev->driver->master_create) {
+                       ret = dev->driver->master_create(dev, priv->master);
+                       if (ret) {
+                               mutex_lock(&dev->struct_mutex);
+                               /* drop both references if this fails */
+                               drm_master_put(&priv->minor->master);
+                               drm_master_put(&priv->master);
+                               mutex_unlock(&dev->struct_mutex);
+                               goto out_free;
+                       }
+               }
+               mutex_lock(&dev->struct_mutex);
+               if (dev->driver->master_set) {
+                       ret = dev->driver->master_set(dev, priv, true);
+                       if (ret) {
+                               /* drop both references if this fails */
+                               drm_master_put(&priv->minor->master);
+                               drm_master_put(&priv->master);
+                               mutex_unlock(&dev->struct_mutex);
+                               goto out_free;
+                       }
+               }
+               mutex_unlock(&dev->struct_mutex);
+       } else {
+               /* get a reference to the master */
+               priv->master = drm_master_get(priv->minor->master);
+               mutex_unlock(&dev->struct_mutex);
+       }
 
-       retcode = devfs_set_cdevpriv(fp, priv, &drm_cdevpriv_dtor);
-       if (retcode != 0)
-               drm_cdevpriv_dtor(priv);
+       mutex_lock(&dev->struct_mutex);
+       list_add(&priv->lhead, &dev->filelist);
+       mutex_unlock(&dev->struct_mutex);
 
-       return retcode;
+       return 0;
+      out_free:
+       kfree(priv, M_DRM);
+       filp->private_data = NULL;
+       return ret;
 }
 
 /**
@@ -391,19 +480,15 @@ drm_dequeue_event(struct drm_device *dev, struct drm_file *file_priv,
 int
 drm_read(struct dev_read_args *ap)
 {
+       struct file *filp = ap->a_fp;
+       struct drm_file *file_priv = filp->private_data;
        struct cdev *kdev = ap->a_head.a_dev;
        struct uio *uio = ap->a_uio;
        int ioflag = ap->a_ioflag;
-       struct drm_file *file_priv;
        struct drm_device *dev;
        struct drm_pending_event *e;
        int error;
 
-       error = devfs_get_cdevpriv(ap->a_fp, (void **)&file_priv);
-       if (error != 0) {
-               DRM_ERROR("can't find authenticator\n");
-               return (EINVAL);
-       }
        dev = drm_get_device_from_kdev(kdev);
        lockmgr(&dev->event_lock, LK_EXCLUSIVE);
        while (list_empty(&file_priv->event_list)) {
@@ -432,11 +517,9 @@ out:
 void
 drm_event_wakeup(struct drm_pending_event *e)
 {
-       struct drm_file *file_priv;
-       struct drm_device *dev;
+       struct drm_file *file_priv = e->file_priv;
+       struct drm_device *dev = file_priv->minor->dev;
 
-       file_priv = e->file_priv;
-       dev = file_priv->dev;
        KKASSERT(lockstatus(&dev->event_lock, curthread) != 0);
 
        wakeup(&file_priv->event_space);
@@ -446,12 +529,10 @@ drm_event_wakeup(struct drm_pending_event *e)
 static int
 drmfilt(struct knote *kn, long hint)
 {
-       struct drm_file *file_priv;
-       struct drm_device *dev;
+       struct drm_file *file_priv = (struct drm_file *)kn->kn_hook;
+       struct drm_device *dev = file_priv->minor->dev;
        int ready = 0;
 
-       file_priv = (struct drm_file *)kn->kn_hook;
-       dev = file_priv->dev;
        lockmgr(&dev->event_lock, LK_EXCLUSIVE);
        if (!list_empty(&file_priv->event_list))
                ready = 1;
@@ -463,13 +544,10 @@ drmfilt(struct knote *kn, long hint)
 static void
 drmfilt_detach(struct knote *kn)
 {
-       struct drm_file *file_priv;
-       struct drm_device *dev;
+       struct drm_file *file_priv = (struct drm_file *)kn->kn_hook;
+       struct drm_device *dev = file_priv->minor->dev;
        struct klist *klist;
 
-       file_priv = (struct drm_file *)kn->kn_hook;
-       dev = file_priv->dev;
-
        lockmgr(&dev->event_lock, LK_EXCLUSIVE);
        klist = &file_priv->dkq.ki_note;
        knote_remove(klist, kn);
@@ -482,25 +560,16 @@ static struct filterops drmfiltops =
 int
 drm_kqfilter(struct dev_kqfilter_args *ap)
 {
-       struct cdev *kdev = ap->a_head.a_dev;
-       struct drm_file *file_priv;
-       struct drm_device *dev;
+       struct file *filp = ap->a_fp;
+       struct drm_file *file_priv = filp->private_data;
+       struct drm_device *dev = file_priv->minor->dev;
        struct knote *kn = ap->a_kn;
        struct klist *klist;
-       int error;
-
-       error = devfs_get_cdevpriv(ap->a_fp, (void **)&file_priv);
-       if (error != 0) {
-               DRM_ERROR("can't find authenticator\n");
-               return (EINVAL);
-       }
-       dev = drm_get_device_from_kdev(kdev);
 
        ap->a_result = 0;
 
        switch (kn->kn_filter) {
        case EVFILT_READ:
-       case EVFILT_WRITE:
                kn->kn_fop = &drmfiltops;
                kn->kn_hook = (caddr_t)file_priv;
                break;
index 4814902..c03d0eb 100644 (file)
@@ -267,7 +267,7 @@ int drm_getstats(struct drm_device *dev, void *data, struct drm_file *file_priv)
        for (i = 0; i < dev->counters; i++) {
                if (dev->types[i] == _DRM_STAT_LOCK)
                        stats->data[i].value =
-                           (dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0);
+                           (dev->primary->master->lock.hw_lock ? dev->primary->master->lock.hw_lock->lock : 0);
                else 
                        stats->data[i].value = atomic_read(&dev->counts[i]);
                stats->data[i].type = dev->types[i];
index 05dac6f..bee8111 100644 (file)
@@ -62,7 +62,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
        }
 
        DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
-           lock->context, DRM_CURRENTPID, dev->lock.hw_lock->lock,
+           lock->context, DRM_CURRENTPID, dev->primary->master->lock.hw_lock->lock,
            lock->flags);
 
        if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) &&
@@ -71,15 +71,15 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
 
        DRM_LOCK(dev);
        for (;;) {
-               if (drm_lock_take(&dev->lock, lock->context)) {
-                       dev->lock.file_priv = file_priv;
-                       dev->lock.lock_time = jiffies;
+               if (drm_lock_take(&dev->primary->master->lock, lock->context)) {
+                       dev->primary->master->lock.file_priv = file_priv;
+                       dev->primary->master->lock.lock_time = jiffies;
                        atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
                        break;  /* Got lock */
                }
 
                /* Contention */
-               ret = DRM_LOCK_SLEEP(dev, &dev->lock.lock_queue,
+               ret = DRM_LOCK_SLEEP(dev, &dev->primary->master->lock.lock_queue,
                    PCATCH, "drmlk2", 0);
                if (ret != 0)
                        break;
@@ -109,7 +109,7 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
        struct drm_lock *lock = data;
 
        DRM_DEBUG("%d (pid %d) requests unlock (0x%08x), flags = 0x%08x\n",
-           lock->context, DRM_CURRENTPID, dev->lock.hw_lock->lock,
+           lock->context, DRM_CURRENTPID, dev->primary->master->lock.hw_lock->lock,
            lock->flags);
 
        if (lock->context == DRM_KERNEL_CONTEXT) {
@@ -121,9 +121,9 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
        atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
 
        DRM_LOCK(dev);
-       drm_lock_transfer(&dev->lock, DRM_KERNEL_CONTEXT);
+       drm_lock_transfer(&dev->primary->master->lock, DRM_KERNEL_CONTEXT);
 
-       if (drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT)) {
+       if (drm_lock_free(&dev->primary->master->lock, DRM_KERNEL_CONTEXT)) {
                DRM_ERROR("\n");
        }
        DRM_UNLOCK(dev);
index 648a2ec..b24d9fe 100644 (file)
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- *
- * $FreeBSD: src/sys/dev/drm2/drm_stub.c,v 1.1 2012/05/22 11:07:44 kib Exp $
  */
 
+#include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <drm/drmP.h>
+#include <drm/drm_core.h>
+
+unsigned int drm_debug = 0;    /* 1 to enable debug output */
+EXPORT_SYMBOL(drm_debug);
+
+unsigned int drm_vblank_offdelay = 5000;    /* Default to 5000 msecs. */
+EXPORT_SYMBOL(drm_vblank_offdelay);
+
+unsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */
+EXPORT_SYMBOL(drm_timestamp_precision);
 
 /*
  * Default to use monotonic timestamps for wait-for-vblank and page-flip
  */
 unsigned int drm_timestamp_monotonic = 1;
 
-int
-drm_setmaster_ioctl(struct drm_device *dev, void *data,
-    struct drm_file *file_priv)
+MODULE_AUTHOR(CORE_AUTHOR);
+MODULE_DESCRIPTION(CORE_DESC);
+MODULE_LICENSE("GPL and additional rights");
+MODULE_PARM_DESC(debug, "Enable debug output");
+MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]");
+MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
+MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps");
+
+module_param_named(debug, drm_debug, int, 0600);
+module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
+module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
+module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
+
+struct idr drm_minors_idr;
+
+struct class *drm_class;
+struct proc_dir_entry *drm_proc_root;
+struct dentry *drm_debugfs_root;
+
+int drm_err(const char *func, const char *format, ...)
+{
+#if 0
+       struct va_format vaf;
+       va_list args;
+       int r;
+
+       va_start(args, format);
+
+       vaf.fmt = format;
+       vaf.va = &args;
+
+       r = printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, &vaf);
+
+       va_end(args);
+
+       return r;
+#endif
+       return 0;
+}
+EXPORT_SYMBOL(drm_err);
+
+#if 0
+void drm_ut_debug_printk(unsigned int request_level,
+                        const char *prefix,
+                        const char *function_name,
+                        const char *format, ...)
+{
+       va_list args;
+
+       if (drm_debug & request_level) {
+               if (function_name)
+                       printk(KERN_DEBUG "[%s:%s], ", prefix, function_name);
+               va_start(args, format);
+               vprintk(format, args);
+               va_end(args);
+       }
+}
+EXPORT_SYMBOL(drm_ut_debug_printk);
+#endif
+
+static int drm_minor_get_id(struct drm_device *dev, int type)
+{
+       int new_id;
+       int ret;
+       int base = 0, limit = 63;
+
+       if (type == DRM_MINOR_CONTROL) {
+                base += 64;
+                limit = base + 127;
+        } else if (type == DRM_MINOR_RENDER) {
+                base += 128;
+                limit = base + 255;
+        }
+
+again:
+       if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) {
+               DRM_ERROR("Out of memory expanding drawable idr\n");
+               return -ENOMEM;
+       }
+       mutex_lock(&dev->struct_mutex);
+       ret = idr_get_new_above(&drm_minors_idr, NULL,
+                               base, &new_id);
+       mutex_unlock(&dev->struct_mutex);
+       if (ret == -EAGAIN)
+               goto again;
+       else if (ret) {
+               return ret;
+       }
+
+       if (new_id >= limit) {
+               idr_remove(&drm_minors_idr, new_id);
+               return -EINVAL;
+       }
+       return new_id;
+}
+
+struct drm_master *drm_master_create(struct drm_minor *minor)
+{
+       struct drm_master *master;
+
+       master = kmalloc(sizeof(*master), M_DRM, M_WAITOK | M_ZERO);
+       if (!master)
+               return NULL;
+
+       kref_init(&master->refcount);
+       spin_init(&master->lock.spinlock, "drmmls");
+       init_waitqueue_head(&master->lock.lock_queue);
+       drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER);
+       INIT_LIST_HEAD(&master->magicfree);
+       master->minor = minor;
+
+       list_add_tail(&master->head, &minor->master_list);
+
+       return master;
+}
+
+struct drm_master *drm_master_get(struct drm_master *master)
+{
+       kref_get(&master->refcount);
+       return master;
+}
+EXPORT_SYMBOL(drm_master_get);
+
+static void drm_master_destroy(struct kref *kref)
+{
+       struct drm_master *master = container_of(kref, struct drm_master, refcount);
+       struct drm_magic_entry *pt, *next;
+       struct drm_device *dev = master->minor->dev;
+       struct drm_map_list *r_list, *list_temp;
+
+       list_del(&master->head);
+
+       if (dev->driver->master_destroy)
+               dev->driver->master_destroy(dev, master);
+
+       list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) {
+               if (r_list->master == master) {
+                       drm_rmmap_locked(dev, r_list->map);
+                       r_list = NULL;
+               }
+       }
+
+       if (master->unique) {
+               kfree(master->unique, M_DRM);
+               master->unique = NULL;
+               master->unique_len = 0;
+       }
+
+#if 0
+       kfree(dev->devname, M_DRM);
+       dev->devname = NULL;
+#endif
+
+       list_for_each_entry_safe(pt, next, &master->magicfree, head) {
+               list_del(&pt->head);
+               drm_ht_remove_item(&master->magiclist, &pt->hash_item);
+               kfree(pt, M_DRM);
+       }
+
+       drm_ht_remove(&master->magiclist);
+
+       kfree(master, M_DRM);
+}
+
+void drm_master_put(struct drm_master **master)
+{
+       kref_put(&(*master)->refcount, drm_master_destroy);
+       *master = NULL;
+}
+EXPORT_SYMBOL(drm_master_put);
+
+int drm_setmaster_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
+{
+       int ret;
+
+       if (file_priv->is_master)
+               return 0;
+
+       if (file_priv->minor->master && file_priv->minor->master != file_priv->master)
+               return -EINVAL;
+
+       if (!file_priv->master)
+               return -EINVAL;
+
+       if (file_priv->minor->master)
+               return -EINVAL;
+
+       mutex_lock(&dev->struct_mutex);
+       file_priv->minor->master = drm_master_get(file_priv->master);
+       file_priv->is_master = 1;
+       if (dev->driver->master_set) {
+               ret = dev->driver->master_set(dev, file_priv, false);
+               if (unlikely(ret != 0)) {
+                       file_priv->is_master = 0;
+                       drm_master_put(&file_priv->minor->master);
+               }
+       }
+       mutex_unlock(&dev->struct_mutex);
+
+       return 0;
+}
+
+int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       if (!file_priv->is_master)
+               return -EINVAL;
+
+       if (!file_priv->minor->master)
+               return -EINVAL;
+
+       mutex_lock(&dev->struct_mutex);
+       if (dev->driver->master_drop)
+               dev->driver->master_drop(dev, file_priv, false);
+       drm_master_put(&file_priv->minor->master);
+       file_priv->is_master = 0;
+       mutex_unlock(&dev->struct_mutex);
+       return 0;
+}
+
+#if 0
+int drm_fill_in_dev(struct drm_device *dev,
+                          const struct pci_device_id *ent,
+                          struct drm_driver *driver)
+{
+       int retcode;
+
+       INIT_LIST_HEAD(&dev->filelist);
+       INIT_LIST_HEAD(&dev->ctxlist);
+       INIT_LIST_HEAD(&dev->vmalist);
+       INIT_LIST_HEAD(&dev->maplist);
+       INIT_LIST_HEAD(&dev->vblank_event_list);
+
+       spin_lock_init(&dev->count_lock);
+       spin_lock_init(&dev->event_lock);
+       mutex_init(&dev->struct_mutex);
+       mutex_init(&dev->ctxlist_mutex);
+
+       if (drm_ht_create(&dev->map_hash, 12)) {
+               return -ENOMEM;
+       }
+
+       /* the DRM has 6 basic counters */
+       dev->counters = 6;
+       dev->types[0] = _DRM_STAT_LOCK;
+       dev->types[1] = _DRM_STAT_OPENS;
+       dev->types[2] = _DRM_STAT_CLOSES;
+       dev->types[3] = _DRM_STAT_IOCTLS;
+       dev->types[4] = _DRM_STAT_LOCKS;
+       dev->types[5] = _DRM_STAT_UNLOCKS;
+
+       dev->driver = driver;
+
+       if (dev->driver->bus->agp_init) {
+               retcode = dev->driver->bus->agp_init(dev);
+               if (retcode)
+                       goto error_out_unreg;
+       }
+
+
+
+       retcode = drm_ctxbitmap_init(dev);
+       if (retcode) {
+               DRM_ERROR("Cannot allocate memory for context bitmap.\n");
+               goto error_out_unreg;
+       }
+
+       if (driver->driver_features & DRIVER_GEM) {
+               retcode = drm_gem_init(dev);
+               if (retcode) {
+                       DRM_ERROR("Cannot initialize graphics execution "
+                                 "manager (GEM)\n");
+                       goto error_out_unreg;
+               }
+       }
+
+       return 0;
+
+      error_out_unreg:
+       drm_lastclose(dev);
+       return retcode;
+}
+EXPORT_SYMBOL(drm_fill_in_dev);
+#endif
+
+extern struct dev_ops drm_cdevsw;
+
+/**
+ * Get a secondary minor number.
+ *
+ * \param dev device data structure
+ * \param sec-minor structure to hold the assigned minor
+ * \return negative number on failure.
+ *
+ * Search an empty entry and initialize it to the given parameters, and
+ * create the proc init entry via proc_init(). This routines assigns
+ * minor numbers to secondary heads of multi-headed cards
+ */
+int drm_get_minor(device_t kdev, struct drm_device *dev, struct drm_minor **minor, int type)
+{
+       struct drm_minor *new_minor;
+       int ret;
+       int minor_id;
+       int unit;
+
+       DRM_DEBUG("\n");
+
+       minor_id = drm_minor_get_id(dev, type);
+       if (minor_id < 0)
+               return minor_id;
+
+       new_minor = kmalloc(sizeof(struct drm_minor), M_DRM, M_WAITOK | M_ZERO);
+       if (!new_minor) {
+               ret = -ENOMEM;
+               goto err_idr;
+       }
+
+       new_minor->type = type;
+#if 0  /* Linux */
+       new_minor->device = MKDEV(DRM_MAJOR, minor_id);
+#else
+       unit = device_get_unit(kdev);
+       new_minor->device = make_dev(&drm_cdevsw, minor_id, DRM_DEV_UID, DRM_DEV_GID,
+                               DRM_DEV_MODE, "dri/card%d", unit);
+       new_minor->device->si_drv1 = dev;
+#endif
+
+       new_minor->dev = dev;
+       new_minor->index = minor_id;
+       INIT_LIST_HEAD(&new_minor->master_list);
+
+       idr_replace(&drm_minors_idr, new_minor, minor_id);
+
+#if 0
+       if (type == DRM_MINOR_LEGACY) {
+               ret = drm_proc_init(new_minor, minor_id, drm_proc_root);
+               if (ret) {
+                       DRM_ERROR("DRM: Failed to initialize /proc/dri.\n");
+                       goto err_mem;
+               }
+       } else
+               new_minor->proc_root = NULL;
+#endif
+
+#if defined(CONFIG_DEBUG_FS)
+       ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
+       if (ret) {
+               DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
+               goto err_g2;
+       }
+#endif
+
+#if 0
+       ret = drm_sysfs_device_add(new_minor);
+       if (ret) {
+               printk(KERN_ERR
+                      "DRM: Error sysfs_device_add.\n");
+               goto err_g2;
+       }
+#endif
+       *minor = new_minor;
+
+       DRM_DEBUG("new minor assigned %d\n", minor_id);
+       return 0;
+
+
+#if 0
+err_g2:
+       if (new_minor->type == DRM_MINOR_LEGACY)
+               drm_proc_cleanup(new_minor, drm_proc_root);
+err_mem:
+       kfree(new_minor, M_DRM);
+#endif
+err_idr:
+       idr_remove(&drm_minors_idr, minor_id);
+       *minor = NULL;
+       return ret;
+}
+EXPORT_SYMBOL(drm_get_minor);
+
+#if 0
+/**
+ * Put a secondary minor number.
+ *
+ * \param sec_minor - structure to be released
+ * \return always zero
+ *
+ * Cleans up the proc resources. Not legal for this to be the
+ * last minor released.
+ *
+ */
+int drm_put_minor(struct drm_minor **minor_p)
 {
+       struct drm_minor *minor = *minor_p;
 
-       DRM_DEBUG("setmaster\n");
+       DRM_DEBUG("release secondary minor %d\n", minor->index);
 
-       if (file_priv->master != 0)
-               return (0);
-       return (-EPERM);
+       if (minor->type == DRM_MINOR_LEGACY)
+               drm_proc_cleanup(minor, drm_proc_root);
+#if defined(CONFIG_DEBUG_FS)
+       drm_debugfs_cleanup(minor);
+#endif
+
+       drm_sysfs_device_remove(minor);
+
+       idr_remove(&drm_minors_idr, minor->index);
+
+       kfree(minor, M_DRM);
+       *minor_p = NULL;
+       return 0;
 }
+EXPORT_SYMBOL(drm_put_minor);
+#endif
 
-int
-drm_dropmaster_ioctl(struct drm_device *dev, void *data,
-    struct drm_file *file_priv)
+#if 0
+static void drm_unplug_minor(struct drm_minor *minor)
 {
+       drm_sysfs_device_remove(minor);
+}
+
+/**
+ * Called via drm_exit() at module unload time or when pci device is
+ * unplugged.
+ *
+ * Cleans up all DRM device, calling drm_lastclose().
+ *
+ */
+void drm_put_dev(struct drm_device *dev)
+{
+       struct drm_driver *driver;
+       struct drm_map_list *r_list, *list_temp;
+
+       DRM_DEBUG("\n");
+
+       if (!dev) {
+               DRM_ERROR("cleanup called no dev\n");
+               return;
+       }
+       driver = dev->driver;
+
+       drm_lastclose(dev);
+
+       if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
+           dev->agp && dev->agp->agp_mtrr >= 0) {
+               int retval;
+               retval = mtrr_del(dev->agp->agp_mtrr,
+                                 dev->agp->agp_info.aper_base,
+                                 dev->agp->agp_info.aper_size * 1024 * 1024);
+               DRM_DEBUG("mtrr_del=%d\n", retval);
+       }
+
+       if (dev->driver->unload)
+               dev->driver->unload(dev);
+
+       if (drm_core_has_AGP(dev) && dev->agp) {
+               kfree(dev->agp, M_DRM);
+               dev->agp = NULL;
+       }
+
+       drm_vblank_cleanup(dev);
+
+       list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
+               drm_rmmap(dev, r_list->map);
+       drm_ht_remove(&dev->map_hash);
+
+       drm_ctxbitmap_cleanup(dev);
+
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               drm_put_minor(&dev->control);
+
+       if (driver->driver_features & DRIVER_GEM)
+               drm_gem_destroy(dev);
+
+       drm_put_minor(&dev->primary);
+
+       list_del(&dev->driver_item);
+       kfree(dev->devname, M_DRM);
+       kfree(dev, M_DRM);
+}
+EXPORT_SYMBOL(drm_put_dev);
+
+void drm_unplug_dev(struct drm_device *dev)
+{
+       /* for a USB device */
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               drm_unplug_minor(dev->control);
+       drm_unplug_minor(dev->primary);
+
+       mutex_lock(&drm_global_mutex);
+
+       drm_device_set_unplugged(dev);
 
-       DRM_DEBUG("dropmaster\n");
-       if (file_priv->master != 0)
-               return (-EINVAL);
-       return (0);
+       if (dev->open_count == 0) {
+               drm_put_dev(dev);
+       }
+       mutex_unlock(&drm_global_mutex);
 }
+EXPORT_SYMBOL(drm_unplug_dev);
+#endif
index 57fbbb8..f7536b0 100644 (file)
@@ -311,7 +311,7 @@ static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS
                priv = &tempprivs[i];
                DRM_SYSCTL_PRINT("%c %-12s %5d %5d %10u %10lu\n",
                               priv->authenticated ? 'y' : 'n',
-                              devtoname(priv->dev->devnode),
+                              devtoname(priv->minor->dev->devnode),
                               priv->pid,
                               priv->uid,
                               priv->magic,
index c696eea..ad06589 100644 (file)
@@ -72,16 +72,15 @@ intel_read_legacy_status_page(struct drm_i915_private *dev_priv, int reg)
 
 void i915_update_dri1_breadcrumb(struct drm_device *dev)
 {
-       /*
-        * The dri breadcrumb update races against the drm master disappearing.
-        * Instead of trying to fix this (this is by far not the only ums issue)
-        * just don't do the update in kms mode.
-        */
-       if (drm_core_check_feature(dev, DRIVER_MODESET))
-               return;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_master_private *master_priv;
 
-       /* XXX: don't do it at all actually */
-       return;
+       if (dev->primary->master) {
+               master_priv = dev->primary->master->driver_priv;
+               if (master_priv->sarea_priv)
+                       master_priv->sarea_priv->last_dispatch =
+                               READ_BREADCRUMB(dev_priv);
+       }
 }
 
 static void i915_write_hws_pga(struct drm_device *dev)
@@ -123,6 +122,7 @@ static void i915_free_hws(struct drm_device *dev)
 void i915_kernel_lost_context(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_master_private *master_priv;
        struct intel_ring_buffer *ring = LP_RING(dev_priv);
 
        /*
@@ -138,15 +138,12 @@ void i915_kernel_lost_context(struct drm_device * dev)
        if (ring->space < 0)
                ring->space += ring->size;
 
-#if 1
-       KIB_NOTYET();
-#else
        if (!dev->primary->master)
                return;
-#endif
 
-       if (ring->head == ring->tail && dev_priv->sarea_priv)
-               dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
+       master_priv = dev->primary->master->driver_priv;
+       if (ring->head == ring->tail && master_priv->sarea_priv)
+               master_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
 }
 
 static int i915_dma_cleanup(struct drm_device * dev)
@@ -177,18 +174,17 @@ static int i915_dma_cleanup(struct drm_device * dev)
 static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
        int ret;
 
-       dev_priv->sarea = drm_getsarea(dev);
-       if (!dev_priv->sarea) {
-               DRM_ERROR("can not find sarea!\n");
-               i915_dma_cleanup(dev);
-               return -EINVAL;
+       master_priv->sarea = drm_getsarea(dev);
+       if (master_priv->sarea) {
+               master_priv->sarea_priv = (drm_i915_sarea_t *)
+                       ((u8 *)master_priv->sarea->handle + init->sarea_priv_offset);
+       } else {
+               DRM_DEBUG_DRIVER("sarea not found assuming DRI2 userspace\n");
        }
 
-       dev_priv->sarea_priv = (drm_i915_sarea_t *)
-           ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
-
        if (init->ring_size != 0) {
                if (LP_RING(dev_priv)->obj != NULL) {
                        i915_dma_cleanup(dev);
@@ -210,8 +206,8 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
        dev_priv->dri1.back_offset = init->back_offset;
        dev_priv->dri1.front_offset = init->front_offset;
        dev_priv->dri1.current_page = 0;
-       dev_priv->sarea_priv->pf_current_page = 0;
-
+       if (master_priv->sarea_priv)
+               master_priv->sarea_priv->pf_current_page = 0;
 
        /* Allow hardware batchbuffers unless told otherwise.
         */
@@ -421,12 +417,13 @@ i915_emit_box(struct drm_device *dev,
 static void i915_emit_breadcrumb(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
 
        dev_priv->dri1.counter++;
        if (dev_priv->dri1.counter > 0x7FFFFFFFUL)
                dev_priv->dri1.counter = 0;
-       if (dev_priv->sarea_priv)
-               dev_priv->sarea_priv->last_enqueue = dev_priv->dri1.counter;
+       if (master_priv->sarea_priv)
+               master_priv->sarea_priv->last_enqueue = dev_priv->dri1.counter;
 
        if (BEGIN_LP_RING(4) == 0) {
                OUT_RING(MI_STORE_DWORD_INDEX);
@@ -536,15 +533,17 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
 static int i915_dispatch_flip(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_master_private *master_priv =
+               dev->primary->master->driver_priv;
        int ret;
 
-       if (!dev_priv->sarea_priv)
+       if (!master_priv->sarea_priv)
                return -EINVAL;
 
        DRM_DEBUG_DRIVER("%s: page=%d pfCurrentPage=%d\n",
                          __func__,
                         dev_priv->dri1.current_page,
-                        dev_priv->sarea_priv->pf_current_page);
+                        master_priv->sarea_priv->pf_current_page);
 
        i915_kernel_lost_context(dev);
 
@@ -571,7 +570,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
 
        ADVANCE_LP_RING();
 
-       dev_priv->sarea_priv->last_enqueue = dev_priv->dri1.counter++;
+       master_priv->sarea_priv->last_enqueue = dev_priv->dri1.counter++;
 
        if (BEGIN_LP_RING(4) == 0) {
                OUT_RING(MI_STORE_DWORD_INDEX);
@@ -581,7 +580,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
                ADVANCE_LP_RING();
        }
 
-       dev_priv->sarea_priv->pf_current_page = dev_priv->dri1.current_page;
+       master_priv->sarea_priv->pf_current_page = dev_priv->dri1.current_page;
        return 0;
 }
 
@@ -612,7 +611,9 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
                            struct drm_file *file_priv)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)dev_priv->sarea_priv;
+       struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
+       drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+           master_priv->sarea_priv;
        drm_i915_batchbuffer_t *batch = data;
        int ret;
        struct drm_clip_rect *cliprects = NULL;
@@ -665,7 +666,9 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)dev_priv->sarea_priv;
+       struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
+       drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+           master_priv->sarea_priv;
        drm_i915_cmdbuffer_t *cmdbuf = data;
        struct drm_clip_rect *cliprects = NULL;
        void *batch_data;
@@ -686,7 +689,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
        if (batch_data == NULL)
                return -ENOMEM;
 
-       ret = -copyin(cmdbuf->buf, batch_data, cmdbuf->sz);
+       ret = copy_from_user(batch_data, cmdbuf->buf, cmdbuf->sz);
        if (ret != 0) {
                ret = -EFAULT;
                goto fail_batch_free;
@@ -731,9 +734,7 @@ fail_batch_free:
 static int i915_emit_irq(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-#if 0
        struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
-#endif
 
        i915_kernel_lost_context(dev);
 
@@ -742,8 +743,8 @@ static int i915_emit_irq(struct drm_device * dev)
        dev_priv->dri1.counter++;
        if (dev_priv->dri1.counter > 0x7FFFFFFFUL)
                dev_priv->dri1.counter = 1;
-       if (dev_priv->sarea_priv)
-               dev_priv->sarea_priv->last_enqueue = dev_priv->dri1.counter;
+       if (master_priv->sarea_priv)
+               master_priv->sarea_priv->last_enqueue = dev_priv->dri1.counter;
 
        if (BEGIN_LP_RING(4) == 0) {
                OUT_RING(MI_STORE_DWORD_INDEX);
@@ -759,16 +760,13 @@ static int i915_emit_irq(struct drm_device * dev)
 static int i915_wait_irq(struct drm_device * dev, int irq_nr)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-#if 0
        struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
-#endif
        int ret = 0;
        struct intel_ring_buffer *ring = LP_RING(dev_priv);
 
        DRM_DEBUG_DRIVER("irq_nr=%d breadcrumb=%d\n", irq_nr,
                  READ_BREADCRUMB(dev_priv));
 
-#if 0
        if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
                if (master_priv->sarea_priv)
                        master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
@@ -777,18 +775,6 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
 
        if (master_priv->sarea_priv)
                master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-#else
-       if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
-               if (dev_priv->sarea_priv) {
-                       dev_priv->sarea_priv->last_dispatch =
-                               READ_BREADCRUMB(dev_priv);
-               }
-               return 0;
-       }
-
-       if (dev_priv->sarea_priv)
-               dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-#endif
 
        if (ring->irq_get(ring)) {
                DRM_WAIT_ON(ret, ring->irq_queue, 3 * DRM_HZ,
@@ -1051,7 +1037,6 @@ static int i915_setparam(struct drm_device *dev, void *data,
 static int i915_set_status_page(struct drm_device *dev, void *data,
                                struct drm_file *file_priv)
 {
-#if 0  /* We don't care about dri1 */
        drm_i915_private_t *dev_priv = dev->dev_private;
        drm_i915_hws_addr_t *hws = data;
        struct intel_ring_buffer *ring;
@@ -1095,8 +1080,6 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
        DRM_DEBUG_DRIVER("load hws at %p\n",
                         ring->status_page.page_addr);
        return 0;
-#endif
-       return -EINVAL;
 }
 
 static int i915_get_bridge_dev(struct drm_device *dev)
@@ -1176,7 +1159,7 @@ intel_setup_mchbar(struct drm_device *dev)
 
        if (IS_I915G(dev) || IS_I915GM(dev)) {
                pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
-               enabled = (temp & DEVEN_MCHBAR_EN) != 0;
+               enabled = !!(temp & DEVEN_MCHBAR_EN);
        } else {
                pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
                enabled = temp & 1;
@@ -1336,6 +1319,30 @@ out:
        return ret;
 }
 
+int i915_master_create(struct drm_device *dev, struct drm_master *master)
+{
+       struct drm_i915_master_private *master_priv;
+
+       master_priv = kmalloc(sizeof(*master_priv), M_DRM, M_WAITOK | M_ZERO);
+       if (!master_priv)
+               return -ENOMEM;
+
+       master->driver_priv = master_priv;
+       return 0;
+}
+
+void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
+{
+       struct drm_i915_master_private *master_priv = master->driver_priv;
+
+       if (!master_priv)
+               return;
+
+       kfree(master_priv, M_DRM);
+
+       master->driver_priv = NULL;
+}
+
 #if 0
 static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
 {
@@ -1449,7 +1456,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                goto put_gmch;
        }
 
-       aperture_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
+       aperture_size = dev_priv->gtt.mappable_end;
 
        dev_priv->gtt.mappable =
                io_mapping_create_wc(dev_priv->gtt.mappable_base,
@@ -1683,7 +1690,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file)
        struct drm_i915_file_private *file_priv;
 
        DRM_DEBUG_DRIVER("\n");
-       file_priv = kmalloc(sizeof(*file_priv), M_DRM, M_WAITOK | M_ZERO);
+       file_priv = kmalloc(sizeof(*file_priv), M_DRM, M_WAITOK);
        if (!file_priv)
                return -ENOMEM;
 
@@ -1713,16 +1720,22 @@ void i915_driver_lastclose(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
 
-       if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) {
-#if 1
-               KIB_NOTYET();
-#else
-               drm_fb_helper_restore();
+       /* On gen6+ we refuse to init without kms enabled, but then the drm core
+        * goes right around and calls lastclose. Check for this and don't clean
+        * up anything. */
+       if (!dev_priv)
+               return;
+
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+#if 0
+               intel_fb_restore_mode(dev);
                vga_switcheroo_process_delayed_switch();
 #endif
                return;
        }
+
        i915_gem_lastclose(dev);
+
        i915_dma_cleanup(dev);
 }
 
index b8a309a..de61c5d 100644 (file)
@@ -590,6 +590,7 @@ static int
 i915_attach(device_t kdev)
 {
        struct drm_device *dev;
+       int ret;
 
        dev = device_get_softc(kdev);
 
@@ -599,6 +600,17 @@ i915_attach(device_t kdev)
                driver.driver_features |= DRIVER_MODESET;
 
        dev->driver = &driver;
+
+       /* XXX shoud be in drm_get_pci_dev() */
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+               ret = drm_get_minor(kdev, dev, &dev->control, DRM_MINOR_CONTROL);
+               if (ret)
+                       return -ENODEV;
+       }
+
+       if ((ret = drm_get_minor(kdev, dev, &dev->primary, DRM_MINOR_LEGACY)))
+               return -ENODEV;
+
        return (drm_attach(kdev, i915_attach_list));
 }
 
@@ -909,25 +921,30 @@ i915_pci_probe(device_t kdev)
 }
 
 static struct drm_driver driver = {
-       .driver_features =   DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
-           DRIVER_USE_MTRR | DRIVER_HAVE_IRQ | DRIVER_LOCKLESS_IRQ |
-           DRIVER_GEM /*| DRIVER_MODESET*/,
-
-       .buf_priv_size  = sizeof(drm_i915_private_t),
+       /* Don't use MTRRs here; the Xserver or userspace app should
+        * deal with them for Intel hardware.
+        */
+       .driver_features =
+           DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
+           DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM,
        .load           = i915_driver_load,
-       .open           = i915_driver_open,
        .unload         = i915_driver_unload,
-       .preclose       = i915_driver_preclose,
+       .open           = i915_driver_open,
        .lastclose      = i915_driver_lastclose,
+       .preclose       = i915_driver_preclose,
        .postclose      = i915_driver_postclose,
+
        .device_is_agp  = i915_driver_device_is_agp,
+       .master_create = i915_master_create,
+       .master_destroy = i915_master_destroy,
+
        .gem_init_object = i915_gem_init_object,
        .gem_free_object = i915_gem_free_object,
        .gem_pager_ops  = &i915_gem_pager_ops,
+
        .dumb_create    = i915_gem_dumb_create,
        .dumb_map_offset = i915_gem_mmap_gtt,
        .dumb_destroy   = i915_gem_dumb_destroy,
-
        .ioctls         = i915_ioctls,
 
        .name           = DRIVER_NAME,
index 63a3be9..e1a740a 100644 (file)
@@ -2251,43 +2251,24 @@ intel_finish_fb(struct drm_framebuffer *old_fb)
 static void intel_crtc_update_sarea_pos(struct drm_crtc *crtc, int x, int y)
 {
        struct drm_device *dev = crtc->dev;
-#if 0
        struct drm_i915_master_private *master_priv;
-#else
-       drm_i915_private_t *dev_priv = dev->dev_private;
-#endif
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-#if 0
        if (!dev->primary->master)
                return;
 
        master_priv = dev->primary->master->driver_priv;
        if (!master_priv->sarea_priv)
                return;
-#else
-       if (!dev_priv->sarea_priv)
-               return;
-#endif
 
        switch (intel_crtc->pipe) {
        case 0:
-#if 0
                master_priv->sarea_priv->pipeA_x = x;
                master_priv->sarea_priv->pipeA_y = y;
-#else
-               dev_priv->sarea_priv->planeA_x = x;
-               dev_priv->sarea_priv->planeA_y = y;
-#endif
                break;
        case 1:
-#if 0
                master_priv->sarea_priv->pipeB_x = x;
                master_priv->sarea_priv->pipeB_y = y;
-#else
-               dev_priv->sarea_priv->planeB_x = x;
-               dev_priv->sarea_priv->planeB_y = y;
-#endif
                break;
        default:
                break;
@@ -3731,43 +3712,25 @@ static void intel_crtc_update_sarea(struct drm_crtc *crtc,
                                    bool enabled)
 {
        struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-#if 0
        struct drm_i915_master_private *master_priv;
-#endif
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
 
-#if 0
        if (!dev->primary->master)
                return;
 
        master_priv = dev->primary->master->driver_priv;
        if (!master_priv->sarea_priv)
                return;
-#else
-       if (!dev_priv->sarea_priv)
-               return;
-#endif
 
        switch (pipe) {
        case 0:
-#if 0
                master_priv->sarea_priv->pipeA_w = enabled ? crtc->mode.hdisplay : 0;
                master_priv->sarea_priv->pipeA_h = enabled ? crtc->mode.vdisplay : 0;
-#else
-               dev_priv->sarea_priv->planeA_w = enabled ? crtc->mode.hdisplay : 0;
-               dev_priv->sarea_priv->planeA_h = enabled ? crtc->mode.vdisplay : 0;
-#endif
                break;
        case 1:
-#if 0
                master_priv->sarea_priv->pipeB_w = enabled ? crtc->mode.hdisplay : 0;
                master_priv->sarea_priv->pipeB_h = enabled ? crtc->mode.vdisplay : 0;
-#else
-               dev_priv->sarea_priv->planeB_w = enabled ? crtc->mode.hdisplay : 0;
-               dev_priv->sarea_priv->planeB_h = enabled ? crtc->mode.vdisplay : 0;
-#endif
                break;
        default:
                DRM_ERROR("Can't update pipe %c in SAREA\n", pipe_name(pipe));
@@ -9297,6 +9260,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
        intel_unregister_dsm_handler();
 #endif
 
+
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                /* Skip inactive CRTCs */
                if (!crtc->fb)
index d0578c3..5116712 100644 (file)
@@ -127,6 +127,39 @@ struct drm_device;
 #define DRM_UT_DRIVER          0x02
 #define DRM_UT_KMS             0x04
 #define DRM_UT_PRIME           0x08
+/*
+ * Three debug levels are defined.
+ * drm_core, drm_driver, drm_kms
+ * drm_core level can be used in the generic drm code. For example:
+ *     drm_ioctl, drm_mm, drm_memory
+ * The macro definition of DRM_DEBUG is used.
+ *     DRM_DEBUG(fmt, args...)
+ *     The debug info by using the DRM_DEBUG can be obtained by adding
+ *     the boot option of "drm.debug=1".
+ *
+ * drm_driver level can be used in the specific drm driver. It is used
+ * to add the debug info related with the drm driver. For example:
+ * i915_drv, i915_dma, i915_gem, radeon_drv,
+ *     The macro definition of DRM_DEBUG_DRIVER can be used.
+ *     DRM_DEBUG_DRIVER(fmt, args...)
+ *     The debug info by using the DRM_DEBUG_DRIVER can be obtained by
+ *     adding the boot option of "drm.debug=0x02"
+ *
+ * drm_kms level can be used in the KMS code related with specific drm driver.
+ * It is used to add the debug info related with KMS mode. For example:
+ * the connector/crtc ,
+ *     The macro definition of DRM_DEBUG_KMS can be used.
+ *     DRM_DEBUG_KMS(fmt, args...)
+ *     The debug info by using the DRM_DEBUG_KMS can be obtained by
+ *     adding the boot option of "drm.debug=0x04"
+ *
+ * If we add the boot option of "drm.debug=0x06", we can get the debug info by
+ * using the DRM_DEBUG_KMS and DRM_DEBUG_DRIVER.
+ * If we add the boot option of "drm.debug=0x05", we can get the debug info by
+ * using the DRM_DEBUG_KMS and DRM_DEBUG.
+ */
+
+int drm_err(const char *func, const char *format, ...);
 
 #include "opt_drm.h"
 #ifdef DRM_DEBUG
@@ -138,9 +171,6 @@ struct drm_device;
 #define        DRM_DEBUGBITS_KMS               0x2
 #define        DRM_DEBUGBITS_FAILED_IOCTL      0x4
 
-#undef DRM_LINUX
-#define DRM_LINUX 0
-
 /***********************************************************************/
 /** \name DRM template customization defaults */
 /*@{*/
@@ -167,7 +197,7 @@ struct drm_device;
 /** \name Begin the DRM... */
 /*@{*/
 
-#define DRM_HASH_SIZE        16 /* Size of key hash table                */
+#define DRM_MAGIC_HASH_ORDER  4  /**< Size of key hash table. Must be power of 2. */
 #define DRM_KERNEL_CONTEXT    0         /* Change drm_resctx if changed          */
 #define DRM_RESERVED_CONTEXTS 1         /* Change drm_resctx if changed          */
 
@@ -267,14 +297,21 @@ enum {
        (_map) = (_dev)->context_sareas[_ctx];          \
 } while(0)
 
-#define LOCK_TEST_WITH_RETURN(dev, file_priv)                          \
-do {                                                                   \
-       if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ||              \
-            dev->lock.file_priv != file_priv) {                        \
-               DRM_ERROR("%s called without lock held\n",              \
-                          __FUNCTION__);                               \
-               return EINVAL;                                          \
-       }                                                               \
+/**
+ * Test that the hardware lock is held by the caller, returning otherwise.
+ *
+ * \param dev DRM device.
+ * \param filp file pointer of the caller.
+ */
+#define LOCK_TEST_WITH_RETURN( dev, _file_priv )                               \
+do {                                                                           \
+       if (!_DRM_LOCK_IS_HELD(_file_priv->master->lock.hw_lock->lock) ||       \
+           _file_priv->master->lock.file_priv != _file_priv)   {               \
+               DRM_ERROR( "%s called without lock held, held  %d owner %p %p\n",\
+                          __func__, _DRM_LOCK_IS_HELD(_file_priv->master->lock.hw_lock->lock),\
+                          _file_priv->master->lock.file_priv, _file_priv);     \
+               return -EINVAL;                                                 \
+       }                                                                       \
 } while (0)
 
 /* Returns -errno to shared code */
@@ -382,11 +419,11 @@ typedef struct drm_ioctl_desc {
 #define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags)                        \
        [DRM_IOCTL_NR(DRM_##ioctl)] = {.cmd = DRM_##ioctl, .func = _func, .flags = _flags, .cmd_drv = DRM_IOCTL_##ioctl}
 
-typedef struct drm_magic_entry {
-       drm_magic_t            magic;
-       struct drm_file        *priv;
-       struct drm_magic_entry *next;
-} drm_magic_entry_t;
+struct drm_magic_entry {
+       struct list_head head;
+       struct drm_hash_item hash_item;
+       struct drm_file *priv;
+};
 
 typedef struct drm_magic_head {
        struct drm_magic_entry *head;
@@ -469,13 +506,13 @@ struct drm_prime_file_private {
 /** File private data */
 struct drm_file {
        int authenticated;
-       struct drm_device *dev;
-       int               master;
        pid_t             pid;
        uid_t             uid;
-       drm_magic_t       magic;
-       unsigned long     ioctl_count;
+       drm_magic_t magic;
+       unsigned long ioctl_count;
        struct list_head lhead;
+       struct drm_minor *minor;
+       unsigned long lock_count;
        struct kqinfo     dkq;
 
        /** Mapping of mm object handles to object pointers. */
@@ -483,16 +520,25 @@ struct drm_file {
        /** Lock for synchronization of access to object_idr. */
        struct lock table_lock;
 
-       void             *driver_priv;
+       struct file *filp;
+       void *driver_priv;
 
-       int               is_master;
-       struct drm_master *masterp;
+       int is_master; /* this file private is a master for a minor */
+       struct drm_master *master; /* master this node is currently associated with
+                                     N.B. not always minor->master */
 
-       struct list_head  fbs;
+       /**
+        * fbs - List of framebuffers associated with this file.
+        *
+        * Protected by fbs_lock. Note that the fbs list holds a reference on
+        * the fb object to prevent it from untimely disappearing.
+        */
+       struct list_head fbs;
+       struct lock fbs_lock;
 
        wait_queue_head_t event_wait;
-       struct list_head  event_list;
-       int               event_space;
+       struct list_head event_list;
+       int event_space;
 
        struct drm_prime_file_private prime;
 };
@@ -506,15 +552,14 @@ struct drm_lock_data {
        struct drm_file *file_priv;
        wait_queue_head_t lock_queue;   /**< Queue of blocked processes */
        unsigned long lock_time;        /**< Time of last lock in jiffies */
+       struct spinlock spinlock;
+       uint32_t kernel_waiters;
+       uint32_t user_waiters;
+       int idle_has_lock;
 };
 
-/* This structure, in the struct drm_device, is always initialized while the
- * device
- * is open.  dev->dma_lock protects the incrementing of dev->buf_use, which
- * when set marks that no further bufs may be allocated until device teardown
- * occurs (when the last open of the device has closed).  The high/low
- * watermarks of bufs are only touched by the X Server, and thus not
- * concurrently accessed, so no locking is needed.
+/**
+ * DMA data.
  */
 typedef struct drm_device_dma {
 
@@ -562,6 +607,12 @@ typedef struct drm_sg_mem {
        vm_pindex_t pages;
 } drm_sg_mem_t;
 
+struct drm_sigdata {
+       int context;
+       struct drm_hw_lock *lock;
+};
+
+
 /**
  * Kernel side of a mapping
  */
@@ -589,6 +640,15 @@ struct drm_map_list {
        struct drm_mm_node *file_offset_node;   /**< fake offset */
 };
 
+/**
+ * Context handle list
+ */
+struct drm_ctx_list {
+       struct list_head head;          /**< list head */
+       drm_context_t handle;           /**< context handle */
+       struct drm_file *tag;           /**< associated fd private data */
+};
+
 struct drm_vblank_info {
        wait_queue_head_t queue;        /* vblank wait queue */
        atomic_t count;                 /* number of VBLANK interrupts */
@@ -774,6 +834,28 @@ struct drm_driver {
                    int *max_error, struct timeval *vblank_time,
                    unsigned flags);
 
+       /* Master routines */
+       int (*master_create)(struct drm_device *dev, struct drm_master *master);
+       void (*master_destroy)(struct drm_device *dev, struct drm_master *master);
+       /**
+        * master_set is called whenever the minor master is set.
+        * master_drop is called whenever the minor master is dropped.
+        */
+
+       int (*master_set)(struct drm_device *dev, struct drm_file *file_priv,
+                         bool from_open);
+       void (*master_drop)(struct drm_device *dev, struct drm_file *file_priv,
+                           bool from_release);
+
+       int (*debugfs_init)(struct drm_minor *minor);
+       void (*debugfs_cleanup)(struct drm_minor *minor);
+
+       /**
+        * Driver-specific constructor for drm_gem_objects, to set up
+        * obj->driver_private.
+        *
+        * Returns 0 on success.
+        */
        int     (*gem_init_object)(struct drm_gem_object *obj);
        void    (*gem_free_object)(struct drm_gem_object *obj);
        int     (*gem_open_object)(struct drm_gem_object *, struct drm_file *);
@@ -826,12 +908,19 @@ struct drm_driver {
        int num_ioctls;
 };
 
+#define DRM_MINOR_UNASSIGNED 0
+#define DRM_MINOR_LEGACY 1
+#define DRM_MINOR_CONTROL 2
+#define DRM_MINOR_RENDER 3
+
+
 /**
  * DRM minor structure. This structure represents a drm minor number.
  */
 struct drm_minor {
        int index;                      /**< Minor device number */
        int type;                       /**< Control or render */
+       cdev_t device;                  /**< Device number for mknod */
        device_t kdev;                  /**< OS device */
        struct drm_device *dev;
 
@@ -870,6 +959,8 @@ struct drm_sysctl_info {
 /* Length for the array of resource pointers for drm_get_resource_*. */
 #define DRM_MAX_PCI_RESOURCE   6
 
+typedef unsigned long long cycles_t;
+
 /**
  * DRM device structure. This structure represent a complete card that
  * may contain multiple heads.
@@ -899,11 +990,13 @@ struct drm_device {
 
        /** \name Usage Counters */
        /*@{ */
-       int               open_count;   /* Outstanding files open          */
-       int               buf_use;      /* Buffers in use -- cannot alloc  */
+       int open_count;                 /**< Outstanding files open */
+       atomic_t ioctl_count;           /**< Outstanding IOCTLs pending */
+       atomic_t vma_count;             /**< Outstanding vma areas open */
+       int buf_use;                    /**< Buffers in use -- cannot alloc */
+       atomic_t buf_alloc;             /**< Buffer allocation in progress */
        /*@} */
 
-
        /** \name Performance counters */
        /*@{ */
        unsigned long     counters;
@@ -911,9 +1004,6 @@ struct drm_device {
        atomic_t          counts[15];
        /*@} */
 
-                               /* Authentication */
-       drm_magic_head_t  magiclist[DRM_HASH_SIZE];
-
        struct list_head filelist;
 
        /** \name Memory management */
@@ -922,21 +1012,37 @@ struct drm_device {
        int map_count;                  /**< Number of mappable regions */
        struct drm_open_hash map_hash;  /**< User token hash table for maps */
 
-       drm_local_map_t   **context_sareas;
-       int               max_context;
+       /** \name Context handle management */
+       /*@{ */
+       struct list_head ctxlist;       /**< Linked list of context handles */
+       int ctx_count;                  /**< Number of context handles */
+       struct lock ctxlist_mutex;      /**< For ctxlist */
 
-       struct drm_lock_data lock;      /* Information on hardware lock    */
+       struct idr ctx_idr;
 
-                               /* DMA queues (contexts) */
-       drm_device_dma_t  *dma;         /* Optional pointer for DMA support */
+       /** \name DMA support */
+       /*@{ */
+       struct drm_device_dma *dma;             /**< Optional pointer for DMA support */
+       /*@} */
 
-                               /* Context support */
        int               irq;          /* Interrupt used by board         */
        int               msi_enabled;  /* MSI enabled */
        int               irqrid;       /* Interrupt used by board */
        struct resource   *irqr;        /* Resource for interrupt used by board    */
        void              *irqh;        /* Handle from bus_setup_intr      */
 
+       /** \name Context support */
+       /*@{ */
+       int irq_enabled;                /**< True if irq handler is enabled */
+       __volatile__ long context_flag; /**< Context swapping flag */
+       __volatile__ long interrupt_flag; /**< Interruption handler flag */
+       __volatile__ long dma_flag;     /**< DMA dispatch flag */
+       wait_queue_head_t context_wait; /**< Processes waiting on ctx switch */
+       int last_checked;               /**< Last context checked for DMA */
+       int last_context;               /**< Last current context */
+       unsigned long last_switch;      /**< jiffies at last context switch */
+       /*@} */
+
        /* Storage of resource pointers for drm_get_resource_* */
        struct resource   *pcir[DRM_MAX_PCI_RESOURCE];
        int               pcirid[DRM_MAX_PCI_RESOURCE];
@@ -946,13 +1052,6 @@ struct drm_device {
        int               pci_slot;
        int               pci_func;
 
-       /** \name Context support */
-       /*@{ */
-       int irq_enabled;                /**< True if irq handler is enabled */
-       __volatile__ long context_flag; /**< Context swapping flag */
-       int last_context;               /**< Last current context */
-       /*@} */
-
        int               num_crtcs;
 
        struct sigio      *buf_sigio;   /* Processes waiting for SIGIO     */
@@ -999,6 +1098,12 @@ struct drm_device {
        struct lock     event_lock;
 
        /*@} */
+       cycles_t ctx_start;
+       cycles_t lck_start;
+
+       struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */
+       wait_queue_head_t buf_readers;  /**< Processes waiting to read */
+       wait_queue_head_t buf_writers;  /**< Processes waiting to ctx switch */
 
        struct drm_agp_head *agp;       /**< AGP data */
 
@@ -1006,6 +1111,7 @@ struct drm_device {
        struct pci_dev *pdev;           /**< PCI device structure */
        int pci_vendor;                 /**< PCI vendor id */
        int pci_device;                 /**< PCI device id */
+       struct drm_sigdata sigdata;        /**< For block_all_signals */
 
        struct drm_driver *driver;
        struct drm_local_map *agp_buffer_map;
@@ -1085,7 +1191,7 @@ struct dmi_system_id {
 bool dmi_check_system(const struct dmi_system_id *);
 
 extern int     drm_notyet_flag;
-extern int     drm_debug;
+extern unsigned int drm_debug;
 
 extern unsigned int drm_vblank_offdelay;
 extern unsigned int drm_timestamp_precision;
@@ -1108,6 +1214,9 @@ int drm_release(device_t kdev);
 
 d_mmap_t drm_mmap;
 d_mmap_single_t drm_mmap_single;
+
+extern struct idr drm_minors_idr;
+
 extern drm_local_map_t *drm_getsarea(struct drm_device *dev);
 
 void drm_cdevpriv_dtor(void *cd);
@@ -1118,10 +1227,6 @@ int drm_add_busid_modesetting(struct drm_device *dev,
     struct sysctl_ctx_list *ctx, struct sysctl_oid *top);
 
 /* File operations helpers (drm_fops.c) */
-extern int             drm_open_helper(struct cdev *kdev, int flags, int fmt,
-                                        DRM_STRUCTPROC *p,
-                                       struct drm_device *dev,
-                                       struct file *fp);
 extern struct drm_file *drm_find_file_by_proc(struct drm_device *dev,
                                        DRM_STRUCTPROC *p);
 
@@ -1172,7 +1277,6 @@ int       drm_mtrr_del(int handle, unsigned long offset, size_t size, int flags);
 int    drm_ctxbitmap_init(struct drm_device *dev);
 void   drm_ctxbitmap_cleanup(struct drm_device *dev);
 void   drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
-int    drm_ctxbitmap_next(struct drm_device *dev);
 
 /* Locking IOCTL support (drm_lock.c) */
 int    drm_lock_take(struct drm_lock_data *lock_data,
@@ -1191,13 +1295,28 @@ unsigned long drm_get_resource_start(struct drm_device *dev,
                                     unsigned int resource);
 unsigned long drm_get_resource_len(struct drm_device *dev,
                                   unsigned int resource);
-void   drm_rmmap(struct drm_device *dev, drm_local_map_t *map);
-int    drm_order(unsigned long size);
 int    drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *request);
 int    drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc *request);
 extern int drm_addmap(struct drm_device *dev, resource_size_t offset,
                      unsigned int size, enum drm_map_type type,
                      enum drm_map_flags flags, struct drm_local_map **map_ptr);
+extern int drm_addmap_ioctl(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv);
+extern int drm_rmmap(struct drm_device *dev, struct drm_local_map *map);
+extern int drm_rmmap_locked(struct drm_device *dev, struct drm_local_map *map);
+extern int drm_rmmap_ioctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+extern int drm_addbufs(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv);
+extern int drm_infobufs(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_markbufs(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_freebufs(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_mapbufs(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv);
+extern int drm_order(unsigned long size);
 
 /* DMA support (drm_dma.c) */
 int    drm_dma_setup(struct drm_device *dev);
@@ -1324,27 +1443,12 @@ int     drm_setsareactx(struct drm_device *dev, void *data,
 int    drm_getsareactx(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
 
-/* Authentication IOCTL support (drm_auth.c) */
-int    drm_getmagic(struct drm_device *dev, void *data,
-                    struct drm_file *file_priv);
-int    drm_authmagic(struct drm_device *dev, void *data,
-                     struct drm_file *file_priv);
-
-/* Buffer management support (drm_bufs.c) */
-int    drm_addmap_ioctl(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-int    drm_rmmap_ioctl(struct drm_device *dev, void *data,
+                               /* Authentication IOCTL support (drm_auth.h) */
+extern int drm_getmagic(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
-int    drm_addbufs(struct drm_device *dev, void *data,
-                   struct drm_file *file_priv);
-int    drm_infobufs(struct drm_device *dev, void *data,
-                    struct drm_file *file_priv);
-int    drm_markbufs(struct drm_device *dev, void *data,
-                    struct drm_file *file_priv);
-int    drm_freebufs(struct drm_device *dev, void *data,
-                    struct drm_file *file_priv);
-int    drm_mapbufs(struct drm_device *dev, void *data,
-                   struct drm_file *file_priv);
+extern int drm_authmagic(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int drm_remove_magic(struct drm_master *master, drm_magic_t magic);
 
 /* DMA support (drm_dma.c) */
 int    drm_dma(struct drm_device *dev, void *data, struct drm_file *file_priv);
@@ -1376,6 +1480,9 @@ extern int drm_setmaster_ioctl(struct drm_device *dev, void *data,
                               struct drm_file *file_priv);
 extern int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
                                struct drm_file *file_priv);
+struct drm_master *drm_master_create(struct drm_minor *minor);
+extern struct drm_master *drm_master_get(struct drm_master *master);
+extern void drm_master_put(struct drm_master **master);
 
 /* Scatter Gather Support (drm_scatter.c) */
 int    drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
@@ -1595,6 +1702,8 @@ static __inline__ void drm_core_dropmap(struct drm_map *map)
 
 #include <drm/drm_mem_util.h>
 
+int drm_get_minor(device_t, struct drm_device *dev, struct drm_minor **minor, int type);
+
 /* FreeBSD compatibility macros */
 #define VM_OBJECT_WLOCK(object)                VM_OBJECT_LOCK(object)
 #define VM_OBJECT_WUNLOCK(object)      VM_OBJECT_UNLOCK(object)
index 522375d..e3b4535 100644 (file)
@@ -1012,7 +1012,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
                      drm_radeon_kcmd_buffer_t *cmdbuf)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+       struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
        struct drm_device_dma *dma = dev->dma;
        struct drm_buf *buf = NULL;
        int emit_dispatch_age = 0;
@@ -1119,7 +1119,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
                        }
 
                        emit_dispatch_age = 1;
-                       r300_discard_buffer(dev, file_priv->masterp, buf);
+                       r300_discard_buffer(dev, file_priv->master, buf);
                        break;
 
                case R300_CMD_WAIT:
index 943bb3a..8a0ab04 100644 (file)
@@ -538,7 +538,7 @@ static void r600_nomm_put_vb(struct drm_device *dev)
        drm_radeon_private_t *dev_priv = dev->dev_private;
 
        dev_priv->blit_vb->used = 0;
-       radeon_cp_discard_buffer(dev, dev_priv->blit_vb->file_priv->masterp, dev_priv->blit_vb);
+       radeon_cp_discard_buffer(dev, dev_priv->blit_vb->file_priv->master, dev_priv->blit_vb);
 }
 
 static void *r600_nomm_get_vb_ptr(struct drm_device *dev)
index a7fe4b6..64e0c32 100644 (file)
@@ -1906,7 +1906,7 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
        RADEON_WRITE(R600_LAST_CLEAR_REG, 0);
 
        /* reset sarea copies of these */
-       master_priv = file_priv->masterp->driver_priv;
+       master_priv = file_priv->master->driver_priv;
        if (master_priv->sarea_priv) {
                master_priv->sarea_priv->last_frame = 0;
                master_priv->sarea_priv->last_dispatch = 0;
@@ -1965,7 +1965,7 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
                    struct drm_file *file_priv)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+       struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
 
        DRM_DEBUG("\n");
 
@@ -2401,7 +2401,7 @@ int r600_cp_dispatch_indirect(struct drm_device *dev,
 void r600_cp_dispatch_swap(struct drm_device *dev, struct drm_file *file_priv)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_master *master = file_priv->masterp;
+       struct drm_master *master = file_priv->master;
        struct drm_radeon_master_private *master_priv = master->driver_priv;
        drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
        int nbox = sarea_priv->nbox;
@@ -2523,7 +2523,7 @@ int r600_cp_dispatch_texture(struct drm_device *dev,
 
                r600_blit_copy(dev, src_offset, dst_offset, pass_size);
 
-               radeon_cp_discard_buffer(dev, file_priv->masterp, buf);
+               radeon_cp_discard_buffer(dev, file_priv->master, buf);
 
                /* Update the input parameters for next time */
                image->data = (const u8 __user *)image->data + pass_size;
@@ -2588,7 +2588,7 @@ static void r600_ib_free(struct drm_device *dev, struct drm_buf *buf,
        if (buf) {
                if (!r)
                        r600_cp_dispatch_indirect(dev, buf, 0, l * 4);
-               radeon_cp_discard_buffer(dev, fpriv->masterp, buf);
+               radeon_cp_discard_buffer(dev, fpriv->master, buf);
                COMMIT_RING();
        }
 }
index 92075f2..c4fffc0 100644 (file)
@@ -833,7 +833,7 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
        RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0);
 
        /* reset sarea copies of these */
-       master_priv = file_priv->masterp->driver_priv;
+       master_priv = file_priv->master->driver_priv;
        if (master_priv->sarea_priv) {
                master_priv->sarea_priv->last_frame = 0;
                master_priv->sarea_priv->last_dispatch = 0;
@@ -1162,7 +1162,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
                             struct drm_file *file_priv)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+       struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
 
        DRM_DEBUG("\n");
 
index 8f7d2f2..42c2e99 100644 (file)
@@ -2003,7 +2003,7 @@ do {                                                                      \
 
 #define VB_AGE_TEST_WITH_RETURN( dev_priv )                            \
 do {                                                           \
-       struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;\
+       struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;\
        drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;       \
        if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) {         \
                int __ret;                                              \
index 888bd1a..151b89c 100644 (file)
@@ -1533,7 +1533,7 @@ static void radeon_cp_dispatch_vertex(struct drm_device * dev,
                                      drm_radeon_tcl_prim_t * prim)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+       struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
        drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
        int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start;
        int numverts = (int)prim->numverts;
@@ -1915,7 +1915,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev,
                ADVANCE_RING();
                COMMIT_RING();
 
-               radeon_cp_discard_buffer(dev, file_priv->masterp, buf);
+               radeon_cp_discard_buffer(dev, file_priv->master, buf);
 
                /* Update the input parameters for next time */
                image->y += height;
@@ -2155,7 +2155,7 @@ static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_fi
 static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+       struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
        drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
        drm_radeon_clear_t *clear = data;
        drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
@@ -2172,7 +2172,7 @@ static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *
                               sarea_priv->nbox * sizeof(depth_boxes[0])))
                return -EFAULT;
 
-       radeon_cp_dispatch_clear(dev, file_priv->masterp, clear, depth_boxes);
+       radeon_cp_dispatch_clear(dev, file_priv->master, clear, depth_boxes);
 
        COMMIT_RING();
        return 0;
@@ -2219,9 +2219,9 @@ static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *f
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
 
        if (!dev_priv->page_flipping)
-               radeon_do_init_pageflip(dev, file_priv->masterp);
+               radeon_do_init_pageflip(dev, file_priv->master);
 
-       radeon_cp_dispatch_flip(dev, file_priv->masterp);
+       radeon_cp_dispatch_flip(dev, file_priv->master);
 
        COMMIT_RING();
        return 0;
@@ -2230,7 +2230,7 @@ static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *f
 static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+       struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
        drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
 
        DRM_DEBUG("\n");
@@ -2245,7 +2245,7 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f
        if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
                r600_cp_dispatch_swap(dev, file_priv);
        else
-               radeon_cp_dispatch_swap(dev, file_priv->masterp);
+               radeon_cp_dispatch_swap(dev, file_priv->master);
        sarea_priv->ctx_owner = 0;
 
        COMMIT_RING();
@@ -2255,7 +2255,7 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f
 static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+       struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
        drm_radeon_sarea_t *sarea_priv;
        struct drm_device_dma *dma = dev->dma;
        struct drm_buf *buf;
@@ -2324,7 +2324,7 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file
        }
 
        if (vertex->discard) {
-               radeon_cp_discard_buffer(dev, file_priv->masterp, buf);
+               radeon_cp_discard_buffer(dev, file_priv->master, buf);
        }
 
        COMMIT_RING();
@@ -2334,7 +2334,7 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file
 static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+       struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
        drm_radeon_sarea_t *sarea_priv;
        struct drm_device_dma *dma = dev->dma;
        struct drm_buf *buf;
@@ -2413,9 +2413,9 @@ static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file
        prim.numverts = RADEON_MAX_VB_VERTS;    /* duh */
        prim.vc_format = sarea_priv->vc_format;
 
-       radeon_cp_dispatch_indices(dev, file_priv->masterp, buf, &prim);
+       radeon_cp_dispatch_indices(dev, file_priv->master, buf, &prim);
        if (elts->discard) {
-               radeon_cp_discard_buffer(dev, file_priv->masterp, buf);
+               radeon_cp_discard_buffer(dev, file_priv->master, buf);
        }
 
        COMMIT_RING();
@@ -2531,7 +2531,7 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil
        }
 
        if (indirect->discard) {
-               radeon_cp_discard_buffer(dev, file_priv->masterp, buf);
+               radeon_cp_discard_buffer(dev, file_priv->master, buf);
        }
 
        COMMIT_RING();
@@ -2541,7 +2541,7 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil
 static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+       struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
        drm_radeon_sarea_t *sarea_priv;
        struct drm_device_dma *dma = dev->dma;
        struct drm_buf *buf;
@@ -2613,7 +2613,7 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file
                        tclprim.offset = prim.numverts * 64;
                        tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
 
-                       radeon_cp_dispatch_indices(dev, file_priv->masterp, buf, &tclprim);
+                       radeon_cp_dispatch_indices(dev, file_priv->master, buf, &tclprim);
                } else {
                        tclprim.numverts = prim.numverts;
                        tclprim.offset = 0;     /* not used */
@@ -2626,7 +2626,7 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file
        }
 
        if (vertex->discard) {
-               radeon_cp_discard_buffer(dev, file_priv->masterp, buf);
+               radeon_cp_discard_buffer(dev, file_priv->master, buf);
        }
 
        COMMIT_RING();
@@ -2964,7 +2964,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data,
                                goto err;
                        }
 
-                       radeon_cp_discard_buffer(dev, file_priv->masterp, buf);
+                       radeon_cp_discard_buffer(dev, file_priv->master, buf);
                        break;
 
                case RADEON_CMD_PACKET3:
@@ -3127,7 +3127,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil
 static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+       struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
        drm_radeon_setparam_t *sp = data;
        struct drm_radeon_driver_file_fields *radeon_priv;
 
index f401bff..3e2a216 100644 (file)
@@ -123,6 +123,7 @@ struct file {
        struct nchandle f_nchandle; /* namecache reference */
        struct spinlock f_spin; /* NOT USED */
        struct klist    f_klist;/* knotes attached to fp/kq */
+       void    *private_data;  /* Linux per-file data */
 };
 
 #define        DTYPE_VNODE     1       /* file */