Fix panic on module unload and a panic when exiting dri clients sometimes.

Allow module unloading when not in use. Mostly from FreeBSD CVS.
This commit is contained in:
Eric Anholt 2002-07-02 03:27:16 +00:00
parent 5c8bf3796e
commit a043b05c90
4 changed files with 108 additions and 120 deletions

View file

@ -851,24 +851,18 @@ int DRM(open)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
DRM_DEBUG( "open_count = %d\n", dev->open_count );
#ifdef __FreeBSD__
device_busy(dev->device);
#endif
retcode = DRM(open_helper)(kdev, flags, fmt, p, dev);
if ( !retcode ) {
atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
DRM_SPINLOCK( &dev->count_lock );
if ( !dev->open_count++ ) {
#ifdef __FreeBSD__
device_busy(dev->device);
#endif
if ( !dev->open_count++ )
retcode = DRM(setup)( dev );
DRM_SPINUNLOCK( &dev->count_lock );
return retcode;
}
DRM_SPINUNLOCK( &dev->count_lock );
}
#ifdef __FreeBSD__
device_unbusy(dev->device);
#endif
return retcode;
}
@ -923,7 +917,7 @@ int DRM(close)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
for (;;) {
if ( !dev->lock.hw_lock ) {
/* Device has been unregistered */
retcode = EINTR;
retcode = DRM_ERR(EINTR);
break;
}
if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
@ -980,6 +974,9 @@ int DRM(close)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
DRM_SPINLOCK( &dev->count_lock );
#ifdef __FreeBSD__
device_unbusy(dev->device);
#endif
if ( !--dev->open_count ) {
if ( atomic_read( &dev->ioctl_count ) || dev->blocked ) {
DRM_ERROR( "Device busy: %ld %d\n",
@ -992,11 +989,8 @@ int DRM(close)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
return DRM(takedown)( dev );
}
DRM_SPINUNLOCK( &dev->count_lock );
#ifdef __FreeBSD__
device_unbusy(dev->device);
#endif
return DRM_ERR(retcode);
return retcode;
}
/* DRM(ioctl) is called whenever a process performs an ioctl on /dev/drm.

View file

@ -1,6 +1,10 @@
/*
* $FreeBSD: src/sys/dev/drm/drm_sysctl.h,v 1.1 2002/04/27 20:47:57 anholt Exp $
*/
#ifdef __FreeBSD__
SYSCTL_NODE(_hw, OID_AUTO, dri, CTLFLAG_RW, 0, "DRI Graphics");
#include <sys/sysctl.h>
static int DRM(name_info)DRM_SYSCTL_HANDLER_ARGS;
static int DRM(vm_info)DRM_SYSCTL_HANDLER_ARGS;
@ -34,8 +38,7 @@ struct DRM(sysctl_list) {
#define DRM_SYSCTL_ENTRIES (sizeof(DRM(sysctl_list))/sizeof(DRM(sysctl_list)[0]))
struct drm_sysctl_info {
struct sysctl_oid oids[DRM_SYSCTL_ENTRIES + 1];
struct sysctl_oid_list list;
struct sysctl_ctx_list ctx;
char name[2];
};
@ -43,65 +46,62 @@ int DRM(sysctl_init)(drm_device_t *dev)
{
struct drm_sysctl_info *info;
struct sysctl_oid *oid;
struct sysctl_oid *top;
struct sysctl_oid *top, *drioid;
int i;
/* Find the next free slot under hw.graphics */
info = DRM(alloc)(sizeof *info, DRM_MEM_DRIVER);
if ( !info )
return 1;
bzero(info, sizeof *info);
dev->sysctl = info;
/* Add the sysctl node for DRI if it doesn't already exist */
drioid = SYSCTL_ADD_NODE( &info->ctx, &sysctl__hw_children, OID_AUTO, "dri", CTLFLAG_RW, NULL, "DRI Graphics");
if (!drioid)
return 1;
/* Find the next free slot under hw.dri */
i = 0;
SLIST_FOREACH(oid, &sysctl__hw_dri_children, oid_link) {
SLIST_FOREACH(oid, SYSCTL_CHILDREN(drioid), oid_link) {
if (i <= oid->oid_arg2)
i = oid->oid_arg2 + 1;
}
if (i>9)
return 1;
info = DRM(alloc)(sizeof *info, DRM_MEM_DRIVER);
dev->sysctl = info;
/* Construct the node under hw.graphics */
/* Add the hw.dri.x for our device */
info->name[0] = '0' + i;
info->name[1] = 0;
oid = &info->oids[DRM_SYSCTL_ENTRIES];
bzero(oid, sizeof(*oid));
oid->oid_parent = &sysctl__hw_dri_children;
oid->oid_number = OID_AUTO;
oid->oid_kind = CTLTYPE_NODE | CTLFLAG_RW;
oid->oid_arg1 = &info->list;
oid->oid_arg2 = i;
oid->oid_name = info->name;
oid->oid_handler = 0;
oid->oid_fmt = "N";
SLIST_INIT(&info->list);
sysctl_register_oid(oid);
top = oid;
top = SYSCTL_ADD_NODE( &info->ctx, SYSCTL_CHILDREN(drioid), OID_AUTO, info->name, CTLFLAG_RW, NULL, NULL);
if (!top)
return 1;
for (i = 0; i < DRM_SYSCTL_ENTRIES; i++) {
oid = &info->oids[i];
bzero(oid, sizeof(*oid));
oid->oid_parent = top->oid_arg1;
oid->oid_number = OID_AUTO;
oid->oid_kind = CTLTYPE_INT | CTLFLAG_RD;
oid->oid_arg1 = dev;
oid->oid_arg2 = 0;
oid->oid_name = DRM(sysctl_list)[i].name;
oid->oid_handler = DRM(sysctl_list[)i].f;
oid->oid_fmt = "A";
sysctl_register_oid(oid);
oid = sysctl_add_oid( &info->ctx,
SYSCTL_CHILDREN(top),
OID_AUTO,
DRM(sysctl_list)[i].name,
CTLTYPE_INT | CTLFLAG_RD,
dev,
0,
DRM(sysctl_list)[i].f,
"A",
NULL);
if (!oid)
return 1;
}
return 0;
}
int DRM(sysctl_cleanup)(drm_device_t *dev)
{
int i;
DRM_DEBUG("dev->sysctl=%p\n", dev->sysctl);
for (i = 0; i < DRM_SYSCTL_ENTRIES + 1; i++)
sysctl_unregister_oid(&dev->sysctl->oids[i]);
int error;
error = sysctl_ctx_free( &dev->sysctl->ctx );
DRM(free)(dev->sysctl, sizeof *dev->sysctl, DRM_MEM_DRIVER);
dev->sysctl = NULL;
return 0;
return error;
}
static int DRM(name_info)DRM_SYSCTL_HANDLER_ARGS
@ -191,8 +191,8 @@ static int DRM(_queues_info)DRM_SYSCTL_HANDLER_ARGS
q = dev->queuelist[i];
atomic_inc(&q->use_count);
DRM_SYSCTL_PRINT_RET(atomic_dec(&q->use_count),
"%5d/0x%03x %5d %5d"
" %5d/%c%c/%c%c%c %5d %10d %10d %10d\n",
"%5d/0x%03x %5ld %5ld"
" %5ld/%c%c/%c%c%c %5d %10ld %10ld %10ld\n",
i,
q->flags,
atomic_read(&q->use_count),
@ -240,7 +240,7 @@ static int DRM(_bufs_info) DRM_SYSCTL_HANDLER_ARGS
DRM_SYSCTL_PRINT(" o size count free segs pages kB\n\n");
for (i = 0; i <= DRM_MAX_ORDER; i++) {
if (dma->bufs[i].buf_count)
DRM_SYSCTL_PRINT("%2d %8d %5d %5d %5d %5d %5d\n",
DRM_SYSCTL_PRINT("%2d %8d %5d %5ld %5d %5d %5d\n",
i,
dma->bufs[i].buf_size,
dma->bufs[i].buf_count,

View file

@ -851,24 +851,18 @@ int DRM(open)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
DRM_DEBUG( "open_count = %d\n", dev->open_count );
#ifdef __FreeBSD__
device_busy(dev->device);
#endif
retcode = DRM(open_helper)(kdev, flags, fmt, p, dev);
if ( !retcode ) {
atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
DRM_SPINLOCK( &dev->count_lock );
if ( !dev->open_count++ ) {
#ifdef __FreeBSD__
device_busy(dev->device);
#endif
if ( !dev->open_count++ )
retcode = DRM(setup)( dev );
DRM_SPINUNLOCK( &dev->count_lock );
return retcode;
}
DRM_SPINUNLOCK( &dev->count_lock );
}
#ifdef __FreeBSD__
device_unbusy(dev->device);
#endif
return retcode;
}
@ -923,7 +917,7 @@ int DRM(close)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
for (;;) {
if ( !dev->lock.hw_lock ) {
/* Device has been unregistered */
retcode = EINTR;
retcode = DRM_ERR(EINTR);
break;
}
if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
@ -980,6 +974,9 @@ int DRM(close)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
DRM_SPINLOCK( &dev->count_lock );
#ifdef __FreeBSD__
device_unbusy(dev->device);
#endif
if ( !--dev->open_count ) {
if ( atomic_read( &dev->ioctl_count ) || dev->blocked ) {
DRM_ERROR( "Device busy: %ld %d\n",
@ -992,11 +989,8 @@ int DRM(close)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
return DRM(takedown)( dev );
}
DRM_SPINUNLOCK( &dev->count_lock );
#ifdef __FreeBSD__
device_unbusy(dev->device);
#endif
return DRM_ERR(retcode);
return retcode;
}
/* DRM(ioctl) is called whenever a process performs an ioctl on /dev/drm.

View file

@ -1,6 +1,10 @@
/*
* $FreeBSD: src/sys/dev/drm/drm_sysctl.h,v 1.1 2002/04/27 20:47:57 anholt Exp $
*/
#ifdef __FreeBSD__
SYSCTL_NODE(_hw, OID_AUTO, dri, CTLFLAG_RW, 0, "DRI Graphics");
#include <sys/sysctl.h>
static int DRM(name_info)DRM_SYSCTL_HANDLER_ARGS;
static int DRM(vm_info)DRM_SYSCTL_HANDLER_ARGS;
@ -34,8 +38,7 @@ struct DRM(sysctl_list) {
#define DRM_SYSCTL_ENTRIES (sizeof(DRM(sysctl_list))/sizeof(DRM(sysctl_list)[0]))
struct drm_sysctl_info {
struct sysctl_oid oids[DRM_SYSCTL_ENTRIES + 1];
struct sysctl_oid_list list;
struct sysctl_ctx_list ctx;
char name[2];
};
@ -43,65 +46,62 @@ int DRM(sysctl_init)(drm_device_t *dev)
{
struct drm_sysctl_info *info;
struct sysctl_oid *oid;
struct sysctl_oid *top;
struct sysctl_oid *top, *drioid;
int i;
/* Find the next free slot under hw.graphics */
info = DRM(alloc)(sizeof *info, DRM_MEM_DRIVER);
if ( !info )
return 1;
bzero(info, sizeof *info);
dev->sysctl = info;
/* Add the sysctl node for DRI if it doesn't already exist */
drioid = SYSCTL_ADD_NODE( &info->ctx, &sysctl__hw_children, OID_AUTO, "dri", CTLFLAG_RW, NULL, "DRI Graphics");
if (!drioid)
return 1;
/* Find the next free slot under hw.dri */
i = 0;
SLIST_FOREACH(oid, &sysctl__hw_dri_children, oid_link) {
SLIST_FOREACH(oid, SYSCTL_CHILDREN(drioid), oid_link) {
if (i <= oid->oid_arg2)
i = oid->oid_arg2 + 1;
}
if (i>9)
return 1;
info = DRM(alloc)(sizeof *info, DRM_MEM_DRIVER);
dev->sysctl = info;
/* Construct the node under hw.graphics */
/* Add the hw.dri.x for our device */
info->name[0] = '0' + i;
info->name[1] = 0;
oid = &info->oids[DRM_SYSCTL_ENTRIES];
bzero(oid, sizeof(*oid));
oid->oid_parent = &sysctl__hw_dri_children;
oid->oid_number = OID_AUTO;
oid->oid_kind = CTLTYPE_NODE | CTLFLAG_RW;
oid->oid_arg1 = &info->list;
oid->oid_arg2 = i;
oid->oid_name = info->name;
oid->oid_handler = 0;
oid->oid_fmt = "N";
SLIST_INIT(&info->list);
sysctl_register_oid(oid);
top = oid;
top = SYSCTL_ADD_NODE( &info->ctx, SYSCTL_CHILDREN(drioid), OID_AUTO, info->name, CTLFLAG_RW, NULL, NULL);
if (!top)
return 1;
for (i = 0; i < DRM_SYSCTL_ENTRIES; i++) {
oid = &info->oids[i];
bzero(oid, sizeof(*oid));
oid->oid_parent = top->oid_arg1;
oid->oid_number = OID_AUTO;
oid->oid_kind = CTLTYPE_INT | CTLFLAG_RD;
oid->oid_arg1 = dev;
oid->oid_arg2 = 0;
oid->oid_name = DRM(sysctl_list)[i].name;
oid->oid_handler = DRM(sysctl_list[)i].f;
oid->oid_fmt = "A";
sysctl_register_oid(oid);
oid = sysctl_add_oid( &info->ctx,
SYSCTL_CHILDREN(top),
OID_AUTO,
DRM(sysctl_list)[i].name,
CTLTYPE_INT | CTLFLAG_RD,
dev,
0,
DRM(sysctl_list)[i].f,
"A",
NULL);
if (!oid)
return 1;
}
return 0;
}
int DRM(sysctl_cleanup)(drm_device_t *dev)
{
int i;
DRM_DEBUG("dev->sysctl=%p\n", dev->sysctl);
for (i = 0; i < DRM_SYSCTL_ENTRIES + 1; i++)
sysctl_unregister_oid(&dev->sysctl->oids[i]);
int error;
error = sysctl_ctx_free( &dev->sysctl->ctx );
DRM(free)(dev->sysctl, sizeof *dev->sysctl, DRM_MEM_DRIVER);
dev->sysctl = NULL;
return 0;
return error;
}
static int DRM(name_info)DRM_SYSCTL_HANDLER_ARGS
@ -191,8 +191,8 @@ static int DRM(_queues_info)DRM_SYSCTL_HANDLER_ARGS
q = dev->queuelist[i];
atomic_inc(&q->use_count);
DRM_SYSCTL_PRINT_RET(atomic_dec(&q->use_count),
"%5d/0x%03x %5d %5d"
" %5d/%c%c/%c%c%c %5d %10d %10d %10d\n",
"%5d/0x%03x %5ld %5ld"
" %5ld/%c%c/%c%c%c %5d %10ld %10ld %10ld\n",
i,
q->flags,
atomic_read(&q->use_count),
@ -240,7 +240,7 @@ static int DRM(_bufs_info) DRM_SYSCTL_HANDLER_ARGS
DRM_SYSCTL_PRINT(" o size count free segs pages kB\n\n");
for (i = 0; i <= DRM_MAX_ORDER; i++) {
if (dma->bufs[i].buf_count)
DRM_SYSCTL_PRINT("%2d %8d %5d %5d %5d %5d %5d\n",
DRM_SYSCTL_PRINT("%2d %8d %5d %5ld %5d %5d %5d\n",
i,
dma->bufs[i].buf_size,
dma->bufs[i].buf_count,