Hi
The drm code uses 'struct mtx' as DRM_SPINTYPE on FreeBSD 5.x. The
kernel expects such mutices to be freed after use by calling
mtx_destroy(), which the current code fails to do. Quitting X and
restarting it thus results in this kernel panic:
%%
[...]
panic: mutex vblsig 0xc65fa234 already initialized
cpuid = 1; lapic.id = 01000000
boot() called on cpu#1
[...]
#12 0xc02003e7 in panic () at /freebsd/current/src/sys/kern/kern_shutdown.c:531
#13 0xc01f714f in mtx_init (m=0xc65fa234, name=0xc67d652c "vblsig", type=0x0,
opts=0) at /freebsd/current/src/sys/kern/kern_mutex.c:914
#14 0xc67cb50f in ?? ()
#15 0xc67cb7ef in ?? ()
#16 0xc67ccd0e in ?? ()
#17 0xc01c8a0e in spec_ioctl (ap=0xc65fa000)
at /freebsd/current/src/sys/fs/specfs/spec_vnops.c:349
[...]
%%
The attached patch does these things:
- Create a new macro DRM_SPINDESTROY which releases the lock on FreeBSD
5.x by calling mtx_destroy(), on 4.x and NetBSD it does nothing. I
also removed the trailing ';' from the DRM_SPINUNLOCK macro.
- Move the lock creation for getmagic() into the attach routing and make
the mutex a member of drm_device (otherwise, the static lock could not
be released). The vbl_lock which caused my panic is also created in
attach().
- Create mem_cleanup() as counterpart to mem_init(). Mem_clean() just
releases DRM(mem_lock).
- Add code to release all locks in the detach function. The waitlist
mutex is released in waitlist_destroy().
- Fix an occurence of p->p_pid, which doesn't compile on FreeBSD 5.x
because p is a struct thread, not a struct proc.
Regards,
Stefan Farfeleder
Index: drmP.h
===================================================================
RCS file:
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drmP.h,v
retrieving revision 1.11
diff -c -r1.11 drmP.h
*** drmP.h 6 Dec 2002 02:27:30 -0000 1.11
--- drmP.h 4 Feb 2003 17:10:58 -0000
***************
*** 419,424 ****
--- 419,425 ----
/* Locks */
DRM_SPINTYPE count_lock; /* For inuse, open_count, buf_use */
+ DRM_SPINTYPE getmagic_lock; /* For the getmagic ioctl */
struct lock dev_lock; /* For others */
/* Usage Counters */
int open_count; /* Outstanding files open */
***************
*** 530,535 ****
--- 531,537 ----
/* Memory management support (drm_memory.h) */
extern void DRM(mem_init)(void);
+ extern void DRM(mem_cleanup)(void);
extern void *DRM(alloc)(size_t size, int area);
extern void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size,
int area);
Index: drm_auth.h
===================================================================
RCS file:
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_auth.h,v
retrieving revision 1.3
diff -c -r1.3 drm_auth.h
*** drm_auth.h 5 Jul 2002 08:31:07 -0000 1.3
--- drm_auth.h 4 Feb 2003 17:10:58 -0000
***************
*** 116,140 ****
{
static drm_magic_t sequence = 0;
drm_auth_t auth;
- static DRM_SPINTYPE lock;
- static int first = 1;
DRM_DEVICE;
DRM_PRIV;
- if (first) {
- DRM_SPININIT(lock, "drm getmagic");
- first = 0;
- }
-
/* Find unique magic */
if (priv->magic) {
auth.magic = priv->magic;
} else {
do {
! DRM_SPINLOCK(&lock);
if (!sequence) ++sequence; /* reserve 0 */
auth.magic = sequence++;
! DRM_SPINUNLOCK(&lock);
} while (DRM(find_file)(dev, auth.magic));
priv->magic = auth.magic;
DRM(add_magic)(dev, priv, auth.magic);
--- 116,133 ----
{
static drm_magic_t sequence = 0;
drm_auth_t auth;
DRM_DEVICE;
DRM_PRIV;
/* Find unique magic */
if (priv->magic) {
auth.magic = priv->magic;
} else {
do {
! DRM_SPINLOCK(&dev->getmagic_lock);
if (!sequence) ++sequence; /* reserve 0 */
auth.magic = sequence++;
! DRM_SPINUNLOCK(&dev->getmagic_lock);
} while (DRM(find_file)(dev, auth.magic));
priv->magic = auth.magic;
DRM(add_magic)(dev, priv, auth.magic);
Index: drm_dma.h
===================================================================
RCS file:
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_dma.h,v
retrieving revision 1.10
diff -c -r1.10 drm_dma.h
*** drm_dma.h 2 Feb 2003 03:06:47 -0000 1.10
--- drm_dma.h 4 Feb 2003 17:11:01 -0000
***************
*** 525,531 ****
#endif
#if __HAVE_VBL_IRQ
- DRM_SPININIT( dev->vbl_lock, "vblsig" );
TAILQ_INIT( &dev->vbl_sig_list );
#endif
--- 525,530 ----
Index: drm_drv.h
===================================================================
RCS file:
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h,v
retrieving revision 1.8
diff -c -r1.8 drm_drv.h
*** drm_drv.h 27 Oct 2002 05:24:33 -0000 1.8
--- drm_drv.h 4 Feb 2003 17:11:02 -0000
***************
*** 701,706 ****
--- 701,707 ----
if ( dev->agp == NULL ) {
DRM_ERROR( "Cannot initialize the agpgart module.\n" );
DRM(sysctl_cleanup)( dev );
+ DRM(mem_cleanup)();
#ifdef __FreeBSD__
destroy_dev(dev->devnode);
#endif
***************
*** 739,744 ****
--- 740,746 ----
if( retcode ) {
DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
DRM(sysctl_cleanup)( dev );
+ DRM(mem_cleanup)();
#ifdef __FreeBSD__
destroy_dev(dev->devnode);
#endif
***************
*** 754,759 ****
--- 756,766 ----
DRIVER_DATE,
unit );
+ DRM_SPININIT(dev->getmagic_lock, "drm getmagic");
+ #if __HAVE_VBL_IRQ
+ DRM_SPININIT(dev->vbl_lock, "vblsig");
+ #endif
+
DRIVER_POSTINIT();
return 0;
***************
*** 785,790 ****
--- 792,798 ----
dev = device_get_softc(nbdev);
#endif
DRM(sysctl_cleanup)( dev );
+ DRM(mem_cleanup)();
#ifdef __FreeBSD__
destroy_dev(dev->devnode);
#endif
***************
*** 813,818 ****
--- 821,833 ----
dev->agp = NULL;
}
#endif
+
+ DRM_SPINDESTROY(&dev->count_lock);
+ DRM_SPINDESTROY(&dev->getmagic_lock);
+ #if __HAVE_VBL_IRQ
+ DRM_SPINDESTROY(&dev->vbl_lock);
+ #endif
+
DRIVER_POSTCLEANUP();
}
***************
*** 926,932 ****
--- 941,951 ----
}
if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT ) ) {
+ #if defined (__FreeBSD__) && (__FreeBSD_version >= 500000)
+ dev->lock.pid = p->td_proc->p_pid;
+ #else
dev->lock.pid = p->p_pid;
+ #endif
dev->lock.lock_time = jiffies;
atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
break; /* Got lock */
Index: drm_lists.h
===================================================================
RCS file:
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_lists.h,v
retrieving revision 1.3
diff -c -r1.3 drm_lists.h
*** drm_lists.h 5 Jul 2002 08:31:07 -0000 1.3
--- drm_lists.h 4 Feb 2003 17:11:03 -0000
***************
*** 66,71 ****
--- 66,73 ----
bl->rp = NULL;
bl->wp = NULL;
bl->end = NULL;
+ DRM_SPINDESTROY( &bl->write_lock );
+ DRM_SPINDESTROY( &bl->read_lock );
return 0;
}
Index: drm_memory.h
===================================================================
RCS file:
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_memory.h,v
retrieving revision 1.3
diff -c -r1.3 drm_memory.h
*** drm_memory.h 5 Jul 2002 08:31:07 -0000 1.3
--- drm_memory.h 4 Feb 2003 17:11:03 -0000
***************
*** 95,100 ****
--- 95,105 ----
DRM(ram_used) = 0;
}
+ void DRM(mem_cleanup)(void)
+ {
+ DRM_SPINDESTROY(&DRM(mem_lock));
+ }
+
#ifdef __FreeBSD__
/* drm_mem_info is called whenever a process reads /dev/drm/mem. */
static int DRM(_mem_info) DRM_SYSCTL_HANDLER_ARGS
Index: drm_os_freebsd.h
===================================================================
RCS file:
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h,v
retrieving revision 1.11
diff -c -r1.11 drm_os_freebsd.h
*** drm_os_freebsd.h 24 Jan 2003 00:49:15 -0000 1.11
--- drm_os_freebsd.h 4 Feb 2003 17:11:05 -0000
***************
*** 80,86 ****
#define DRM_SPINTYPE struct mtx
#define DRM_SPININIT(l,name) mtx_init(&l, name, NULL, MTX_DEF)
#define DRM_SPINLOCK(l) mtx_lock(l)
! #define DRM_SPINUNLOCK(u) mtx_unlock(u);
#define DRM_CURRENTPID curthread->td_proc->p_pid
#else
#define DRM_CURPROC curproc
--- 80,87 ----
#define DRM_SPINTYPE struct mtx
#define DRM_SPININIT(l,name) mtx_init(&l, name, NULL, MTX_DEF)
#define DRM_SPINLOCK(l) mtx_lock(l)
! #define DRM_SPINUNLOCK(u) mtx_unlock(u)
! #define DRM_SPINDESTROY(l) mtx_destroy(l)
#define DRM_CURRENTPID curthread->td_proc->p_pid
#else
#define DRM_CURPROC curproc
***************
*** 88,94 ****
#define DRM_SPINTYPE struct simplelock
#define DRM_SPININIT(l,name) simple_lock_init(&l)
#define DRM_SPINLOCK(l) simple_lock(l)
! #define DRM_SPINUNLOCK(u) simple_unlock(u);
#define DRM_CURRENTPID curproc->p_pid
#endif
--- 89,96 ----
#define DRM_SPINTYPE struct simplelock
#define DRM_SPININIT(l,name) simple_lock_init(&l)
#define DRM_SPINLOCK(l) simple_lock(l)
! #define DRM_SPINUNLOCK(u) simple_unlock(u)
! #define DRM_SPINDESTROY(l) (void)0
#define DRM_CURRENTPID curproc->p_pid
#endif
Index: drm_os_netbsd.h
===================================================================
RCS file:
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_netbsd.h,v
retrieving revision 1.2
diff -c -r1.2 drm_os_netbsd.h
*** drm_os_netbsd.h 5 Jul 2002 08:31:07 -0000 1.2
--- drm_os_netbsd.h 4 Feb 2003 17:11:06 -0000
***************
*** 64,70 ****
#define DRM_SPINTYPE struct simplelock
#define DRM_SPININIT(l,name) simple_lock_init(&l)
#define DRM_SPINLOCK(l) simple_lock(l)
! #define DRM_SPINUNLOCK(u) simple_unlock(u);
#define DRM_CURRENTPID curproc->p_pid
#define DRM_IOCTL_ARGS dev_t kdev, u_long cmd, caddr_t data, int
flags, DRM_STRUCTPROC *p
--- 64,71 ----
#define DRM_SPINTYPE struct simplelock
#define DRM_SPININIT(l,name) simple_lock_init(&l)
#define DRM_SPINLOCK(l) simple_lock(l)
! #define DRM_SPINUNLOCK(u) simple_unlock(u)
! #define DRM_SPINDESTROY(l) (void)0
#define DRM_CURRENTPID curproc->p_pid
#define DRM_IOCTL_ARGS dev_t kdev, u_long cmd, caddr_t data, int
flags, DRM_STRUCTPROC *p