diff options
Diffstat (limited to 'linux-core/drm_drv.c')
-rw-r--r-- | linux-core/drm_drv.c | 507 |
1 files changed, 7 insertions, 500 deletions
diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index c9958815..630e29dc 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -142,82 +142,6 @@ drm_ioctl_desc_t drm_ioctls[] = { #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( drm_ioctls ) -static int drm_setup( drm_device_t *dev ) -{ - int i; - - if (dev->fn_tbl->presetup) - dev->fn_tbl->presetup(dev); - - atomic_set( &dev->ioctl_count, 0 ); - atomic_set( &dev->vma_count, 0 ); - 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_ARRAY_SIZE(dev->counts) ; i++ ) - atomic_set( &dev->counts[i], 0 ); - - for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) { - dev->magiclist[i].head = NULL; - dev->magiclist[i].tail = NULL; - } - - dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), - DRM_MEM_CTXLIST); - if(dev->ctxlist == NULL) return -ENOMEM; - memset(dev->ctxlist, 0, sizeof(*dev->ctxlist)); - INIT_LIST_HEAD(&dev->ctxlist->head); - - dev->vmalist = NULL; - dev->sigdata.lock = dev->lock.hw_lock = NULL; - init_waitqueue_head( &dev->lock.lock_queue ); - dev->queue_count = 0; - dev->queue_reserved = 0; - dev->queue_slots = 0; - dev->queuelist = NULL; - 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->ctx_start = 0; - dev->lck_start = 0; - - dev->buf_rp = dev->buf; - dev->buf_wp = dev->buf; - dev->buf_end = dev->buf + DRM_BSZ; - 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. - */ - if (dev->fn_tbl->postsetup) - dev->fn_tbl->postsetup(dev); - - return 0; -} - - /** * Take down the DRM device. * @@ -227,7 +151,7 @@ static int drm_setup( drm_device_t *dev ) * * \sa drm_device and setup(). */ -static int drm_takedown( drm_device_t *dev ) +int drm_takedown( drm_device_t *dev ) { drm_magic_entry_t *pt, *next; drm_map_t *map; @@ -362,87 +286,6 @@ static int drm_takedown( drm_device_t *dev ) return 0; } -int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver_fn *driver_fn) -{ - int retcode; - - dev->count_lock = SPIN_LOCK_UNLOCKED; - init_timer( &dev->timer ); - sema_init( &dev->struct_sem, 1 ); - sema_init( &dev->ctxlist_sem, 1 ); - - dev->name = DRIVER_NAME; - dev->pdev = pdev; - -#ifdef __alpha__ - dev->hose = pdev->sysdata; - dev->pci_domain = dev->hose->bus->number; -#else - dev->pci_domain = 0; -#endif - dev->pci_bus = pdev->bus->number; - dev->pci_slot = PCI_SLOT(pdev->devfn); - dev->pci_func = PCI_FUNC(pdev->devfn); - dev->irq = pdev->irq; - - dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS); - if(dev->maplist == NULL) return -ENOMEM; - INIT_LIST_HEAD(&dev->maplist->head); - - /* the DRM has 6 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->fn_tbl = driver_fn; - - if (dev->fn_tbl->preinit) - if ((retcode = dev->fn_tbl->preinit(dev, ent->driver_data))) - goto error_out_unreg; - - if (drm_core_has_AGP(dev)) { - dev->agp = drm_agp_init(); - if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) { - DRM_ERROR( "Cannot initialize the agpgart module.\n" ); - retcode = -EINVAL; - goto error_out_unreg; - } - - - if (drm_core_has_MTRR(dev)) { - if (dev->agp) - dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base, - dev->agp->agp_info.aper_size*1024*1024, - MTRR_TYPE_WRCOMB, - 1 ); - } - } - - retcode = drm_ctxbitmap_init( dev ); - if( retcode ) { - DRM_ERROR( "Cannot allocate memory for context bitmap.\n" ); - goto error_out_unreg; - } - - dev->device = MKDEV(DRM_MAJOR, dev->minor ); -DRM_DEBUG("driver_fn->postinit %p\n", driver_fn->postinit); - - /* postinit is a required function to display the signon banner */ - /* drivers add secondary heads here if needed */ - if ((retcode = dev->fn_tbl->postinit(dev, ent->driver_data))) - goto error_out_unreg; - - return 0; - - error_out_unreg: - drm_takedown(dev); - return retcode; -} - void __exit drm_cleanup_pci(struct pci_dev *pdev) { drm_device_t *dev = pci_get_drvdata(pdev); @@ -630,6 +473,12 @@ void __exit drm_exit (struct pci_driver *driver) } EXPORT_SYMBOL(drm_exit); +/** File operations structure */ +static struct file_operations drm_stub_fops = { + .owner = THIS_MODULE, + .open = drm_stub_open +}; + static int __init drm_core_init(void) { int ret = -ENOMEM; @@ -725,210 +574,6 @@ int drm_version( struct inode *inode, struct file *filp, return 0; } -/** - * 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 inode *inode, struct file *filp ) -{ - drm_device_t *dev = NULL; - int minor = iminor(inode); - int retcode = 0; - - if (!((minor >= 0) && (minor < cards_limit))) - return -ENODEV; - - dev = drm_minors[minor].dev; - if (!dev) - return -ENODEV; - - retcode = drm_open_helper( inode, filp, dev ); - if ( !retcode ) { - atomic_inc( &dev->counts[_DRM_STAT_OPENS] ); - spin_lock( &dev->count_lock ); - if ( !dev->open_count++ ) { - spin_unlock( &dev->count_lock ); - return drm_setup( dev ); - } - spin_unlock( &dev->count_lock ); - } - - return retcode; -} -EXPORT_SYMBOL(drm_open); - -/** - * Release file. - * - * \param inode device inode - * \param filp file pointer. - * \return zero on success or a negative number on failure. - * - * If the hardware lock is held then free it, and take it again for the kernel - * context since it's necessary to reclaim buffers. Unlink the file private - * data from its list and free it. Decreases the open count and if it reaches - * zero calls takedown(). - */ -int drm_release( struct inode *inode, struct file *filp ) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev; - int retcode = 0; - - lock_kernel(); - dev = priv->dev; - - DRM_DEBUG( "open_count = %d\n", dev->open_count ); - - if (dev->fn_tbl->prerelease) - dev->fn_tbl->prerelease(dev, filp); - - /* ======================================================== - * Begin inline drm_release - */ - - DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n", - current->pid, (long)old_encode_dev(dev->device), dev->open_count ); - - if ( priv->lock_count && dev->lock.hw_lock && - _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) && - dev->lock.filp == filp ) { - DRM_DEBUG( "File %p released, freeing lock for context %d\n", - filp, - _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) ); - - if (dev->fn_tbl->release) - dev->fn_tbl->release(dev, filp); - - drm_lock_free( dev, &dev->lock.hw_lock->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->fn_tbl->release && priv->lock_count && dev->lock.hw_lock ) { - /* The lock is required to reclaim buffers */ - DECLARE_WAITQUEUE( entry, current ); - - add_wait_queue( &dev->lock.lock_queue, &entry ); - for (;;) { - current->state = TASK_INTERRUPTIBLE; - if ( !dev->lock.hw_lock ) { - /* Device has been unregistered */ - retcode = -EINTR; - break; - } - if ( drm_lock_take( &dev->lock.hw_lock->lock, - DRM_KERNEL_CONTEXT ) ) { - dev->lock.filp = filp; - dev->lock.lock_time = jiffies; - atomic_inc( &dev->counts[_DRM_STAT_LOCKS] ); - break; /* Got lock */ - } - /* Contention */ - schedule(); - if ( signal_pending( current ) ) { - retcode = -ERESTARTSYS; - break; - } - } - current->state = TASK_RUNNING; - remove_wait_queue( &dev->lock.lock_queue, &entry ); - if( !retcode ) { - if (dev->fn_tbl->release) - dev->fn_tbl->release(dev, filp); - drm_lock_free( dev, &dev->lock.hw_lock->lock, - DRM_KERNEL_CONTEXT ); - } - } - - if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) - { - dev->fn_tbl->reclaim_buffers(filp); - } - - drm_fasync( -1, filp, 0 ); - - down( &dev->ctxlist_sem ); - if ( !list_empty( &dev->ctxlist->head ) ) { - drm_ctx_list_t *pos, *n; - - list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) { - if ( pos->tag == priv && - pos->handle != DRM_KERNEL_CONTEXT ) { - if (dev->fn_tbl->context_dtor) - dev->fn_tbl->context_dtor(dev, pos->handle); - - drm_ctxbitmap_free( dev, pos->handle ); - - list_del( &pos->head ); - drm_free( pos, sizeof(*pos), DRM_MEM_CTXLIST ); - --dev->ctx_count; - } - } - } - up( &dev->ctxlist_sem ); - - down( &dev->struct_sem ); - if ( priv->remove_auth_on_close == 1 ) { - drm_file_t *temp = dev->file_first; - while ( temp ) { - temp->authenticated = 0; - temp = temp->next; - } - } - if ( priv->prev ) { - priv->prev->next = priv->next; - } else { - dev->file_first = priv->next; - } - if ( priv->next ) { - priv->next->prev = priv->prev; - } else { - dev->file_last = priv->prev; - } - up( &dev->struct_sem ); - - if (dev->fn_tbl->free_filp_priv) - dev->fn_tbl->free_filp_priv( dev, priv ); - drm_free( priv, sizeof(*priv), DRM_MEM_FILES ); - - /* ======================================================== - * End inline drm_release - */ - - atomic_inc( &dev->counts[_DRM_STAT_CLOSES] ); - spin_lock( &dev->count_lock ); - if ( !--dev->open_count ) { - if ( atomic_read( &dev->ioctl_count ) || dev->blocked ) { - DRM_ERROR( "Device busy: %d %d\n", - atomic_read( &dev->ioctl_count ), - dev->blocked ); - spin_unlock( &dev->count_lock ); - unlock_kernel(); - return -EBUSY; - } - spin_unlock( &dev->count_lock ); - unlock_kernel(); - return drm_takedown( dev ); - } - spin_unlock( &dev->count_lock ); - - unlock_kernel(); - - return retcode; -} -EXPORT_SYMBOL(drm_release); - /** * Called whenever a process performs an ioctl on /dev/drm. * @@ -986,141 +631,3 @@ err_i1: } EXPORT_SYMBOL(drm_ioctl); -/** - * Lock ioctl. - * - * \param inode device inode. - * \param filp file pointer. - * \param cmd command. - * \param arg user argument, pointing to a drm_lock structure. - * \return zero on success or negative number on failure. - * - * Add the current task to the lock wait queue, and attempt to take to lock. - */ -int drm_lock( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - DECLARE_WAITQUEUE( entry, current ); - drm_lock_t lock; - int ret = 0; - - ++priv->lock_count; - - if ( copy_from_user( &lock, (drm_lock_t __user *)arg, sizeof(lock) ) ) - return -EFAULT; - - if ( lock.context == DRM_KERNEL_CONTEXT ) { - DRM_ERROR( "Process %d using kernel context %d\n", - current->pid, lock.context ); - return -EINVAL; - } - - DRM_DEBUG( "%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n", - lock.context, current->pid, - dev->lock.hw_lock->lock, lock.flags ); - - if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE)) - if ( lock.context < 0 ) - return -EINVAL; - - add_wait_queue( &dev->lock.lock_queue, &entry ); - for (;;) { - current->state = TASK_INTERRUPTIBLE; - if ( !dev->lock.hw_lock ) { - /* Device has been unregistered */ - ret = -EINTR; - break; - } - if ( drm_lock_take( &dev->lock.hw_lock->lock, - lock.context ) ) { - dev->lock.filp = filp; - dev->lock.lock_time = jiffies; - atomic_inc( &dev->counts[_DRM_STAT_LOCKS] ); - break; /* Got lock */ - } - - /* Contention */ - schedule(); - if ( signal_pending( current ) ) { - ret = -ERESTARTSYS; - break; - } - } - current->state = TASK_RUNNING; - remove_wait_queue( &dev->lock.lock_queue, &entry ); - - sigemptyset( &dev->sigmask ); - sigaddset( &dev->sigmask, SIGSTOP ); - sigaddset( &dev->sigmask, SIGTSTP ); - sigaddset( &dev->sigmask, SIGTTIN ); - sigaddset( &dev->sigmask, SIGTTOU ); - dev->sigdata.context = lock.context; - dev->sigdata.lock = dev->lock.hw_lock; - block_all_signals( drm_notifier, - &dev->sigdata, &dev->sigmask ); - - if (dev->fn_tbl->dma_ready && (lock.flags & _DRM_LOCK_READY)) - dev->fn_tbl->dma_ready(dev); - - if ( dev->fn_tbl->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT )) - return dev->fn_tbl->dma_quiescent(dev); - - - if ( dev->fn_tbl->kernel_context_switch && dev->last_context != lock.context ) { - dev->fn_tbl->kernel_context_switch(dev, dev->last_context, - lock.context); - } - - - DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" ); - - return ret; -} - -/** - * Unlock ioctl. - * - * \param inode device inode. - * \param filp file pointer. - * \param cmd command. - * \param arg user argument, pointing to a drm_lock structure. - * \return zero on success or negative number on failure. - * - * Transfer and free the lock. - */ -int drm_unlock( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_lock_t lock; - - if ( copy_from_user( &lock, (drm_lock_t __user *)arg, sizeof(lock) ) ) - return -EFAULT; - - if ( lock.context == DRM_KERNEL_CONTEXT ) { - DRM_ERROR( "Process %d using kernel context %d\n", - current->pid, lock.context ); - return -EINVAL; - } - - atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] ); - - if (dev->fn_tbl->kernel_context_switch_unlock) - dev->fn_tbl->kernel_context_switch_unlock(dev); - else - { - drm_lock_transfer( dev, &dev->lock.hw_lock->lock, - DRM_KERNEL_CONTEXT ); - - if ( drm_lock_free( dev, &dev->lock.hw_lock->lock, - DRM_KERNEL_CONTEXT ) ) { - DRM_ERROR( "\n" ); - } - } - - unblock_all_signals(); - return 0; -} |