- SMPng lock the DRM. This is only partial -- there are a few code paths

used by root (the X Server) which are not locked. However, it should
    deal with lost-IRQ issues on -current which I think people have been
    experiencing but I am unable to reproduce (though I understand why they
    would occur, because of a bug of mine). Note that most of the locking
    (DRM_LOCK()/UNLOCK()) is all covered by Giant still, so it doesn't
    matter yet.
- Remove locking on FreeBSD-stable and NetBSD. These are covered by the
    fact that there is no reentrancy of the kernel except by interrupts,
    which are locked using spldrm()/splx() instead.
This commit is contained in:
Eric Anholt 2003-10-19 23:35:58 +00:00
parent 59fbe01fea
commit 0cf1887139
26 changed files with 476 additions and 478 deletions

View file

@ -59,7 +59,7 @@ int DRM(ati_pcigart_init)( drm_device_t *dev,
}
address = (long)contigmalloc((1 << ATI_PCIGART_TABLE_ORDER) * PAGE_SIZE,
DRM(M_DRM), M_WAITOK, 0ul, 0xfffffffful, PAGE_SIZE, 0);
DRM(M_DRM), M_NOWAIT, 0ul, 0xfffffffful, PAGE_SIZE, 0);
if ( !address ) {
DRM_ERROR( "cannot allocate PCI GART page!\n" );
goto done;

View file

@ -180,7 +180,6 @@ typedef struct drm_freelist {
int low_mark; /* Low water mark */
int high_mark; /* High water mark */
DRM_SPINTYPE lock;
} drm_freelist_t;
typedef struct drm_buf_entry {
@ -216,10 +215,17 @@ struct drm_file {
typedef struct drm_lock_data {
drm_hw_lock_t *hw_lock; /* Hardware lock */
DRMFILE filp; /* Unique identifier of holding process (NULL is kernel)*/
wait_queue_head_t lock_queue; /* Queue of blocked processes */
int lock_queue; /* Queue of blocked processes */
unsigned long lock_time; /* Time of last lock in jiffies */
} drm_lock_data_t;
/* This structure, in the drm_device_t, 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.
*/
typedef struct drm_device_dma {
drm_buf_entry_t bufs[DRM_MAX_ORDER+1];
int buf_count;
@ -311,8 +317,15 @@ struct drm_device {
int flags; /* Flags to open(2) */
/* Locks */
DRM_SPINTYPE count_lock; /* For open_count, buf_use, buf_alloc */
struct lock dev_lock; /* For others */
#if defined(__FreeBSD__) && __FreeBSD_version > 500000
#if __HAVE_DMA
struct mtx dma_lock; /* protects dev->dma */
#endif
#if __HAVE_IRQ
struct mtx irq_lock; /* protects irq condition checks */
#endif
struct mtx dev_lock; /* protects everything else */
#endif
/* Usage Counters */
int open_count; /* Outstanding files open */
int buf_use; /* Buffers in use -- cannot alloc */
@ -327,8 +340,8 @@ struct drm_device {
drm_file_list_t files;
drm_magic_head_t magiclist[DRM_HASH_SIZE];
/* Memory management */
drm_map_list_t *maplist; /* Linked list of regions */
/* Linked list of mappable regions. Protected by dev_lock */
drm_map_list_t *maplist;
drm_local_map_t **context_sareas;
int max_context;
@ -349,18 +362,13 @@ struct drm_device {
#endif
void *irqh; /* Handle from bus_setup_intr */
atomic_t context_flag; /* Context swapping flag */
struct callout timer; /* Timer for delaying ctx switch */
int last_context; /* Last current context */
#if __FreeBSD_version >= 400005
struct task task;
#endif
#if __HAVE_VBL_IRQ
wait_queue_head_t vbl_queue; /* vbl wait channel */
int vbl_queue; /* vbl wait channel */
atomic_t vbl_received;
#if 0 /* vbl signals are untested */
struct drm_vbl_sig_list vbl_sig_list;
DRM_SPINTYPE vbl_lock;
#endif
#endif
#ifdef __FreeBSD__
@ -382,11 +390,6 @@ struct drm_device {
extern int DRM(flags);
/* Authentication (drm_auth.h) */
extern int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv,
drm_magic_t magic);
extern int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic);
/* Driver support (drm_drv.h) */
extern int DRM(version)( DRM_IOCTL_ARGS );

View file

@ -54,7 +54,7 @@ static drm_file_t *DRM(find_file)(drm_device_t *dev, drm_magic_t magic)
return retval;
}
int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
static int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
{
int hash;
drm_magic_entry_t *entry;
@ -82,7 +82,7 @@ int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
return 0;
}
int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic)
static int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic)
{
drm_magic_entry_t *prev = NULL;
drm_magic_entry_t *pt;
@ -116,9 +116,17 @@ int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic)
int DRM(getmagic)(DRM_IOCTL_ARGS)
{
static drm_magic_t sequence = 0;
drm_auth_t auth;
drm_auth_t auth;
drm_file_t *priv;
DRM_DEVICE;
DRM_PRIV;
DRM_LOCK();
priv = (drm_file_t *) DRM(find_file_by_proc)(dev, p);
DRM_UNLOCK();
if (priv == NULL) {
DRM_DEBUG("can't find authenticator\n");
return EINVAL;
}
/* Find unique magic */
if (priv->magic) {
@ -152,6 +160,7 @@ int DRM(authmagic)(DRM_IOCTL_ARGS)
DRM_COPY_FROM_USER_IOCTL(auth, (drm_auth_t *)data, sizeof(auth));
DRM_DEBUG("%u\n", auth.magic);
if ((file = DRM(find_file)(dev, auth.magic))) {
file->authenticated = 1;
DRM(remove_magic)(dev, auth.magic);

View file

@ -226,6 +226,8 @@ int DRM(rmmap)( DRM_IOCTL_ARGS )
return DRM_ERR(EINVAL);
}
TAILQ_REMOVE(dev->maplist, list, link);
DRM_UNLOCK();
DRM(free)(list, sizeof(*list), DRM_MEM_MAPS);
switch (map->type) {
@ -268,7 +270,6 @@ int DRM(rmmap)( DRM_IOCTL_ARGS )
break;
}
DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
DRM_UNLOCK();
return 0;
}
@ -350,20 +351,11 @@ static int DRM(addbufs_agp)(drm_device_t *dev, drm_buf_desc_t *request)
DRM_DEBUG( "page_order: %d\n", page_order );
DRM_DEBUG( "total: %d\n", total );
if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER )
return DRM_ERR(EINVAL);
DRM_LOCK();
entry = &dma->bufs[order];
if ( entry->buf_count ) {
DRM_UNLOCK();
return DRM_ERR(ENOMEM); /* May only call once for each order */
}
entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist),
DRM_MEM_BUFS );
if ( !entry->buflist ) {
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
@ -394,7 +386,6 @@ static int DRM(addbufs_agp)(drm_device_t *dev, drm_buf_desc_t *request)
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
DRM(cleanup_buf_error)(dev, entry);
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
@ -413,7 +404,6 @@ static int DRM(addbufs_agp)(drm_device_t *dev, drm_buf_desc_t *request)
if (temp_buflist == NULL) {
/* Free the entry because it isn't valid */
DRM(cleanup_buf_error)(dev, entry);
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
dma->buflist = temp_buflist;
@ -428,8 +418,6 @@ static int DRM(addbufs_agp)(drm_device_t *dev, drm_buf_desc_t *request)
DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
DRM_UNLOCK();
request->count = entry->buf_count;
request->size = size;
@ -467,20 +455,12 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
DRM_DEBUG( "count=%d, size=%d (%d), order=%d\n",
request->count, request->size, size, order );
if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER )
return DRM_ERR(EINVAL);
alignment = (request->flags & _DRM_PAGE_ALIGN)
? round_page(size) : size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;
DRM_LOCK();
entry = &dma->bufs[order];
if ( entry->buf_count ) {
DRM_UNLOCK();
return DRM_ERR(ENOMEM); /* May only call once for each order */
}
entry->buflist = DRM(alloc)(count * sizeof(*entry->buflist),
DRM_MEM_BUFS);
@ -503,7 +483,6 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
DRM_MEM_SEGS);
DRM(free)(entry->seglist_bus, count *
sizeof(*entry->seglist_bus), DRM_MEM_SEGS);
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
@ -532,7 +511,6 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
DRM(free)(temp_pagelist, (dma->page_count +
(count << page_order)) * sizeof(*dma->pagelist),
DRM_MEM_PAGES);
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
@ -571,7 +549,6 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
DRM(free)(temp_pagelist, (dma->page_count +
(count << page_order)) *
sizeof(*dma->pagelist), DRM_MEM_PAGES );
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
bzero(buf->dev_private, buf->dev_priv_size);
@ -593,7 +570,6 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
DRM(free)(temp_pagelist, (dma->page_count +
(count << page_order)) * sizeof(*dma->pagelist),
DRM_MEM_PAGES);
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
dma->buflist = temp_buflist;
@ -614,8 +590,6 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
dma->page_count += entry->seg_count << page_order;
dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
DRM_UNLOCK();
request->count = entry->buf_count;
request->size = size;
@ -662,23 +636,12 @@ static int DRM(addbufs_sg)(drm_device_t *dev, drm_buf_desc_t *request)
DRM_DEBUG( "page_order: %d\n", page_order );
DRM_DEBUG( "total: %d\n", total );
if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER )
return DRM_ERR(EINVAL);
DRM_LOCK();
entry = &dma->bufs[order];
if ( entry->buf_count ) {
DRM_UNLOCK();
return DRM_ERR(ENOMEM); /* May only call once for each order */
}
entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist),
DRM_MEM_BUFS );
if ( !entry->buflist ) {
DRM_UNLOCK();
entry->buflist = DRM(calloc)(1, count * sizeof(*entry->buflist),
DRM_MEM_BUFS);
if (entry->buflist == NULL)
return DRM_ERR(ENOMEM);
}
memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
entry->buf_size = size;
entry->page_order = page_order;
@ -706,7 +669,6 @@ static int DRM(addbufs_sg)(drm_device_t *dev, drm_buf_desc_t *request)
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
DRM(cleanup_buf_error)(dev, entry);
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
@ -728,7 +690,6 @@ static int DRM(addbufs_sg)(drm_device_t *dev, drm_buf_desc_t *request)
if (temp_buflist == NULL) {
/* Free the entry because it isn't valid */
DRM(cleanup_buf_error)(dev, entry);
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
dma->buflist = temp_buflist;
@ -743,8 +704,6 @@ static int DRM(addbufs_sg)(drm_device_t *dev, drm_buf_desc_t *request)
DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
DRM_UNLOCK();
request->count = entry->buf_count;
request->size = size;
@ -759,25 +718,28 @@ int DRM(addbufs)( DRM_IOCTL_ARGS )
DRM_DEVICE;
drm_buf_desc_t request;
int err;
int order;
DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_desc_t *)data, sizeof(request) );
if (dev->dma == NULL)
return DRM_ERR(EINVAL);
if (request.count < 0 || request.count > 4096)
return DRM_ERR(EINVAL);
DRM_SPINLOCK(&dev->count_lock);
if (dev->buf_use) {
DRM_SPINUNLOCK(&dev->count_lock);
order = DRM(order)(request.size);
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
return DRM_ERR(EINVAL);
DRM_SPINLOCK(&dev->dma_lock);
/* No more allocations after first buffer-using ioctl. */
if (dev->buf_use != 0) {
DRM_SPINUNLOCK(&dev->dma_lock);
return DRM_ERR(EBUSY);
}
/* dev->buf_alloc acts as a lock to prevent infobufs/mapbufs from
* trying to read from the dma->bufs while buffers are being allocated */
dev->buf_alloc++;
DRM_SPINUNLOCK(&dev->count_lock);
/* No more than one allocation per order */
if (dev->dma->bufs[order].buf_count != 0) {
DRM_SPINUNLOCK(&dev->dma_lock);
return DRM_ERR(ENOMEM);
}
#if __REALLY_HAVE_AGP
if ( request.flags & _DRM_AGP_BUFFER )
@ -794,13 +756,10 @@ int DRM(addbufs)( DRM_IOCTL_ARGS )
#else
err = DRM_ERR(EINVAL);
#endif
DRM_SPINUNLOCK(&dev->dma_lock);
DRM_COPY_TO_USER_IOCTL((drm_buf_desc_t *)data, request, sizeof(request));
DRM_SPINLOCK(&dev->count_lock);
dev->buf_alloc--;
DRM_SPINUNLOCK(&dev->count_lock);
return err;
}
@ -811,19 +770,14 @@ int DRM(infobufs)( DRM_IOCTL_ARGS )
drm_buf_info_t request;
int i;
int count;
if ( !dma ) return DRM_ERR(EINVAL);
DRM_SPINLOCK( &dev->count_lock );
if (dev->buf_alloc != 0) {
DRM_SPINUNLOCK( &dev->count_lock );
return DRM_ERR(EBUSY);
}
++dev->buf_use; /* Can't allocate more after this call */
DRM_SPINUNLOCK( &dev->count_lock );
int retcode = 0;
DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_info_t *)data, sizeof(request) );
DRM_SPINLOCK(&dev->dma_lock);
++dev->buf_use; /* Can't allocate more after this call */
DRM_SPINUNLOCK(&dev->dma_lock);
for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) {
if ( dma->bufs[i].buf_count ) ++count;
}
@ -841,8 +795,10 @@ int DRM(infobufs)( DRM_IOCTL_ARGS )
from.high_mark = dma->bufs[i].freelist.high_mark;
if (DRM_COPY_TO_USER(&request.list[count], &from,
sizeof(drm_buf_desc_t)) != 0)
return DRM_ERR(EFAULT);
sizeof(drm_buf_desc_t)) != 0) {
retcode = DRM_ERR(EFAULT);
break;
}
DRM_DEBUG( "%d %d %d %d %d\n",
i,
@ -858,7 +814,7 @@ int DRM(infobufs)( DRM_IOCTL_ARGS )
DRM_COPY_TO_USER_IOCTL( (drm_buf_info_t *)data, request, sizeof(request) );
return 0;
return retcode;
}
int DRM(markbufs)( DRM_IOCTL_ARGS )
@ -867,26 +823,28 @@ int DRM(markbufs)( DRM_IOCTL_ARGS )
drm_device_dma_t *dma = dev->dma;
drm_buf_desc_t request;
int order;
drm_buf_entry_t *entry;
if ( !dma ) return DRM_ERR(EINVAL);
DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_desc_t *)data, sizeof(request) );
DRM_DEBUG( "%d, %d, %d\n",
request.size, request.low_mark, request.high_mark );
order = DRM(order)( request.size );
if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER )
return DRM_ERR(EINVAL);
entry = &dma->bufs[order];
if ( request.low_mark < 0 || request.low_mark > entry->buf_count )
return DRM_ERR(EINVAL);
if ( request.high_mark < 0 || request.high_mark > entry->buf_count )
order = DRM(order)(request.size);
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ||
request.low_mark < 0 || request.high_mark < 0) {
return DRM_ERR(EINVAL);
}
entry->freelist.low_mark = request.low_mark;
entry->freelist.high_mark = request.high_mark;
DRM_SPINLOCK(&dev->dma_lock);
if (request.low_mark > dma->bufs[order].buf_count ||
request.high_mark > dma->bufs[order].buf_count) {
return DRM_ERR(EINVAL);
}
dma->bufs[order].freelist.low_mark = request.low_mark;
dma->bufs[order].freelist.high_mark = request.high_mark;
DRM_SPINUNLOCK(&dev->dma_lock);
return 0;
}
@ -899,32 +857,36 @@ int DRM(freebufs)( DRM_IOCTL_ARGS )
int i;
int idx;
drm_buf_t *buf;
if ( !dma ) return DRM_ERR(EINVAL);
int retcode = 0;
DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_free_t *)data, sizeof(request) );
DRM_DEBUG( "%d\n", request.count );
DRM_SPINLOCK(&dev->dma_lock);
for ( i = 0 ; i < request.count ; i++ ) {
if ( DRM_COPY_FROM_USER( &idx,
&request.list[i],
sizeof(idx) ) )
return DRM_ERR(EFAULT);
if (DRM_COPY_FROM_USER(&idx, &request.list[i], sizeof(idx))) {
retcode = DRM_ERR(EFAULT);
break;
}
if ( idx < 0 || idx >= dma->buf_count ) {
DRM_ERROR( "Index %d (of %d max)\n",
idx, dma->buf_count - 1 );
return DRM_ERR(EINVAL);
retcode = DRM_ERR(EINVAL);
break;
}
buf = dma->buflist[idx];
if ( buf->filp != filp ) {
DRM_ERROR("Process %d freeing buffer not owned\n",
DRM_CURRENTPID);
return DRM_ERR(EINVAL);
retcode = DRM_ERR(EINVAL);
break;
}
DRM(free_buffer)( dev, buf );
}
DRM_SPINUNLOCK(&dev->dma_lock);
return 0;
return retcode;
}
int DRM(mapbufs)( DRM_IOCTL_ARGS )
@ -949,16 +911,6 @@ int DRM(mapbufs)( DRM_IOCTL_ARGS )
drm_buf_map_t request;
int i;
if ( !dma ) return DRM_ERR(EINVAL);
DRM_SPINLOCK( &dev->count_lock );
if (dev->buf_alloc != 0) {
DRM_SPINUNLOCK( &dev->count_lock );
return DRM_ERR(EBUSY);
}
dev->buf_use++; /* Can't allocate more after this call */
DRM_SPINUNLOCK( &dev->count_lock );
DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_map_t *)data, sizeof(request) );
#ifdef __NetBSD__
@ -972,6 +924,10 @@ int DRM(mapbufs)( DRM_IOCTL_ARGS )
vms = p->p_vmspace;
#endif
DRM_SPINLOCK(&dev->dma_lock);
dev->buf_use++; /* Can't allocate more after this call */
DRM_SPINUNLOCK(&dev->dma_lock);
if (request.count < dma->buf_count)
goto done;
@ -1040,4 +996,3 @@ int DRM(mapbufs)( DRM_IOCTL_ARGS )
}
#endif /* __HAVE_DMA */

