summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <anholt@freebsd.org>2003-10-19 23:35:58 +0000
committerEric Anholt <anholt@freebsd.org>2003-10-19 23:35:58 +0000
commit0cf1887139eb1ce18d09f7be0567aa93d802040d (patch)
tree05704a5a90bc9b0fbabed4029f200f9eff955953
parent59fbe01fea8f77fc3810643c14a1738d197d4291 (diff)
- 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.
-rw-r--r--bsd-core/ati_pcigart.c2
-rw-r--r--bsd-core/drmP.h37
-rw-r--r--bsd-core/drm_auth.c17
-rw-r--r--bsd-core/drm_bufs.c161
-rw-r--r--bsd-core/drm_dma.c6
-rw-r--r--bsd-core/drm_drv.c138
-rw-r--r--bsd-core/drm_fops.c13
-rw-r--r--bsd-core/drm_irq.c30
-rw-r--r--bsd-core/drm_os_freebsd.h36
-rw-r--r--bsd-core/drm_os_netbsd.h21
-rw-r--r--bsd-core/drm_pci.c2
-rw-r--r--bsd-core/drm_sysctl.c6
-rw-r--r--bsd-core/drm_vm.c2
-rw-r--r--bsd/ati_pcigart.h2
-rw-r--r--bsd/drmP.h37
-rw-r--r--bsd/drm_auth.h17
-rw-r--r--bsd/drm_bufs.h161
-rw-r--r--bsd/drm_dma.h6
-rw-r--r--bsd/drm_drv.h138
-rw-r--r--bsd/drm_fops.h13
-rw-r--r--bsd/drm_irq.h30
-rw-r--r--bsd/drm_os_freebsd.h36
-rw-r--r--bsd/drm_os_netbsd.h21
-rw-r--r--bsd/drm_pci.h2
-rw-r--r--bsd/drm_sysctl.h6
-rw-r--r--bsd/drm_vm.h2
26 files changed, 470 insertions, 472 deletions
diff --git a/bsd-core/ati_pcigart.c b/bsd-core/ati_pcigart.c
index 0a05dda6..9aa2192f 100644
--- a/bsd-core/ati_pcigart.c
+++ b/bsd-core/ati_pcigart.c
@@ -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;
diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h
index c39df162..67915374 100644
--- a/bsd-core/drmP.h
+++ b/bsd-core/drmP.h
@@ -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 );
diff --git a/bsd-core/drm_auth.c b/bsd-core/drm_auth.c
index 6f819ad8..9e34b35c 100644
--- a/bsd-core/drm_auth.c
+++ b/bsd-core/drm_auth.c
@@ -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);
diff --git a/bsd-core/drm_bufs.c b/bsd-core/drm_bufs.c
index 4c33763c..cdd2359d 100644
--- a/bsd-core/drm_bufs.c
+++ b/bsd-core/drm_bufs.c
@@ -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)
+ if (request.count < 0 || request.count > 4096)
return DRM_ERR(EINVAL);
- if (request.count < 0 || request.count > 4096)
+ order = DRM(order)(request.size);
+ if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
return DRM_ERR(EINVAL);
- DRM_SPINLOCK(&dev->count_lock);
- if (dev->buf_use) {
- DRM_SPINUNLOCK(&dev->count_lock);
+ 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,18 +770,13 @@ int DRM(infobufs)( DRM_IOCTL_ARGS )
drm_buf_info_t request;
int i;
int count;
+ int retcode = 0;
- if ( !dma ) return DRM_ERR(EINVAL);
+ DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_info_t *)data, sizeof(request) );
- DRM_SPINLOCK( &dev->count_lock );
- if (dev->buf_alloc != 0) {
- DRM_SPINUNLOCK( &dev->count_lock );
- return DRM_ERR(EBUSY);
- }
+ DRM_SPINLOCK(&dev->dma_lock);
++dev->buf_use; /* Can't allocate more after this call */
- DRM_SPINUNLOCK( &dev->count_lock );
-
- DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_info_t *)data, sizeof(request) );
+ 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 )
+ 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);
- if ( request.high_mark < 0 || request.high_mark > entry->buf_count )
+ }
+
+ 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);
+ }
- entry->freelist.low_mark = request.low_mark;
- entry->freelist.high_mark = request.high_mark;
+ 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 */
-
diff --git a/bsd-core/drm_dma.c b/bsd-core/drm_dma.c
index d5852403..8d87c38a 100644
--- a/bsd-core/drm_dma.c
+++ b/bsd-core/drm_dma.c
@@ -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);
}
diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c
index 8a9e3036..731f31da 100644
--- a/bsd-core/drm_drv.c
+++ b/bsd-core/drm_drv.c
@@ -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;
}
diff --git a/bsd-core/drm_fops.c b/bsd-core/drm_fops.c
index b44254b8..3c4553de 100644
--- a/bsd-core/drm_fops.c
+++ b/bsd-core/drm_fops.c
@@ -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
diff --git a/bsd-core/drm_irq.c b/bsd-core/drm_irq.c
index 3366ff1c..f984118e 100644
--- a/bsd-core/drm_irq.c
+++ b/bsd-core/drm_irq.c
@@ -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
diff --git a/bsd-core/drm_os_freebsd.h b/bsd-core/drm_os_freebsd.h
index 3894f54d..320db342 100644
--- a/bsd-core/drm_os_freebsd.h
+++ b/bsd-core/drm_os_freebsd.h
@@ -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 )
diff --git a/bsd-core/drm_os_netbsd.h b/bsd-core/drm_os_netbsd.h
index 47e710c7..7653b05e 100644
--- a/bsd-core/drm_os_netbsd.h
+++ b/bsd-core/drm_os_netbsd.h
@@ -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 */
diff --git a/bsd-core/drm_pci.c b/bsd-core/drm_pci.c
index aa065b64..1d8b593d 100644
--- a/bsd-core/drm_pci.c
+++ b/bsd-core/drm_pci.c
@@ -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);
diff --git a/bsd-core/drm_sysctl.c b/bsd-core/drm_sysctl.c
index 270b3947..fe586d4c 100644
--- a/bsd-core/drm_sysctl.c
+++ b/bsd-core/drm_sysctl.c
@@ -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();
diff --git a/bsd-core/drm_vm.c b/bsd-core/drm_vm.c
index da815329..9e9f1e14 100644
--- a/bsd-core/drm_vm.c
+++ b/bsd-core/drm_vm.c
@@ -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;
diff --git a/bsd/ati_pcigart.h b/bsd/ati_pcigart.h
index 0a05dda6..9aa2192f 100644
--- a/bsd/ati_pcigart.h
+++ b/bsd/ati_pcigart.h
@@ -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;
diff --git a/bsd/drmP.h b/bsd/drmP.h
index c39df162..67915374 100644
--- a/bsd/drmP.h
+++ b/bsd/drmP.h
@@ -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 );
diff --git a/bsd/drm_auth.h b/bsd/drm_auth.h
index 6f819ad8..9e34b35c 100644
--- a/bsd/drm_auth.h
+++ b/bsd/drm_auth.h
@@ -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);
diff --git a/bsd/drm_bufs.h b/bsd/drm_bufs.h
index 4c33763c..cdd2359d 100644
--- a/bsd/drm_bufs.h
+++ b/bsd/drm_bufs.h
@@ -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)
+ if (request.count < 0 || request.count > 4096)
return DRM_ERR(EINVAL);
- if (request.count < 0 || request.count > 4096)
+ order = DRM(order)(request.size);
+ if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
return DRM_ERR(EINVAL);
- DRM_SPINLOCK(&dev->count_lock);
- if (dev->buf_use) {
- DRM_SPINUNLOCK(&dev->count_lock);
+ 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,18 +770,13 @@ int DRM(infobufs)( DRM_IOCTL_ARGS )
drm_buf_info_t request;
int i;
int count;
+ int retcode = 0;
- if ( !dma ) return DRM_ERR(EINVAL);
+ DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_info_t *)data, sizeof(request) );
- DRM_SPINLOCK( &dev->count_lock );
- if (dev->buf_alloc != 0) {
- DRM_SPINUNLOCK( &dev->count_lock );
- return DRM_ERR(EBUSY);
- }
+ DRM_SPINLOCK(&dev->dma_lock);
++dev->buf_use; /* Can't allocate more after this call */
- DRM_SPINUNLOCK( &dev->count_lock );
-
- DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_info_t *)data, sizeof(request) );
+ 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 )
+ 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);
- if ( request.high_mark < 0 || request.high_mark > entry->buf_count )
+ }
+
+ 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);
+ }
- entry->freelist.low_mark = request.low_mark;
- entry->freelist.high_mark = request.high_mark;
+ 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 */
-
diff --git a/bsd/drm_dma.h b/bsd/drm_dma.h
index d5852403..8d87c38a 100644
--- a/bsd/drm_dma.h
+++ b/bsd/drm_dma.h
@@ -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);
}
diff --git a/bsd/drm_drv.h b/bsd/drm_drv.h
index 8a9e3036..731f31da 100644
--- a/bsd/drm_drv.h
+++ b/bsd/drm_drv.h
@@ -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;
}
diff --git a/bsd/drm_fops.h b/bsd/drm_fops.h
index b44254b8..3c4553de 100644
--- a/bsd/drm_fops.h
+++ b/bsd/drm_fops.h
@@ -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
diff --git a/bsd/drm_irq.h b/bsd/drm_irq.h
index 3366ff1c..f984118e 100644
--- a/bsd/drm_irq.h
+++ b/bsd/drm_irq.h
@@ -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
diff --git a/bsd/drm_os_freebsd.h b/bsd/drm_os_freebsd.h
index 3894f54d..320db342 100644
--- a/bsd/drm_os_freebsd.h
+++ b/bsd/drm_os_freebsd.h
@@ -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 )
diff --git a/bsd/drm_os_netbsd.h b/bsd/drm_os_netbsd.h
index 47e710c7..7653b05e 100644
--- a/bsd/drm_os_netbsd.h
+++ b/bsd/drm_os_netbsd.h
@@ -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 */
diff --git a/bsd/drm_pci.h b/bsd/drm_pci.h
index aa065b64..1d8b593d 100644
--- a/bsd/drm_pci.h
+++ b/bsd/drm_pci.h
@@ -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);
diff --git a/bsd/drm_sysctl.h b/bsd/drm_sysctl.h
index 270b3947..fe586d4c 100644
--- a/bsd/drm_sysctl.h
+++ b/bsd/drm_sysctl.h
@@ -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();
diff --git a/bsd/drm_vm.h b/bsd/drm_vm.h
index da815329..9e9f1e14 100644
--- a/bsd/drm_vm.h
+++ b/bsd/drm_vm.h
@@ -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;