From 2aa08105f11f5815d087c0f6baea9af394bd323f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Tigeot?= Date: Sat, 10 Jan 2015 21:06:46 +0100 Subject: [PATCH] drm: Handle drm masters and minors like Linux * 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. --- sys/dev/drm/drm_auth.c | 215 ++++++------ sys/dev/drm/drm_bufs.c | 74 +++-- sys/dev/drm/drm_context.c | 377 ++++++++++++++-------- sys/dev/drm/drm_crtc.c | 22 +- sys/dev/drm/drm_drv.c | 175 ++-------- sys/dev/drm/drm_fops.c | 267 +++++++++------ sys/dev/drm/drm_ioctl.c | 2 +- sys/dev/drm/drm_lock.c | 16 +- sys/dev/drm/drm_stub.c | 520 +++++++++++++++++++++++++++++- sys/dev/drm/drm_sysctl.c | 2 +- sys/dev/drm/i915/i915_dma.c | 141 ++++---- sys/dev/drm/i915/i915_drv.c | 33 +- sys/dev/drm/i915/intel_display.c | 38 +-- sys/dev/drm/include/drm/drmP.h | 271 +++++++++++----- sys/dev/drm/radeon/r300_cmdbuf.c | 4 +- sys/dev/drm/radeon/r600_blit.c | 2 +- sys/dev/drm/radeon/r600_cp.c | 10 +- sys/dev/drm/radeon/radeon_cp.c | 4 +- sys/dev/drm/radeon/radeon_drv.h | 2 +- sys/dev/drm/radeon/radeon_state.c | 38 +-- sys/sys/file.h | 1 + 21 files changed, 1444 insertions(+), 770 deletions(-) diff --git a/sys/dev/drm/drm_auth.c b/sys/dev/drm/drm_auth.c index dd8c833e3a..a1042f20a6 100644 --- a/sys/dev/drm/drm_auth.c +++ b/sys/dev/drm/drm_auth.c @@ -1,4 +1,14 @@ -/*- +/** + * \file drm_auth.c + * IOCTLs for authentication + * + * \author Rickard E. (Rik) Faith + * \author Gareth Hughes + */ + +/* + * 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. @@ -21,141 +31,134 @@ * 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 - * Gareth Hughes - * - * $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 -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; } diff --git a/sys/dev/drm/drm_bufs.c b/sys/dev/drm/drm_bufs.c index ef4576695d..ce9b2cfd7e 100644 --- a/sys/dev/drm/drm_bufs.c +++ b/sys/dev/drm/drm_bufs.c @@ -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 diff --git a/sys/dev/drm/drm_context.c b/sys/dev/drm/drm_context.c index a590de2b63..3ed10b1d9f 100644 --- a/sys/dev/drm/drm_context.c +++ b/sys/dev/drm/drm_context.c @@ -1,4 +1,14 @@ -/*- +/** + * \file drm_context.c + * IOCTLs for generic contexts + * + * \author Rickard E. (Rik) Faith + * \author Gareth Hughes + */ + +/* + * 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. @@ -21,131 +31,143 @@ * 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 - * Gareth Hughes - * - * $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 + * added context constructor/destructor hooks, + * needed by SiS driver's memory management. */ #include -/* ================================================================ - * 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; } + +/*@}*/ diff --git a/sys/dev/drm/drm_crtc.c b/sys/dev/drm/drm_crtc.c index 3353cf1d28..2a06ae8b36 100644 --- a/sys/dev/drm/drm_crtc.c +++ b/sys/dev/drm/drm_crtc.c @@ -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, diff --git a/sys/dev/drm/drm_drv.c b/sys/dev/drm/drm_drv.c index 672dbeddbb..f9680174f0 100644 --- a/sys/dev/drm/drm_drv.c +++ b/sys/dev/drm/drm_drv.c @@ -34,23 +34,15 @@ * open/close, and ioctl dispatch. */ -#include -#include +#include + +#include #include #include -#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, diff --git a/sys/dev/drm/drm_fops.c b/sys/dev/drm/drm_fops.c index a0f35864bb..6ea62aa992 100644 --- a/sys/dev/drm/drm_fops.c +++ b/sys/dev/drm/drm_fops.c @@ -32,26 +32,22 @@ * 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 -#include #include +#include #include +#include -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; diff --git a/sys/dev/drm/drm_ioctl.c b/sys/dev/drm/drm_ioctl.c index 48149028be..c03d0ebf01 100644 --- a/sys/dev/drm/drm_ioctl.c +++ b/sys/dev/drm/drm_ioctl.c @@ -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]; diff --git a/sys/dev/drm/drm_lock.c b/sys/dev/drm/drm_lock.c index 05dac6f1e6..bee8111c82 100644 --- a/sys/dev/drm/drm_lock.c +++ b/sys/dev/drm/drm_lock.c @@ -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); diff --git a/sys/dev/drm/drm_stub.c b/sys/dev/drm/drm_stub.c index 648a2ecded..b24d9fe4f5 100644 --- a/sys/dev/drm/drm_stub.c +++ b/sys/dev/drm/drm_stub.c @@ -29,11 +29,21 @@ * 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 +#include #include +#include + +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 @@ -41,25 +51,503 @@ */ 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 diff --git a/sys/dev/drm/drm_sysctl.c b/sys/dev/drm/drm_sysctl.c index 57fbbb8c93..f7536b0bc9 100644 --- a/sys/dev/drm/drm_sysctl.c +++ b/sys/dev/drm/drm_sysctl.c @@ -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, diff --git a/sys/dev/drm/i915/i915_dma.c b/sys/dev/drm/i915/i915_dma.c index c696eeae10..ad06589710 100644 --- a/sys/dev/drm/i915/i915_dma.c +++ b/sys/dev/drm/i915/i915_dma.c @@ -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); } diff --git a/sys/dev/drm/i915/i915_drv.c b/sys/dev/drm/i915/i915_drv.c index b8a309a94f..de61c5d9e7 100644 --- a/sys/dev/drm/i915/i915_drv.c +++ b/sys/dev/drm/i915/i915_drv.c @@ -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, diff --git a/sys/dev/drm/i915/intel_display.c b/sys/dev/drm/i915/intel_display.c index 63a3be9a13..e1a740acd8 100644 --- a/sys/dev/drm/i915/intel_display.c +++ b/sys/dev/drm/i915/intel_display.c @@ -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) diff --git a/sys/dev/drm/include/drm/drmP.h b/sys/dev/drm/include/drm/drmP.h index d0578c39fb..51167127a5 100644 --- a/sys/dev/drm/include/drm/drmP.h +++ b/sys/dev/drm/include/drm/drmP.h @@ -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 +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) diff --git a/sys/dev/drm/radeon/r300_cmdbuf.c b/sys/dev/drm/radeon/r300_cmdbuf.c index 522375d313..e3b4535fb5 100644 --- a/sys/dev/drm/radeon/r300_cmdbuf.c +++ b/sys/dev/drm/radeon/r300_cmdbuf.c @@ -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: diff --git a/sys/dev/drm/radeon/r600_blit.c b/sys/dev/drm/radeon/r600_blit.c index 943bb3a558..8a0ab048fc 100644 --- a/sys/dev/drm/radeon/r600_blit.c +++ b/sys/dev/drm/radeon/r600_blit.c @@ -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) diff --git a/sys/dev/drm/radeon/r600_cp.c b/sys/dev/drm/radeon/r600_cp.c index a7fe4b6570..64e0c32e1d 100644 --- a/sys/dev/drm/radeon/r600_cp.c +++ b/sys/dev/drm/radeon/r600_cp.c @@ -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(); } } diff --git a/sys/dev/drm/radeon/radeon_cp.c b/sys/dev/drm/radeon/radeon_cp.c index 92075f21df..c4fffc0123 100644 --- a/sys/dev/drm/radeon/radeon_cp.c +++ b/sys/dev/drm/radeon/radeon_cp.c @@ -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"); diff --git a/sys/dev/drm/radeon/radeon_drv.h b/sys/dev/drm/radeon/radeon_drv.h index 8f7d2f285b..42c2e99af1 100644 --- a/sys/dev/drm/radeon/radeon_drv.h +++ b/sys/dev/drm/radeon/radeon_drv.h @@ -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; \ diff --git a/sys/dev/drm/radeon/radeon_state.c b/sys/dev/drm/radeon/radeon_state.c index 888bd1ae2a..151b89ca76 100644 --- a/sys/dev/drm/radeon/radeon_state.c +++ b/sys/dev/drm/radeon/radeon_state.c @@ -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; diff --git a/sys/sys/file.h b/sys/sys/file.h index f401bff3dd..3e2a21698f 100644 --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -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 */ -- 2.41.0