View file

@ -51,6 +51,8 @@ int DRM(dma_setup)( drm_device_t *dev )
if (dev->dma == NULL)
return DRM_ERR(ENOMEM);
DRM_SPININIT(dev->dma_lock, "drmdma");
return 0;
}
@ -59,7 +61,8 @@ void DRM(dma_takedown)(drm_device_t *dev)
drm_device_dma_t *dma = dev->dma;
int i, j;
if (!dma) return;
if (dma == NULL)
return;
/* Clear dma buffers */
for (i = 0; i <= DRM_MAX_ORDER; i++) {
@ -106,6 +109,7 @@ void DRM(dma_takedown)(drm_device_t *dev)
DRM_MEM_PAGES);
DRM(free)(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
dev->dma = NULL;
DRM_SPINUNINIT(dev->dma_lock);
}

View file

@ -111,7 +111,7 @@ int DRM(flags) = 0;
#endif
static int DRM(init)(device_t nbdev);
static void DRM(cleanup)(device_t nbdev);
static void DRM(cleanup)(drm_device_t *dev);
#ifdef __FreeBSD__
#define DRIVER_SOFTC(unit) \
@ -253,7 +253,7 @@ static int DRM(attach)(device_t dev)
static int DRM(detach)(device_t dev)
{
DRM(cleanup)(dev);
DRM(cleanup)(device_get_softc(dev));
return 0;
}
static device_method_t DRM(methods)[] = {
@ -411,6 +411,7 @@ const char *DRM(find_description)(int vendor, int device) {
return NULL;
}
/* Initialize the DRM on first open. Called with device's lock held */
static int DRM(setup)( drm_device_t *dev )
{
int i;
@ -421,7 +422,7 @@ static int DRM(setup)( drm_device_t *dev )
#if __HAVE_DMA
i = DRM(dma_setup)( dev );
if ( i < 0 )
if ( i != 0 )
return i;
#endif
@ -481,11 +482,6 @@ static int DRM(setup)( drm_device_t *dev )
dev->irq = 0;
dev->context_flag = 0;
dev->last_context = 0;
#if __FreeBSD_version >= 500000
callout_init( &dev->timer, 1 );
#else
callout_init( &dev->timer );
#endif
#ifdef __FreeBSD__
dev->buf_sigio = NULL;
@ -499,7 +495,9 @@ static int DRM(setup)( drm_device_t *dev )
return 0;
}
/* Free resources associated with the DRM on the last close.
* Called with the device's lock held.
*/
static int DRM(takedown)( drm_device_t *dev )
{
drm_magic_entry_t *pt, *next;
@ -515,9 +513,6 @@ static int DRM(takedown)( drm_device_t *dev )
DRM(irq_uninstall)( dev );
#endif
DRM_LOCK();
callout_stop( &dev->timer );
if ( dev->unique ) {
DRM(free)( dev->unique, strlen( dev->unique ) + 1,
DRM_MEM_DRIVER );
@ -540,7 +535,7 @@ static int DRM(takedown)( drm_device_t *dev )
drm_agp_mem_t *nexte;
/* Remove AGP resources, but leave dev->agp
intact until drv_cleanup is called. */
intact until DRM(cleanup) is called. */
for ( entry = dev->agp->memory ; entry ; entry = nexte ) {
nexte = entry->next;
if ( entry->bound ) DRM(unbind_agp)( entry->handle );
@ -625,7 +620,6 @@ static int DRM(takedown)( drm_device_t *dev )
dev->lock.filp = NULL;
DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
}
DRM_UNLOCK();
return 0;
}
@ -664,11 +658,12 @@ static int DRM(init)( device_t nbdev )
DRM_DEV_GID,
DRM_DEV_MODE,
"dri/card%d", unit );
#if __FreeBSD_version >= 500000
mtx_init(&dev->dev_lock, "drm device", NULL, MTX_DEF);
#endif
#elif defined(__NetBSD__)
unit = minor(dev->device.dv_unit);
#endif
DRM_SPININIT(dev->count_lock, "drm device");
lockinit(&dev->dev_lock, PZERO, "drmlk", 0, 0);
dev->name = DRIVER_NAME;
DRM(mem_init)();
DRM(sysctl_init)(dev);
@ -679,12 +674,8 @@ static int DRM(init)( device_t nbdev )
#if __MUST_HAVE_AGP
if ( dev->agp == NULL ) {
DRM_ERROR( "Cannot initialize the agpgart module.\n" );
DRM(sysctl_cleanup)( dev );
#ifdef __FreeBSD__
destroy_dev(dev->devnode);
#endif
DRM(takedown)( dev );
return DRM_ERR(ENOMEM);
retcode = DRM_ERR(ENOMEM);
goto error;
}
#endif /* __MUST_HAVE_AGP */
#if __REALLY_HAVE_MTRR
@ -716,12 +707,7 @@ static int DRM(init)( device_t nbdev )
retcode = DRM(ctxbitmap_init)( dev );
if (retcode != 0) {
DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
DRM(sysctl_cleanup)( dev );
#ifdef __FreeBSD__
destroy_dev(dev->devnode);
#endif
DRM(takedown)( dev );
return retcode;
goto error;
}
#endif
DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
@ -735,28 +721,36 @@ static int DRM(init)( device_t nbdev )
DRIVER_POSTINIT();
return 0;
error:
DRM(sysctl_cleanup)(dev);
DRM_LOCK();
DRM(takedown)(dev);
DRM_UNLOCK();
#ifdef __FreeBSD__
destroy_dev(dev->devnode);
#if __FreeBSD_version >= 500000
mtx_destroy(&dev->dev_lock);
#endif
#endif
return retcode;
}
/* linux: drm_cleanup is called via cleanup_module at module unload time.
* bsd: drm_cleanup is called per device at module unload time.
* FIXME: NetBSD
*/
static void DRM(cleanup)(device_t nbdev)
static void DRM(cleanup)(drm_device_t *dev)
{
drm_device_t *dev;
#ifdef __NetBSD__
#if __REALLY_HAVE_MTRR
struct mtrr mtrrmap;
int one = 1;
#endif /* __REALLY_HAVE_MTRR */
dev = nbdev;
#endif /* __NetBSD__ */
DRM_DEBUG( "\n" );
#ifdef __FreeBSD__
dev = device_get_softc(nbdev);
#endif
DRM(sysctl_cleanup)( dev );
#ifdef __FreeBSD__
destroy_dev(dev->devnode);
@ -777,7 +771,9 @@ static void DRM(cleanup)(device_t nbdev)
}
#endif
DRM_LOCK();
DRM(takedown)( dev );
DRM_UNLOCK();
#if __REALLY_HAVE_AGP
if ( dev->agp ) {
@ -788,7 +784,9 @@ static void DRM(cleanup)(device_t nbdev)
#endif
DRIVER_POSTCLEANUP();
DRM(mem_uninit)();
DRM_SPINUNINIT(dev->count_lock);
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
mtx_destroy(&dev->dev_lock);
#endif
}
@ -834,13 +832,13 @@ int DRM(open)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
if ( !retcode ) {
atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
DRM_SPINLOCK( &dev->count_lock );
DRM_LOCK();
#ifdef __FreeBSD__
device_busy(dev->device);
#endif
if ( !dev->open_count++ )
retcode = DRM(setup)( dev );
DRM_SPINUNLOCK( &dev->count_lock );
DRM_UNLOCK();
}
return retcode;
@ -854,8 +852,12 @@ int DRM(close)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
DRMFILE filp = (void *)(DRM_CURRENTPID);
DRM_DEBUG( "open_count = %d\n", dev->open_count );
DRM_LOCK();
priv = DRM(find_file_by_proc)(dev, p);
if (!priv) {
DRM_UNLOCK();
DRM_DEBUG("can't find authenticator\n");
return EINVAL;
}
@ -908,10 +910,13 @@ int DRM(close)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
break; /* Got lock */
}
/* Contention */
#if defined(__FreeBSD__) && __FreeBSD_version > 500000
retcode = msleep((void *)&dev->lock.lock_queue,
dev->dev_lock, PZERO | PCATCH, "drmlk2", 0);
#else
retcode = tsleep((void *)&dev->lock.lock_queue,
PZERO|PCATCH,
"drmlk2",
0);
PZERO | PCATCH, "drmlk2", 0);
#endif
if (retcode)
break;
}
@ -933,32 +938,24 @@ int DRM(close)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
dev->buf_pgid = 0;
#endif /* __NetBSD__ */
DRM_LOCK();
priv = DRM(find_file_by_proc)(dev, p);
if (priv) {
priv->refs--;
if (!priv->refs) {
TAILQ_REMOVE(&dev->files, priv, link);
DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES );
}
if (--priv->refs == 0) {
TAILQ_REMOVE(&dev->files, priv, link);
DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES );
}
DRM_UNLOCK();
/* ========================================================
* End inline drm_release
*/
atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
DRM_SPINLOCK( &dev->count_lock );
#ifdef __FreeBSD__
device_unbusy(dev->device);
#endif
if ( !--dev->open_count ) {
DRM_SPINUNLOCK( &dev->count_lock );
return DRM(takedown)( dev );
if (--dev->open_count == 0) {
retcode = DRM(takedown)(dev);
}
DRM_SPINUNLOCK( &dev->count_lock );
DRM_UNLOCK();
return retcode;
}
@ -973,7 +970,15 @@ int DRM(ioctl)(dev_t kdev, u_long cmd, caddr_t data, int flags,
drm_ioctl_desc_t *ioctl;
int (*func)(DRM_IOCTL_ARGS);
int nr = DRM_IOCTL_NR(cmd);
DRM_PRIV;
drm_file_t *priv;
DRM_LOCK();
priv = (drm_file_t *) DRM(find_file_by_proc)(dev, p);
DRM_UNLOCK();
if (priv == NULL) {
DRM_DEBUG("can't find authenticator\n");
return EINVAL;
}
atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
++priv->ioctl_count;
@ -988,10 +993,7 @@ int DRM(ioctl)(dev_t kdev, u_long cmd, caddr_t data, int flags,
switch (cmd) {
case FIONBIO:
return 0;
case FIOASYNC:
dev->flags |= FASYNC;
return 0;
#ifdef __FreeBSD__
@ -1017,7 +1019,7 @@ int DRM(ioctl)(dev_t kdev, u_long cmd, caddr_t data, int flags,
#endif /* __NetBSD__ */
}
if (nr >= DRIVER_IOCTL_COUNT)
if (nr >= DRIVER_IOCTL_COUNT || IOCGROUP(cmd) != DRM_IOCTL_BASE)
return EINVAL;
ioctl = &DRM(ioctls)[nr];
@ -1059,12 +1061,8 @@ int DRM(lock)( DRM_IOCTL_ARGS )
return DRM_ERR(EINVAL);
#endif
DRM_LOCK();
for (;;) {
if (dev->lock.hw_lock == NULL) {
/* Device has been unregistered */
ret = DRM_ERR(EINTR);
break;
}
if (DRM(lock_take)(&dev->lock.hw_lock->lock, lock.context)) {
dev->lock.filp = (void *)DRM_CURRENTPID;
dev->lock.lock_time = jiffies;
@ -1073,11 +1071,17 @@ int DRM(lock)( DRM_IOCTL_ARGS )
}
/* Contention */
ret = tsleep((void *)&dev->lock.lock_queue, PZERO|PCATCH,
#if defined(__FreeBSD__) && __FreeBSD_version > 500000
ret = msleep((void *)&dev->lock.lock_queue, &dev->dev_lock,
PZERO | PCATCH, "drmlk2", 0);
#else
ret = tsleep((void *)&dev->lock.lock_queue, PZERO | PCATCH,
"drmlk2", 0);
#endif
if (ret != 0)
break;
}
DRM_UNLOCK();
DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
if (ret != 0)
@ -1110,6 +1114,7 @@ int DRM(unlock)( DRM_IOCTL_ARGS )
atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
DRM_LOCK();
DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT );
#if __HAVE_DMA_SCHEDULE
@ -1120,6 +1125,7 @@ int DRM(unlock)( DRM_IOCTL_ARGS )
DRM_KERNEL_CONTEXT ) ) {
DRM_ERROR( "\n" );
}
DRM_UNLOCK();
return 0;
}

