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