View file

@ -33,6 +33,7 @@
#include "drmP.h"
/* Requires device lock held */
drm_file_t *DRM(find_file_by_proc)(drm_device_t *dev, DRM_STRUCTPROC *p)
{
#if __FreeBSD_version >= 500021
@ -50,8 +51,7 @@ drm_file_t *DRM(find_file_by_proc)(drm_device_t *dev, DRM_STRUCTPROC *p)
return NULL;
}
/* DRM(open) is called whenever a process opens /dev/drm. */
/* DRM(open_helper) is called whenever a process opens /dev/drm. */
int DRM(open_helper)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p,
drm_device_t *dev)
{
@ -64,12 +64,16 @@ int DRM(open_helper)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p,
DRM_DEBUG("pid = %d, minor = %d\n", DRM_CURRENTPID, m);
/* FIXME: linux mallocs and bzeros here */
DRM_LOCK();
priv = (drm_file_t *) DRM(find_file_by_proc)(dev, p);
if (priv) {
priv->refs++;
} else {
priv = (drm_file_t *) DRM(alloc)(sizeof(*priv), DRM_MEM_FILES);
if (priv == NULL) {
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
bzero(priv, sizeof(*priv));
#if __FreeBSD_version >= 500000
priv->uid = p->td_ucred->cr_svuid;
@ -84,10 +88,9 @@ int DRM(open_helper)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p,
priv->devXX = dev;
priv->ioctl_count = 0;
priv->authenticated = !DRM_SUSER(p);
DRM_LOCK();
TAILQ_INSERT_TAIL(&dev->files, priv, link);
DRM_UNLOCK();
}
DRM_UNLOCK();
#ifdef __FreeBSD__
kdev->si_drv1 = dev;
#endif

View file

@ -27,7 +27,19 @@
* Eric Anholt <anholt@FreeBSD.org>
*
*/
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
static irqreturn_t
DRM(irq_handler_wrap)(DRM_IRQ_ARGS)
{
drm_device_t *dev = (drm_device_t *)arg;
DRM_SPINLOCK(&dev->irq_lock);
DRM(irq_handler)(arg);
DRM_SPINUNLOCK(&dev->irq_lock);
}
#endif
int DRM(irq_install)( drm_device_t *dev, int irq )
{
int retcode;
@ -54,8 +66,9 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
TASK_INIT(&dev->task, 0, DRM(dma_immediate_bh), dev);
#endif
DRM_SPININIT(dev->irq_lock, "DRM IRQ lock");
#if __HAVE_VBL_IRQ && 0 /* disabled */
DRM_SPININIT( dev->vbl_lock, "vblsig" );
TAILQ_INIT( &dev->vbl_sig_list );
#endif
@ -72,6 +85,7 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
if (pci_intr_map(&dev->pa, &dev->ih) != 0) {
#endif
DRM_LOCK();
DRM_SPINUNINIT(dev->irq_lock);
dev->irq = 0;
dev->irqrid = 0;
DRM_UNLOCK();
@ -84,7 +98,7 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
DRM(irq_handler), dev, &dev->irqh);
#else
retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY | INTR_MPSAFE,
DRM(irq_handler), dev, &dev->irqh);
DRM(irq_handler_wrap), dev, &dev->irqh);
#endif
if ( retcode ) {
#elif defined(__NetBSD__)
@ -96,6 +110,7 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
#ifdef __FreeBSD__
bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, dev->irqr);
#endif
DRM_SPINUNINIT(dev->irq_lock);
dev->irq = 0;
dev->irqrid = 0;
DRM_UNLOCK();
@ -133,6 +148,7 @@ int DRM(irq_uninstall)( drm_device_t *dev )
#elif defined(__NetBSD__)
pci_intr_disestablish(&dev->pa.pa_pc, dev->irqh);
#endif
DRM_SPINUNINIT(dev->irq_lock);
return 0;
}
@ -187,9 +203,9 @@ int DRM(wait_vblank)( DRM_IOCTL_ARGS )
vblwait.reply.sequence = atomic_read(&dev->vbl_received);
DRM_SPINLOCK(&dev->vbl_lock);
DRM_SPINLOCK(&dev->irq_lock);
TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link);
DRM_SPINUNLOCK(&dev->vbl_lock);
DRM_SPINUNLOCK(&dev->irq_lock);
ret = 0;
#endif
ret = EINVAL;
@ -218,8 +234,6 @@ void DRM(vbl_send_signals)( drm_device_t *dev )
unsigned int vbl_seq = atomic_read( &dev->vbl_received );
struct proc *p;
DRM_SPINLOCK(&dev->vbl_lock);
vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list);
while (vbl_sig != NULL) {
drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link);
@ -234,8 +248,6 @@ void DRM(vbl_send_signals)( drm_device_t *dev )
}
vbl_sig = next;
}
DRM_SPINUNLOCK(&dev->vbl_lock);
}
#endif

View file

@ -123,15 +123,23 @@
#define DRM_SPINLOCK(l) mtx_lock(l)
#define DRM_SPINUNLOCK(u) mtx_unlock(u);
#define DRM_CURRENTPID curthread->td_proc->p_pid
#define DRM_LOCK() mtx_lock(&dev->dev_lock)
#define DRM_UNLOCK() mtx_unlock(&dev->dev_lock)
#else
/* There is no need for locking on FreeBSD 4.x. Synchronization is handled by
* the fact that there is no reentrancy of the kernel except for interrupt
* handlers, and the interrupt handler synchronization is managed by spls.
*/
#define DRM_CURPROC curproc
#define DRM_STRUCTPROC struct proc
#define DRM_SPINTYPE struct simplelock
#define DRM_SPININIT(l,name) simple_lock_init(&l)
#define DRM_SPINTYPE
#define DRM_SPININIT(l,name)
#define DRM_SPINUNINIT(l)
#define DRM_SPINLOCK(l) simple_lock(l)
#define DRM_SPINUNLOCK(u) simple_unlock(u);
#define DRM_SPINLOCK(l)
#define DRM_SPINUNLOCK(u)
#define DRM_CURRENTPID curproc->p_pid
#define DRM_LOCK()
#define DRM_UNLOCK()
#endif
/* Currently our DRMFILE (filp) is a void * which is actually the pid
@ -139,8 +147,6 @@
* code for that is not yet written */
#define DRMFILE void *
#define DRM_IOCTL_ARGS dev_t kdev, u_long cmd, caddr_t data, int flags, DRM_STRUCTPROC *p, DRMFILE filp
#define DRM_LOCK() lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, DRM_CURPROC)
#define DRM_UNLOCK() lockmgr(&dev->dev_lock, LK_RELEASE, 0, DRM_CURPROC)
#define DRM_SUSER(p) suser(p)
#define DRM_TASKQUEUE_ARGS void *arg, int pending
#define DRM_IRQ_ARGS void *arg
@ -165,13 +171,6 @@ typedef void irqreturn_t;
#define DRM_AGP_FIND_DEVICE() agp_find_device()
#define DRM_ERR(v) v
#define DRM_PRIV \
drm_file_t *priv = (drm_file_t *) DRM(find_file_by_proc)(dev, p); \
if (!priv) { \
DRM_DEBUG("can't find authenticator\n"); \
return EINVAL; \
}
#define LOCK_TEST_WITH_RETURN(dev, filp) \
do { \
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || \
@ -207,6 +206,16 @@ do { \
#define DRM_HZ hz
#if defined(__FreeBSD__) && __FreeBSD_version > 500000
#define DRM_WAIT_ON( ret, queue, timeout, condition ) \
for ( ret = 0 ; !ret && !(condition) ; ) { \
mtx_lock(&dev->irq_lock); \
if (!(condition)) \
ret = msleep(&(queue), &dev->irq_lock, \
PZERO | PCATCH, "drmwtq", (timeout)); \
mtx_unlock(&dev->irq_lock); \
}
#else
#define DRM_WAIT_ON( ret, queue, timeout, condition ) \
for ( ret = 0 ; !ret && !(condition) ; ) { \
int s = spldrm(); \
@ -215,6 +224,7 @@ for ( ret = 0 ; !ret && !(condition) ; ) { \
"drmwtq", (timeout) ); \
splx(s); \
}
#endif
#define DRM_WAKEUP( queue ) wakeup( queue )
#define DRM_WAKEUP_INT( queue ) wakeup( queue )

View file

@ -101,10 +101,10 @@ extern struct cfdriver DRM(cd);
#define DRM_CURPROC curproc
#define DRM_STRUCTPROC struct proc
#define DRM_SPINTYPE struct simplelock
#define DRM_SPININIT(l,name) simple_lock_init(&l)
#define DRM_SPININIT(l,name)
#define DRM_SPINUNINIT(l)
#define DRM_SPINLOCK(l) simple_lock(l)
#define DRM_SPINUNLOCK(u) simple_unlock(u);
#define DRM_SPINLOCK(l)
#define DRM_SPINUNLOCK(u)
#define DRM_CURRENTPID curproc->p_pid
/* Currently our DRMFILE (filp) is a void * which is actually the pid
@ -112,8 +112,8 @@ extern struct cfdriver DRM(cd);
* code for that is not yet written */
#define DRMFILE void *
#define DRM_IOCTL_ARGS dev_t kdev, u_long cmd, caddr_t data, int flags, DRM_STRUCTPROC *p, DRMFILE filp
#define DRM_LOCK() lockmgr(&dev->dev_lock, LK_EXCLUSIVE, NULL)
#define DRM_UNLOCK() lockmgr(&dev->dev_lock, LK_RELEASE, NULL)
#define DRM_LOCK()
#define DRM_UNLOCK()
#define DRM_SUSER(p) suser(p->p_ucred, &p->p_acflag)
#define DRM_TASKQUEUE_ARGS void *dev, int pending
#define DRM_IRQ_ARGS void *arg
@ -138,13 +138,6 @@ extern const int DRM(M_DRM) = M_DEVBUF;
#define DRM_AGP_FIND_DEVICE() agp_find_device(0)
#define DRM_PRIV \
drm_file_t *priv = (drm_file_t *) DRM(find_file_by_proc)(dev, p); \
if (!priv) { \
DRM_DEBUG("can't find authenticator\n"); \
return EINVAL; \
}
#define LOCK_TEST_WITH_RETURN(dev, filp) \
do { \
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || \
@ -182,9 +175,11 @@ do { \
#define DRM_WAIT_ON( ret, queue, timeout, condition ) \
while (!condition) { \
int s = spldrm(); \
ret = tsleep( (void *)&(queue), PZERO | PCATCH, "drmwtq", (timeout) ); \
if ( ret ) \
return ret; \
splx(s); \
}
#define DRM_ERR(v) v
@ -320,7 +315,7 @@ find_first_zero_bit(atomic_t *p, int max)
#define jiffies hardclock_ticks
/* Redefinitions to make templating easy */
#define wait_queue_head_t atomic_t
#define wait_queue_head_t int
#define agp_memory void
/* Macros to make printf easier */

View file

@ -44,7 +44,7 @@ DRM(pci_alloc)(drm_device_t *dev, size_t size, size_t align, dma_addr_t maxaddr,
{
void *vaddr;
vaddr = contigmalloc(size, DRM(M_DRM), M_WAITOK, 0ul, maxaddr, align,
vaddr = contigmalloc(size, DRM(M_DRM), M_NOWAIT, 0ul, maxaddr, align,
0);
*busaddr = vtophys(vaddr);

View file

@ -173,7 +173,7 @@ static int DRM(_vm_info)DRM_SYSCTL_HANDLER_ARGS
static int DRM(vm_info)DRM_SYSCTL_HANDLER_ARGS
{
drm_device_t *dev = arg1;
drm_device_t __unused *dev = arg1;
int ret;
DRM_LOCK();
@ -225,7 +225,7 @@ static int DRM(_bufs_info) DRM_SYSCTL_HANDLER_ARGS
static int DRM(bufs_info) DRM_SYSCTL_HANDLER_ARGS
{
drm_device_t *dev = arg1;
drm_device_t __unused *dev = arg1;
int ret;
DRM_LOCK();
@ -259,7 +259,7 @@ static int DRM(_clients_info) DRM_SYSCTL_HANDLER_ARGS
static int DRM(clients_info)DRM_SYSCTL_HANDLER_ARGS
{
drm_device_t *dev = arg1;
drm_device_t __unused *dev = arg1;
int ret;
DRM_LOCK();

View file

@ -65,7 +65,9 @@ paddr_t DRM(mmap)(dev_t kdev, off_t offset, int prot)
drm_map_list_entry_t *listentry = NULL;
drm_file_t *priv;
DRM_LOCK();
priv = DRM(find_file_by_proc)(dev, DRM_CURPROC);
DRM_UNLOCK();
if (!priv) {
DRM_DEBUG("can't find authenticator\n");
return EINVAL;

View file

@ -59,7 +59,7 @@ int DRM(ati_pcigart_init)( drm_device_t *dev,
}
address = (long)contigmalloc((1 << ATI_PCIGART_TABLE_ORDER) * PAGE_SIZE,
DRM(M_DRM), M_WAITOK, 0ul, 0xfffffffful, PAGE_SIZE, 0);
DRM(M_DRM), M_NOWAIT, 0ul, 0xfffffffful, PAGE_SIZE, 0);
if ( !address ) {
DRM_ERROR( "cannot allocate PCI GART page!\n" );
goto done;

View file

@ -180,7 +180,6 @@ typedef struct drm_freelist {
int low_mark; /* Low water mark */
int high_mark; /* High water mark */
DRM_SPINTYPE lock;
} drm_freelist_t;
typedef struct drm_buf_entry {
@ -216,10 +215,17 @@ struct drm_file {
typedef struct drm_lock_data {
drm_hw_lock_t *hw_lock; /* Hardware lock */
DRMFILE filp; /* Unique identifier of holding process (NULL is kernel)*/
wait_queue_head_t lock_queue; /* Queue of blocked processes */
int lock_queue; /* Queue of blocked processes */
unsigned long lock_time; /* Time of last lock in jiffies */
} drm_lock_data_t;
/* This structure, in the drm_device_t, 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.
*/
typedef struct drm_device_dma {
drm_buf_entry_t bufs[DRM_MAX_ORDER+1];
int buf_count;
@ -311,8 +317,15 @@ struct drm_device {
int flags; /* Flags to open(2) */
/* Locks */
DRM_SPINTYPE count_lock; /* For open_count, buf_use, buf_alloc */
struct lock dev_lock; /* For others */
#if defined(__FreeBSD__) && __FreeBSD_version > 500000
#if __HAVE_DMA
struct mtx dma_lock; /* protects dev->dma */
#endif
#if __HAVE_IRQ
struct mtx irq_lock; /* protects irq condition checks */
#endif
struct mtx dev_lock; /* protects everything else */
#endif
/* Usage Counters */
int open_count; /* Outstanding files open */
int buf_use; /* Buffers in use -- cannot alloc */
@ -327,8 +340,8 @@ struct drm_device {
drm_file_list_t files;
drm_magic_head_t magiclist[DRM_HASH_SIZE];
/* Memory management */
drm_map_list_t *maplist; /* Linked list of regions */
/* Linked list of mappable regions. Protected by dev_lock */
drm_map_list_t *maplist;
drm_local_map_t **context_sareas;
int max_context;
@ -349,18 +362,13 @@ struct drm_device {
#endif
void *irqh; /* Handle from bus_setup_intr */
atomic_t context_flag; /* Context swapping flag */
struct callout timer; /* Timer for delaying ctx switch */
int last_context; /* Last current context */
#if __FreeBSD_version >= 400005
struct task task;
#endif
#if __HAVE_VBL_IRQ
wait_queue_head_t vbl_queue; /* vbl wait channel */
int vbl_queue; /* vbl wait channel */
atomic_t vbl_received;
#if 0 /* vbl signals are untested */
struct drm_vbl_sig_list vbl_sig_list;
DRM_SPINTYPE vbl_lock;
#endif
#endif
#ifdef __FreeBSD__
@ -382,11 +390,6 @@ struct drm_device {
extern int DRM(flags);
/* Authentication (drm_auth.h) */
extern int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv,
drm_magic_t magic);
extern int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic);
/* Driver support (drm_drv.h) */
extern int DRM(version)( DRM_IOCTL_ARGS );

View file

@ -54,7 +54,7 @@ static drm_file_t *DRM(find_file)(drm_device_t *dev, drm_magic_t magic)
return retval;
}
int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
static int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
{
int hash;
drm_magic_entry_t *entry;
@ -82,7 +82,7 @@ int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
return 0;
}
int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic)
static int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic)
{
drm_magic_entry_t *prev = NULL;
drm_magic_entry_t *pt;
@ -116,9 +116,17 @@ int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic)
int DRM(getmagic)(DRM_IOCTL_ARGS)
{
static drm_magic_t sequence = 0;
drm_auth_t auth;
drm_auth_t auth;
drm_file_t *priv;
DRM_DEVICE;
DRM_PRIV;
DRM_LOCK();
priv = (drm_file_t *) DRM(find_file_by_proc)(dev, p);
DRM_UNLOCK();
if (priv == NULL) {
DRM_DEBUG("can't find authenticator\n");
return EINVAL;
}
/* Find unique magic */
if (priv->magic) {
@ -152,6 +160,7 @@ int DRM(authmagic)(DRM_IOCTL_ARGS)
DRM_COPY_FROM_USER_IOCTL(auth, (drm_auth_t *)data, sizeof(auth));
DRM_DEBUG("%u\n", auth.magic);
if ((file = DRM(find_file)(dev, auth.magic))) {
file->authenticated = 1;
DRM(remove_magic)(dev, auth.magic);

View file

@ -226,6 +226,8 @@ int DRM(rmmap)( DRM_IOCTL_ARGS )
return DRM_ERR(EINVAL);
}
TAILQ_REMOVE(dev->maplist, list, link);
DRM_UNLOCK();
DRM(free)(list, sizeof(*list), DRM_MEM_MAPS);
switch (map->type) {
@ -268,7 +270,6 @@ int DRM(rmmap)( DRM_IOCTL_ARGS )
break;
}
DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
DRM_UNLOCK();
return 0;
}
@ -350,20 +351,11 @@ static int DRM(addbufs_agp)(drm_device_t *dev, drm_buf_desc_t *request)
DRM_DEBUG( "page_order: %d\n", page_order );
DRM_DEBUG( "total: %d\n", total );
if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER )
return DRM_ERR(EINVAL);
DRM_LOCK();
entry = &dma->bufs[order];
if ( entry->buf_count ) {
DRM_UNLOCK();
return DRM_ERR(ENOMEM); /* May only call once for each order */
}
entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist),
DRM_MEM_BUFS );
if ( !entry->buflist ) {
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
@ -394,7 +386,6 @@ static int DRM(addbufs_agp)(drm_device_t *dev, drm_buf_desc_t *request)
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
DRM(cleanup_buf_error)(dev, entry);
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
@ -413,7 +404,6 @@ static int DRM(addbufs_agp)(drm_device_t *dev, drm_buf_desc_t *request)
if (temp_buflist == NULL) {
/* Free the entry because it isn't valid */
DRM(cleanup_buf_error)(dev, entry);
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
dma->buflist = temp_buflist;
@ -428,8 +418,6 @@ static int DRM(addbufs_agp)(drm_device_t *dev, drm_buf_desc_t *request)
DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
DRM_UNLOCK();
request->count = entry->buf_count;
request->size = size;
@ -467,20 +455,12 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
DRM_DEBUG( "count=%d, size=%d (%d), order=%d\n",
request->count, request->size, size, order );
if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER )
return DRM_ERR(EINVAL);
alignment = (request->flags & _DRM_PAGE_ALIGN)
? round_page(size) : size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;
DRM_LOCK();
entry = &dma->bufs[order];
if ( entry->buf_count ) {
DRM_UNLOCK();
return DRM_ERR(ENOMEM); /* May only call once for each order */
}
entry->buflist = DRM(alloc)(count * sizeof(*entry->buflist),
DRM_MEM_BUFS);
@ -503,7 +483,6 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
DRM_MEM_SEGS);
DRM(free)(entry->seglist_bus, count *
sizeof(*entry->seglist_bus), DRM_MEM_SEGS);
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
@ -532,7 +511,6 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
DRM(free)(temp_pagelist, (dma->page_count +
(count << page_order)) * sizeof(*dma->pagelist),
DRM_MEM_PAGES);
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
@ -571,7 +549,6 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
DRM(free)(temp_pagelist, (dma->page_count +
(count << page_order)) *
sizeof(*dma->pagelist), DRM_MEM_PAGES );
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
bzero(buf->dev_private, buf->dev_priv_size);
@ -593,7 +570,6 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
DRM(free)(temp_pagelist, (dma->page_count +
(count << page_order)) * sizeof(*dma->pagelist),
DRM_MEM_PAGES);
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
dma->buflist = temp_buflist;
@ -614,8 +590,6 @@ static int DRM(addbufs_pci)(drm_device_t *dev, drm_buf_desc_t *request)
dma->page_count += entry->seg_count << page_order;
dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
DRM_UNLOCK();
request->count = entry->buf_count;
request->size = size;
@ -662,23 +636,12 @@ static int DRM(addbufs_sg)(drm_device_t *dev, drm_buf_desc_t *request)
DRM_DEBUG( "page_order: %d\n", page_order );
DRM_DEBUG( "total: %d\n", total );
if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER )
return DRM_ERR(EINVAL);
DRM_LOCK();
entry = &dma->bufs[order];
if ( entry->buf_count ) {
DRM_UNLOCK();
return DRM_ERR(ENOMEM); /* May only call once for each order */
}
entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist),
DRM_MEM_BUFS );
if ( !entry->buflist ) {
DRM_UNLOCK();
entry->buflist = DRM(calloc)(1, count * sizeof(*entry->buflist),
DRM_MEM_BUFS);
if (entry->buflist == NULL)
return DRM_ERR(ENOMEM);
}
memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
entry->buf_size = size;
entry->page_order = page_order;
@ -706,7 +669,6 @@ static int DRM(addbufs_sg)(drm_device_t *dev, drm_buf_desc_t *request)
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
DRM(cleanup_buf_error)(dev, entry);
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
@ -728,7 +690,6 @@ static int DRM(addbufs_sg)(drm_device_t *dev, drm_buf_desc_t *request)
if (temp_buflist == NULL) {
/* Free the entry because it isn't valid */
DRM(cleanup_buf_error)(dev, entry);
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
dma->buflist = temp_buflist;
@ -743,8 +704,6 @@ static int DRM(addbufs_sg)(drm_device_t *dev, drm_buf_desc_t *request)
DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
DRM_UNLOCK();
request->count = entry->buf_count;
request->size = size;
@ -759,25 +718,28 @@ int DRM(addbufs)( DRM_IOCTL_ARGS )
DRM_DEVICE;
drm_buf_desc_t request;
int err;
int order;
DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_desc_t *)data, sizeof(request) );
if (dev->dma == NULL)
return DRM_ERR(EINVAL);
if (request.count < 0 || request.count > 4096)
return DRM_ERR(EINVAL);
DRM_SPINLOCK(&dev->count_lock);
if (dev->buf_use) {
DRM_SPINUNLOCK(&dev->count_lock);
order = DRM(order)(request.size);
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
return DRM_ERR(EINVAL);
DRM_SPINLOCK(&dev->dma_lock);
/* No more allocations after first buffer-using ioctl. */
if (dev->buf_use != 0) {
DRM_SPINUNLOCK(&dev->dma_lock);
return DRM_ERR(EBUSY);
}
/* dev->buf_alloc acts as a lock to prevent infobufs/mapbufs from
* trying to read from the dma->bufs while buffers are being allocated */
dev->buf_alloc++;
DRM_SPINUNLOCK(&dev->count_lock);
/* No more than one allocation per order */
if (dev->dma->bufs[order].buf_count != 0) {
DRM_SPINUNLOCK(&dev->dma_lock);
return DRM_ERR(ENOMEM);
}
#if __REALLY_HAVE_AGP
if ( request.flags & _DRM_AGP_BUFFER )
@ -794,13 +756,10 @@ int DRM(addbufs)( DRM_IOCTL_ARGS )
#else
err = DRM_ERR(EINVAL);
#endif
DRM_SPINUNLOCK(&dev->dma_lock);
DRM_COPY_TO_USER_IOCTL((drm_buf_desc_t *)data, request, sizeof(request));
DRM_SPINLOCK(&dev->count_lock);
dev->buf_alloc--;
DRM_SPINUNLOCK(&dev->count_lock);
return err;
}
@ -811,19 +770,14 @@ int DRM(infobufs)( DRM_IOCTL_ARGS )
drm_buf_info_t request;
int i;
int count;
if ( !dma ) return DRM_ERR(EINVAL);
DRM_SPINLOCK( &dev->count_lock );
if (dev->buf_alloc != 0) {
DRM_SPINUNLOCK( &dev->count_lock );
return DRM_ERR(EBUSY);
}
++dev->buf_use; /* Can't allocate more after this call */
DRM_SPINUNLOCK( &dev->count_lock );
int retcode = 0;
DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_info_t *)data, sizeof(request) );
DRM_SPINLOCK(&dev->dma_lock);
++dev->buf_use; /* Can't allocate more after this call */
DRM_SPINUNLOCK(&dev->dma_lock);
for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) {
if ( dma->bufs[i].buf_count ) ++count;
}
@ -841,8 +795,10 @@ int DRM(infobufs)( DRM_IOCTL_ARGS )
from.high_mark = dma->bufs[i].freelist.high_mark;
if (DRM_COPY_TO_USER(&request.list[count], &from,
sizeof(drm_buf_desc_t)) != 0)
return DRM_ERR(EFAULT);
sizeof(drm_buf_desc_t)) != 0) {
retcode = DRM_ERR(EFAULT);
break;
}
DRM_DEBUG( "%d %d %d %d %d\n",
i,
@ -858,7 +814,7 @@ int DRM(infobufs)( DRM_IOCTL_ARGS )
DRM_COPY_TO_USER_IOCTL( (drm_buf_info_t *)data, request, sizeof(request) );
return 0;
return retcode;
}
int DRM(markbufs)( DRM_IOCTL_ARGS )
@ -867,26 +823,28 @@ int DRM(markbufs)( DRM_IOCTL_ARGS )
drm_device_dma_t *dma = dev->dma;
drm_buf_desc_t request;
int order;
drm_buf_entry_t *entry;
if ( !dma ) return DRM_ERR(EINVAL);
DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_desc_t *)data, sizeof(request) );
DRM_DEBUG( "%d, %d, %d\n",
request.size, request.low_mark, request.high_mark );
order = DRM(order)( request.size );
if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER )
return DRM_ERR(EINVAL);
entry = &dma->bufs[order];
if ( request.low_mark < 0 || request.low_mark > entry->buf_count )
return DRM_ERR(EINVAL);
if ( request.high_mark < 0 || request.high_mark > entry->buf_count )
order = DRM(order)(request.size);
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ||
request.low_mark < 0 || request.high_mark < 0) {
return DRM_ERR(EINVAL);
}
entry->freelist.low_mark = request.low_mark;
entry->freelist.high_mark = request.high_mark;
DRM_SPINLOCK(&dev->dma_lock);
if (request.low_mark > dma->bufs[order].buf_count ||
request.high_mark > dma->bufs[order].buf_count) {
return DRM_ERR(EINVAL);
}
dma->bufs[order].freelist.low_mark = request.low_mark;
dma->bufs[order].freelist.high_mark = request.high_mark;
DRM_SPINUNLOCK(&dev->dma_lock);
return 0;
}
@ -899,32 +857,36 @@ int DRM(freebufs)( DRM_IOCTL_ARGS )
int i;
int idx;
drm_buf_t *buf;
if ( !dma ) return DRM_ERR(EINVAL);
int retcode = 0;
DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_free_t *)data, sizeof(request) );
DRM_DEBUG( "%d\n", request.count );
DRM_SPINLOCK(&dev->dma_lock);
for ( i = 0 ; i < request.count ; i++ ) {
if ( DRM_COPY_FROM_USER( &idx,
&request.list[i],
sizeof(idx) ) )
return DRM_ERR(EFAULT);
if (DRM_COPY_FROM_USER(&idx, &request.list[i], sizeof(idx))) {
retcode = DRM_ERR(EFAULT);
break;
}
if ( idx < 0 || idx >= dma->buf_count ) {
DRM_ERROR( "Index %d (of %d max)\n",
idx, dma->buf_count - 1 );
return DRM_ERR(EINVAL);
retcode = DRM_ERR(EINVAL);
break;
}
buf = dma->buflist[idx];
if ( buf->filp != filp ) {
DRM_ERROR("Process %d freeing buffer not owned\n",
DRM_CURRENTPID);
return DRM_ERR(EINVAL);
retcode = DRM_ERR(EINVAL);
break;
}
DRM(free_buffer)( dev, buf );
}
DRM_SPINUNLOCK(&dev->dma_lock);
return 0;
return retcode;
}
int DRM(mapbufs)( DRM_IOCTL_ARGS )
@ -949,16 +911,6 @@ int DRM(mapbufs)( DRM_IOCTL_ARGS )
drm_buf_map_t request;
int i;
if ( !dma ) return DRM_ERR(EINVAL);
DRM_SPINLOCK( &dev->count_lock );
if (dev->buf_alloc != 0) {
DRM_SPINUNLOCK( &dev->count_lock );
return DRM_ERR(EBUSY);
}
dev->buf_use++; /* Can't allocate more after this call */
DRM_SPINUNLOCK( &dev->count_lock );
DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_map_t *)data, sizeof(request) );
#ifdef __NetBSD__
@ -972,6 +924,10 @@ int DRM(mapbufs)( DRM_IOCTL_ARGS )
vms = p->p_vmspace;
#endif
DRM_SPINLOCK(&dev->dma_lock);
dev->buf_use++; /* Can't allocate more after this call */
DRM_SPINUNLOCK(&dev->dma_lock);
if (request.count < dma->buf_count)
goto done;
@ -1040,4 +996,3 @@ int DRM(mapbufs)( DRM_IOCTL_ARGS )
}
#endif /* __HAVE_DMA */

View file

@ -51,6 +51,8 @@ int DRM(dma_setup)( drm_device_t *dev )
if (dev->dma == NULL)
return DRM_ERR(ENOMEM);
DRM_SPININIT(dev->dma_lock, "drmdma");
return 0;
}
@ -59,7 +61,8 @@ void DRM(dma_takedown)(drm_device_t *dev)
drm_device_dma_t *dma = dev->dma;
int i, j;
if (!dma) return;
if (dma == NULL)
return;
/* Clear dma buffers */
for (i = 0; i <= DRM_MAX_ORDER; i++) {
@ -106,6 +109,7 @@ void DRM(dma_takedown)(drm_device_t *dev)
DRM_MEM_PAGES);
DRM(free)(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
dev->dma = NULL;
DRM_SPINUNINIT(dev->dma_lock);
}

View file

@ -111,7 +111,7 @@ int DRM(flags) = 0;
#endif
static int DRM(init)(device_t nbdev);
static void DRM(cleanup)(device_t nbdev);
static void DRM(cleanup)(drm_device_t *dev);
#ifdef __FreeBSD__
#define DRIVER_SOFTC(unit) \
@ -253,7 +253,7 @@ static int DRM(attach)(device_t dev)
static int DRM(detach)(device_t dev)
{
DRM(cleanup)(dev);
DRM(cleanup)(device_get_softc(dev));
return 0;
}
static device_method_t DRM(methods)[] = {
@ -411,6 +411,7 @@ const char *DRM(find_description)(int vendor, int device) {
return NULL;
}
/* Initialize the DRM on first open. Called with device's lock held */
static int DRM(setup)( drm_device_t *dev )
{
int i;
@ -421,7 +422,7 @@ static int DRM(setup)( drm_device_t *dev )
#if __HAVE_DMA
i = DRM(dma_setup)( dev );
if ( i < 0 )
if ( i != 0 )
return i;
#endif
@ -481,11 +482,6 @@ static int DRM(setup)( drm_device_t *dev )
dev->irq = 0;
dev->context_flag = 0;
dev->last_context = 0;
#if __FreeBSD_version >= 500000
callout_init( &dev->timer, 1 );
#else
callout_init( &dev->timer );
#endif
#ifdef __FreeBSD__
dev->buf_sigio = NULL;
@ -499,7 +495,9 @@ static int DRM(setup)( drm_device_t *dev )
return 0;
}
/* Free resources associated with the DRM on the last close.
* Called with the device's lock held.
*/
static int DRM(takedown)( drm_device_t *dev )
{
drm_magic_entry_t *pt, *next;
@ -515,9 +513,6 @@ static int DRM(takedown)( drm_device_t *dev )
DRM(irq_uninstall)( dev );
#endif
DRM_LOCK();
callout_stop( &dev->timer );
if ( dev->unique ) {
DRM(free)( dev->unique, strlen( dev->unique ) + 1,
DRM_MEM_DRIVER );
@ -540,7 +535,7 @@ static int DRM(takedown)( drm_device_t *dev )
drm_agp_mem_t *nexte;
/* Remove AGP resources, but leave dev->agp
intact until drv_cleanup is called. */
intact until DRM(cleanup) is called. */
for ( entry = dev->agp->memory ; entry ; entry = nexte ) {
nexte = entry->next;
if ( entry->bound ) DRM(unbind_agp)( entry->handle );
@ -625,7 +620,6 @@ static int DRM(takedown)( drm_device_t *dev )
dev->lock.filp = NULL;
DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
}
DRM_UNLOCK();
return 0;
}
@ -664,11 +658,12 @@ static int DRM(init)( device_t nbdev )
DRM_DEV_GID,
DRM_DEV_MODE,
"dri/card%d", unit );
#if __FreeBSD_version >= 500000
mtx_init(&dev->dev_lock, "drm device", NULL, MTX_DEF);
#endif
#elif defined(__NetBSD__)
unit = minor(dev->device.dv_unit);
#endif
DRM_SPININIT(dev->count_lock, "drm device");
lockinit(&dev->dev_lock, PZERO, "drmlk", 0, 0);
dev->name = DRIVER_NAME;
DRM(mem_init)();
DRM(sysctl_init)(dev);
@ -679,12 +674,8 @@ static int DRM(init)( device_t nbdev )
#if __MUST_HAVE_AGP
if ( dev->agp == NULL ) {
DRM_ERROR( "Cannot initialize the agpgart module.\n" );
DRM(sysctl_cleanup)( dev );
#ifdef __FreeBSD__
destroy_dev(dev->devnode);
#endif
DRM(takedown)( dev );
return DRM_ERR(ENOMEM);
retcode = DRM_ERR(ENOMEM);
goto error;
}
#endif /* __MUST_HAVE_AGP */
#if __REALLY_HAVE_MTRR
@ -716,12 +707,7 @@ static int DRM(init)( device_t nbdev )
retcode = DRM(ctxbitmap_init)( dev );
if (retcode != 0) {
DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
DRM(sysctl_cleanup)( dev );
#ifdef __FreeBSD__
destroy_dev(dev->devnode);
#endif
DRM(takedown)( dev );
return retcode;
goto error;
}
#endif
DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
@ -735,28 +721,36 @@ static int DRM(init)( device_t nbdev )
DRIVER_POSTINIT();
return 0;
error:
DRM(sysctl_cleanup)(dev);
DRM_LOCK();
DRM(takedown)(dev);
DRM_UNLOCK();
#ifdef __FreeBSD__
destroy_dev(dev->devnode);
#if __FreeBSD_version >= 500000
mtx_destroy(&dev->dev_lock);
#endif
#endif
return retcode;
}
/* linux: drm_cleanup is called via cleanup_module at module unload time.
* bsd: drm_cleanup is called per device at module unload time.
* FIXME: NetBSD
*/
static void DRM(cleanup)(device_t nbdev)
static void DRM(cleanup)(drm_device_t *dev)
{
drm_device_t *dev;
#ifdef __NetBSD__
#if __REALLY_HAVE_MTRR
struct mtrr mtrrmap;
int one = 1;
#endif /* __REALLY_HAVE_MTRR */
dev = nbdev;
#endif /* __NetBSD__ */
DRM_DEBUG( "\n" );
#ifdef __FreeBSD__
dev = device_get_softc(nbdev);
#endif
DRM(sysctl_cleanup)( dev );
#ifdef __FreeBSD__
destroy_dev(dev->devnode);
@ -777,7 +771,9 @@ static void DRM(cleanup)(device_t nbdev)
}
#endif
DRM_LOCK();
DRM(takedown)( dev );
DRM_UNLOCK();
#if __REALLY_HAVE_AGP
if ( dev->agp ) {
@ -788,7 +784,9 @@ static void DRM(cleanup)(device_t nbdev)
#endif
DRIVER_POSTCLEANUP();
DRM(mem_uninit)();
DRM_SPINUNINIT(dev->count_lock);
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
mtx_destroy(&dev->dev_lock);
#endif
}
@ -834,13 +832,13 @@ int DRM(open)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
if ( !retcode ) {
atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
DRM_SPINLOCK( &dev->count_lock );
DRM_LOCK();
#ifdef __FreeBSD__
device_busy(dev->device);
#endif
if ( !dev->open_count++ )
retcode = DRM(setup)( dev );
DRM_SPINUNLOCK( &dev->count_lock );
DRM_UNLOCK();
}
return retcode;
@ -854,8 +852,12 @@ int DRM(close)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
DRMFILE filp = (void *)(DRM_CURRENTPID);
DRM_DEBUG( "open_count = %d\n", dev->open_count );
DRM_LOCK();
priv = DRM(find_file_by_proc)(dev, p);
if (!priv) {
DRM_UNLOCK();
DRM_DEBUG("can't find authenticator\n");
return EINVAL;
}
@ -908,10 +910,13 @@ int DRM(close)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
break; /* Got lock */
}
/* Contention */
#if defined(__FreeBSD__) && __FreeBSD_version > 500000
retcode = msleep((void *)&dev->lock.lock_queue,
dev->dev_lock, PZERO | PCATCH, "drmlk2", 0);
#else
retcode = tsleep((void *)&dev->lock.lock_queue,
PZERO|PCATCH,
"drmlk2",
0);
PZERO | PCATCH, "drmlk2", 0);
#endif
if (retcode)
break;
}
@ -933,32 +938,24 @@ int DRM(close)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
dev->buf_pgid = 0;
#endif /* __NetBSD__ */
DRM_LOCK();
priv = DRM(find_file_by_proc)(dev, p);
if (priv) {
priv->refs--;
if (!priv->refs) {
TAILQ_REMOVE(&dev->files, priv, link);
DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES );
}
if (--priv->refs == 0) {
TAILQ_REMOVE(&dev->files, priv, link);
DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES );
}
DRM_UNLOCK();
/* ========================================================
* End inline drm_release
*/
atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
DRM_SPINLOCK( &dev->count_lock );
#ifdef __FreeBSD__
device_unbusy(dev->device);
#endif
if ( !--dev->open_count ) {
DRM_SPINUNLOCK( &dev->count_lock );
return DRM(takedown)( dev );
if (--dev->open_count == 0) {
retcode = DRM(takedown)(dev);
}
DRM_SPINUNLOCK( &dev->count_lock );
DRM_UNLOCK();
return retcode;
}
@ -973,7 +970,15 @@ int DRM(ioctl)(dev_t kdev, u_long cmd, caddr_t data, int flags,
drm_ioctl_desc_t *ioctl;
int (*func)(DRM_IOCTL_ARGS);
int nr = DRM_IOCTL_NR(cmd);
DRM_PRIV;
drm_file_t *priv;
DRM_LOCK();
priv = (drm_file_t *) DRM(find_file_by_proc)(dev, p);
DRM_UNLOCK();
if (priv == NULL) {
DRM_DEBUG("can't find authenticator\n");
return EINVAL;
}
atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
++priv->ioctl_count;
@ -988,10 +993,7 @@ int DRM(ioctl)(dev_t kdev, u_long cmd, caddr_t data, int flags,
switch (cmd) {
case FIONBIO:
return 0;
case FIOASYNC:
dev->flags |= FASYNC;
return 0;
#ifdef __FreeBSD__
@ -1017,7 +1019,7 @@ int DRM(ioctl)(dev_t kdev, u_long cmd, caddr_t data, int flags,
#endif /* __NetBSD__ */
}
if (nr >= DRIVER_IOCTL_COUNT)
if (nr >= DRIVER_IOCTL_COUNT || IOCGROUP(cmd) != DRM_IOCTL_BASE)
return EINVAL;
ioctl = &DRM(ioctls)[nr];
@ -1059,12 +1061,8 @@ int DRM(lock)( DRM_IOCTL_ARGS )
return DRM_ERR(EINVAL);
#endif
DRM_LOCK();
for (;;) {
if (dev->lock.hw_lock == NULL) {
/* Device has been unregistered */
ret = DRM_ERR(EINTR);
break;
}
if (DRM(lock_take)(&dev->lock.hw_lock->lock, lock.context)) {
dev->lock.filp = (void *)DRM_CURRENTPID;
dev->lock.lock_time = jiffies;
@ -1073,11 +1071,17 @@ int DRM(lock)( DRM_IOCTL_ARGS )
}
/* Contention */
ret = tsleep((void *)&dev->lock.lock_queue, PZERO|PCATCH,
#if defined(__FreeBSD__) && __FreeBSD_version > 500000
ret = msleep((void *)&dev->lock.lock_queue, &dev->dev_lock,
PZERO | PCATCH, "drmlk2", 0);
#else
ret = tsleep((void *)&dev->lock.lock_queue, PZERO | PCATCH,
"drmlk2", 0);
#endif
if (ret != 0)
break;
}
DRM_UNLOCK();
DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
if (ret != 0)
@ -1110,6 +1114,7 @@ int DRM(unlock)( DRM_IOCTL_ARGS )
atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
DRM_LOCK();
DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT );
#if __HAVE_DMA_SCHEDULE
@ -1120,6 +1125,7 @@ int DRM(unlock)( DRM_IOCTL_ARGS )
DRM_KERNEL_CONTEXT ) ) {
DRM_ERROR( "\n" );
}
DRM_UNLOCK();
return 0;
}

View file

@ -33,6 +33,7 @@
#include "drmP.h"
/* Requires device lock held */
drm_file_t *DRM(find_file_by_proc)(drm_device_t *dev, DRM_STRUCTPROC *p)
{
#if __FreeBSD_version >= 500021
@ -50,8 +51,7 @@ drm_file_t *DRM(find_file_by_proc)(drm_device_t *dev, DRM_STRUCTPROC *p)
return NULL;
}
/* DRM(open) is called whenever a process opens /dev/drm. */
/* DRM(open_helper) is called whenever a process opens /dev/drm. */
int DRM(open_helper)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p,
drm_device_t *dev)
{
@ -64,12 +64,16 @@ int DRM(open_helper)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p,
DRM_DEBUG("pid = %d, minor = %d\n", DRM_CURRENTPID, m);
/* FIXME: linux mallocs and bzeros here */
DRM_LOCK();
priv = (drm_file_t *) DRM(find_file_by_proc)(dev, p);
if (priv) {
priv->refs++;
} else {
priv = (drm_file_t *) DRM(alloc)(sizeof(*priv), DRM_MEM_FILES);
if (priv == NULL) {
DRM_UNLOCK();
return DRM_ERR(ENOMEM);
}
bzero(priv, sizeof(*priv));
#if __FreeBSD_version >= 500000
priv->uid = p->td_ucred->cr_svuid;
@ -84,10 +88,9 @@ int DRM(open_helper)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p,
priv->devXX = dev;
priv->ioctl_count = 0;
priv->authenticated = !DRM_SUSER(p);
DRM_LOCK();
TAILQ_INSERT_TAIL(&dev->files, priv, link);
DRM_UNLOCK();
}
DRM_UNLOCK();
#ifdef __FreeBSD__
kdev->si_drv1 = dev;
#endif

View file

@ -27,7 +27,19 @@
* Eric Anholt <anholt@FreeBSD.org>
*
*/
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
static irqreturn_t
DRM(irq_handler_wrap)(DRM_IRQ_ARGS)
{
drm_device_t *dev = (drm_device_t *)arg;
DRM_SPINLOCK(&dev->irq_lock);
DRM(irq_handler)(arg);
DRM_SPINUNLOCK(&dev->irq_lock);
}
#endif
int DRM(irq_install)( drm_device_t *dev, int irq )
{
int retcode;
@ -54,8 +66,9 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
TASK_INIT(&dev->task, 0, DRM(dma_immediate_bh), dev);
#endif
DRM_SPININIT(dev->irq_lock, "DRM IRQ lock");
#if __HAVE_VBL_IRQ && 0 /* disabled */
DRM_SPININIT( dev->vbl_lock, "vblsig" );
TAILQ_INIT( &dev->vbl_sig_list );
#endif
@ -72,6 +85,7 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
if (pci_intr_map(&dev->pa, &dev->ih) != 0) {
#endif
DRM_LOCK();
DRM_SPINUNINIT(dev->irq_lock);
dev->irq = 0;
dev->irqrid = 0;
DRM_UNLOCK();
@ -84,7 +98,7 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
DRM(irq_handler), dev, &dev->irqh);
#else
retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY | INTR_MPSAFE,
DRM(irq_handler), dev, &dev->irqh);
DRM(irq_handler_wrap), dev, &dev->irqh);
#endif
if ( retcode ) {
#elif defined(__NetBSD__)
@ -96,6 +110,7 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
#ifdef __FreeBSD__
bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, dev->irqr);
#endif
DRM_SPINUNINIT(dev->irq_lock);
dev->irq = 0;
dev->irqrid = 0;
DRM_UNLOCK();
@ -133,6 +148,7 @@ int DRM(irq_uninstall)( drm_device_t *dev )
#elif defined(__NetBSD__)
pci_intr_disestablish(&dev->pa.pa_pc, dev->irqh);
#endif
DRM_SPINUNINIT(dev->irq_lock);
return 0;
}
@ -187,9 +203,9 @@ int DRM(wait_vblank)( DRM_IOCTL_ARGS )
vblwait.reply.sequence = atomic_read(&dev->vbl_received);
DRM_SPINLOCK(&dev->vbl_lock);
DRM_SPINLOCK(&dev->irq_lock);
TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link);
DRM_SPINUNLOCK(&dev->vbl_lock);
DRM_SPINUNLOCK(&dev->irq_lock);
ret = 0;
#endif
ret = EINVAL;
@ -218,8 +234,6 @@ void DRM(vbl_send_signals)( drm_device_t *dev )
unsigned int vbl_seq = atomic_read( &dev->vbl_received );
struct proc *p;
DRM_SPINLOCK(&dev->vbl_lock);
vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list);
while (vbl_sig != NULL) {
drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link);
@ -234,8 +248,6 @@ void DRM(vbl_send_signals)( drm_device_t *dev )
}
vbl_sig = next;
}
DRM_SPINUNLOCK(&dev->vbl_lock);
}
#endif

View file

@ -123,15 +123,23 @@
#define DRM_SPINLOCK(l) mtx_lock(l)
#define DRM_SPINUNLOCK(u) mtx_unlock(u);
#define DRM_CURRENTPID curthread->td_proc->p_pid
#define DRM_LOCK() mtx_lock(&dev->dev_lock)
#define DRM_UNLOCK() mtx_unlock(&dev->dev_lock)
#else
/* There is no need for locking on FreeBSD 4.x. Synchronization is handled by
* the fact that there is no reentrancy of the kernel except for interrupt
* handlers, and the interrupt handler synchronization is managed by spls.
*/
#define DRM_CURPROC curproc
#define DRM_STRUCTPROC struct proc
#define DRM_SPINTYPE struct simplelock
#define DRM_SPININIT(l,name) simple_lock_init(&l)
#define DRM_SPINTYPE
#define DRM_SPININIT(l,name)
#define DRM_SPINUNINIT(l)
#define DRM_SPINLOCK(l) simple_lock(l)
#define DRM_SPINUNLOCK(u) simple_unlock(u);
#define DRM_SPINLOCK(l)
#define DRM_SPINUNLOCK(u)
#define DRM_CURRENTPID curproc->p_pid
#define DRM_LOCK()
#define DRM_UNLOCK()
#endif
/* Currently our DRMFILE (filp) is a void * which is actually the pid
@ -139,8 +147,6 @@
* code for that is not yet written */
#define DRMFILE void *
#define DRM_IOCTL_ARGS dev_t kdev, u_long cmd, caddr_t data, int flags, DRM_STRUCTPROC *p, DRMFILE filp
#define DRM_LOCK() lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, DRM_CURPROC)
#define DRM_UNLOCK() lockmgr(&dev->dev_lock, LK_RELEASE, 0, DRM_CURPROC)
#define DRM_SUSER(p) suser(p)
#define DRM_TASKQUEUE_ARGS void *arg, int pending
#define DRM_IRQ_ARGS void *arg
@ -165,13 +171,6 @@ typedef void irqreturn_t;
#define DRM_AGP_FIND_DEVICE() agp_find_device()
#define DRM_ERR(v) v
#define DRM_PRIV \
drm_file_t *priv = (drm_file_t *) DRM(find_file_by_proc)(dev, p); \
if (!priv) { \
DRM_DEBUG("can't find authenticator\n"); \
return EINVAL; \
}
#define LOCK_TEST_WITH_RETURN(dev, filp) \
do { \
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || \
@ -207,6 +206,16 @@ do { \
#define DRM_HZ hz
#if defined(__FreeBSD__) && __FreeBSD_version > 500000
#define DRM_WAIT_ON( ret, queue, timeout, condition ) \
for ( ret = 0 ; !ret && !(condition) ; ) { \
mtx_lock(&dev->irq_lock); \
if (!(condition)) \
ret = msleep(&(queue), &dev->irq_lock, \
PZERO | PCATCH, "drmwtq", (timeout)); \
mtx_unlock(&dev->irq_lock); \
}
#else
#define DRM_WAIT_ON( ret, queue, timeout, condition ) \
for ( ret = 0 ; !ret && !(condition) ; ) { \
int s = spldrm(); \
@ -215,6 +224,7 @@ for ( ret = 0 ; !ret && !(condition) ; ) { \
"drmwtq", (timeout) ); \
splx(s); \
}
#endif
#define DRM_WAKEUP( queue ) wakeup( queue )
#define DRM_WAKEUP_INT( queue ) wakeup( queue )

View file

@ -101,10 +101,10 @@ extern struct cfdriver DRM(cd);
#define DRM_CURPROC curproc
#define DRM_STRUCTPROC struct proc
#define DRM_SPINTYPE struct simplelock
#define DRM_SPININIT(l,name) simple_lock_init(&l)
#define DRM_SPININIT(l,name)
#define DRM_SPINUNINIT(l)
#define DRM_SPINLOCK(l) simple_lock(l)
#define DRM_SPINUNLOCK(u) simple_unlock(u);
#define DRM_SPINLOCK(l)
#define DRM_SPINUNLOCK(u)
#define DRM_CURRENTPID curproc->p_pid
/* Currently our DRMFILE (filp) is a void * which is actually the pid
@ -112,8 +112,8 @@ extern struct cfdriver DRM(cd);
* code for that is not yet written */
#define DRMFILE void *
#define DRM_IOCTL_ARGS dev_t kdev, u_long cmd, caddr_t data, int flags, DRM_STRUCTPROC *p, DRMFILE filp
#define DRM_LOCK() lockmgr(&dev->dev_lock, LK_EXCLUSIVE, NULL)
#define DRM_UNLOCK() lockmgr(&dev->dev_lock, LK_RELEASE, NULL)
#define DRM_LOCK()
#define DRM_UNLOCK()
#define DRM_SUSER(p) suser(p->p_ucred, &p->p_acflag)
#define DRM_TASKQUEUE_ARGS void *dev, int pending
#define DRM_IRQ_ARGS void *arg
@ -138,13 +138,6 @@ extern const int DRM(M_DRM) = M_DEVBUF;
#define DRM_AGP_FIND_DEVICE() agp_find_device(0)
#define DRM_PRIV \
drm_file_t *priv = (drm_file_t *) DRM(find_file_by_proc)(dev, p); \
if (!priv) { \
DRM_DEBUG("can't find authenticator\n"); \
return EINVAL; \
}
#define LOCK_TEST_WITH_RETURN(dev, filp) \
do { \
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || \
@ -182,9 +175,11 @@ do { \
#define DRM_WAIT_ON( ret, queue, timeout, condition ) \
while (!condition) { \
int s = spldrm(); \
ret = tsleep( (void *)&(queue), PZERO | PCATCH, "drmwtq", (timeout) ); \
if ( ret ) \
return ret; \
splx(s); \
}
#define DRM_ERR(v) v
@ -320,7 +315,7 @@ find_first_zero_bit(atomic_t *p, int max)
#define jiffies hardclock_ticks
/* Redefinitions to make templating easy */
#define wait_queue_head_t atomic_t
#define wait_queue_head_t int
#define agp_memory void
/* Macros to make printf easier */

View file

@ -44,7 +44,7 @@ DRM(pci_alloc)(drm_device_t *dev, size_t size, size_t align, dma_addr_t maxaddr,
{
void *vaddr;
vaddr = contigmalloc(size, DRM(M_DRM), M_WAITOK, 0ul, maxaddr, align,
vaddr = contigmalloc(size, DRM(M_DRM), M_NOWAIT, 0ul, maxaddr, align,
0);
*busaddr = vtophys(vaddr);

View file

@ -173,7 +173,7 @@ static int DRM(_vm_info)DRM_SYSCTL_HANDLER_ARGS
static int DRM(vm_info)DRM_SYSCTL_HANDLER_ARGS
{
drm_device_t *dev = arg1;
drm_device_t __unused *dev = arg1;
int ret;
DRM_LOCK();
@ -225,7 +225,7 @@ static int DRM(_bufs_info) DRM_SYSCTL_HANDLER_ARGS
static int DRM(bufs_info) DRM_SYSCTL_HANDLER_ARGS
{
drm_device_t *dev = arg1;
drm_device_t __unused *dev = arg1;
int ret;
DRM_LOCK();
@ -259,7 +259,7 @@ static int DRM(_clients_info) DRM_SYSCTL_HANDLER_ARGS
static int DRM(clients_info)DRM_SYSCTL_HANDLER_ARGS
{
drm_device_t *dev = arg1;
drm_device_t __unused *dev = arg1;
int ret;
DRM_LOCK();

View file

@ -65,7 +65,9 @@ paddr_t DRM(mmap)(dev_t kdev, off_t offset, int prot)
drm_map_list_entry_t *listentry = NULL;
drm_file_t *priv;
DRM_LOCK();
priv = DRM(find_file_by_proc)(dev, DRM_CURPROC);
DRM_UNLOCK();
if (!priv) {
DRM_DEBUG("can't find authenticator\n");
return EINVAL;