Index: programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/ati_pcigart.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/ati_pcigart.h,v retrieving revision 1.6 diff -u -r1.6 ati_pcigart.h --- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/ati_pcigart.h 19 Aug 2003 00:41:00 -0000 1.6 +++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/ati_pcigart.h 17 Oct 2003 05:43:06 -0000 @@ -59,7 +59,7 @@ } 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; Index: programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drmP.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drmP.h,v retrieving revision 1.35 diff -u -r1.35 drmP.h --- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drmP.h 17 Oct 2003 05:13:47 -0000 1.35 +++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drmP.h 17 Oct 2003 05:45:06 -0000 @@ -180,7 +180,6 @@ 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 @@ 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 @@ 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 @@ 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; @@ -355,12 +368,8 @@ 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__ @@ -381,11 +390,6 @@ }; 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 ); Index: programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_auth.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_auth.h,v retrieving revision 1.7 diff -u -r1.7 drm_auth.h --- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_auth.h 3 Oct 2003 07:02:51 -0000 1.7 +++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_auth.h 17 Oct 2003 05:43:06 -0000 @@ -54,7 +54,7 @@ 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 @@ 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,15 @@ 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; + + priv = (drm_file_t *) DRM(find_file_by_proc)(dev, p); + if (priv == NULL) { + DRM_DEBUG("can't find authenticator\n"); + return EINVAL; + } /* Find unique magic */ if (priv->magic) { @@ -152,6 +158,7 @@ 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); Index: programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_bufs.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_bufs.h,v retrieving revision 1.18 diff -u -r1.18 drm_bufs.h --- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_bufs.h 3 Oct 2003 08:08:10 -0000 1.18 +++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_bufs.h 17 Oct 2003 05:43:06 -0000 @@ -226,6 +226,8 @@ 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 @@ break; } DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); - DRM_UNLOCK(); return 0; } @@ -350,20 +351,11 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ #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 @@ 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 @@ 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 @@ 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 @@ 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 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 @@ 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 @@ 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 @@ } #endif /* __HAVE_DMA */ - Index: programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_dma.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_dma.h,v retrieving revision 1.27 diff -u -r1.27 drm_dma.h --- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_dma.h 17 Oct 2003 05:13:47 -0000 1.27 +++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_dma.h 17 Oct 2003 05:43:06 -0000 @@ -46,17 +46,11 @@ int DRM(dma_setup)( drm_device_t *dev ) { - int i; - - dev->dma = DRM(alloc)( sizeof(*dev->dma), DRM_MEM_DRIVER ); - if ( !dev->dma ) + dev->dma = DRM(calloc)(1, sizeof(*dev->dma), DRM_MEM_DRIVER); + if (dev->dma == NULL) return DRM_ERR(ENOMEM); - memset( dev->dma, 0, sizeof(*dev->dma) ); - - for ( i = 0 ; i <= DRM_MAX_ORDER ; i++ ) - memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0])); - + DRM_SPININIT(dev->dma_lock, "drmdma"); return 0; } @@ -65,7 +59,8 @@ 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++) { @@ -112,6 +107,7 @@ DRM_MEM_PAGES); DRM(free)(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER); dev->dma = NULL; + DRM_SPINUNINIT(dev->dma_lock); } Index: programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h,v retrieving revision 1.32 diff -u -r1.32 drm_drv.h --- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h 17 Oct 2003 05:13:47 -0000 1.32 +++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h 17 Oct 2003 05:43:06 -0000 @@ -111,7 +111,7 @@ #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(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 @@ 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 @@ #if __HAVE_DMA i = DRM(dma_setup)( dev ); - if ( i < 0 ) + if ( i != 0 ) return i; #endif @@ -482,7 +483,7 @@ dev->context_flag = 0; dev->last_context = 0; #if __FreeBSD_version >= 500000 - callout_init( &dev->timer, 1 ); + callout_init( &dev->timer, CALLOUT_MPSAFE ); #else callout_init( &dev->timer ); #endif @@ -499,7 +500,9 @@ 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,7 +518,6 @@ DRM(irq_uninstall)( dev ); #endif - DRM_LOCK(); callout_stop( &dev->timer ); if ( dev->unique ) { @@ -625,7 +627,6 @@ dev->lock.filp = NULL; DRM_WAKEUP_INT((void *)&dev->lock.lock_queue); } - DRM_UNLOCK(); return 0; } @@ -664,11 +665,12 @@ 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 +681,8 @@ #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 +714,7 @@ 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 +728,36 @@ 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); @@ -788,7 +789,9 @@ #endif DRIVER_POSTCLEANUP(); DRM(mem_uninit)(); - DRM_SPINUNINIT(dev->count_lock); +#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 + mtx_destroy(&dev->dev_lock); +#endif } @@ -832,17 +835,22 @@ retcode = DRM(open_helper)(kdev, flags, fmt, p, dev); + DRM_LOCK(); + if ( !retcode ) { atomic_inc( &dev->counts[_DRM_STAT_OPENS] ); - DRM_SPINLOCK( &dev->count_lock ); + if ( dev->open_count++ == 0 ) { + retcode = DRM(setup)( dev ); + if (retcode != 0) + dev->open_count--; + } #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 +862,9 @@ DRMFILE filp = (void *)(DRM_CURRENTPID); DRM_DEBUG( "open_count = %d\n", dev->open_count ); + priv = DRM(find_file_by_proc)(dev, p); - if (!priv) { + if (priv == NULL) { DRM_DEBUG("can't find authenticator\n"); return EINVAL; } @@ -894,6 +903,7 @@ #if __HAVE_RELEASE else if ( dev->lock.hw_lock ) { /* The lock is required to reclaim buffers */ + DRM_LOCK(); for (;;) { if ( !dev->lock.hw_lock ) { /* Device has been unregistered */ @@ -908,13 +918,17 @@ 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; } + DRM_UNLOCK(); if (retcode == 0) { DRIVER_RELEASE(); DRM(lock_free)( dev, &dev->lock.hw_lock->lock, @@ -933,32 +947,29 @@ dev->buf_pgid = 0; #endif /* __NetBSD__ */ - DRM_LOCK(); priv = DRM(find_file_by_proc)(dev, p); - if (priv) { - priv->refs--; - if (!priv->refs) { + if (priv != NULL) { + DRM_LOCK(); + if (--priv->refs == 0) { TAILQ_REMOVE(&dev->files, priv, link); DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES ); } + DRM_UNLOCK(); } - 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 ); + DRM_LOCK(); + if (--dev->open_count == 0) { + retcode = DRM(takedown)( dev ); } - DRM_SPINUNLOCK( &dev->count_lock ); + DRM_UNLOCK(); return retcode; } @@ -973,7 +984,13 @@ drm_ioctl_desc_t *ioctl; int (*func)(DRM_IOCTL_ARGS); int nr = DRM_IOCTL_NR(cmd); - DRM_PRIV; + drm_file_t *priv; + + priv = (drm_file_t *) DRM(find_file_by_proc)(dev, p); + if (priv == NULL) { + DRM_DEBUG("can't find authenticator\n"); + return EINVAL; + } atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] ); ++priv->ioctl_count; @@ -988,10 +1005,7 @@ switch (cmd) { case FIONBIO: - return 0; - case FIOASYNC: - dev->flags |= FASYNC; return 0; #ifdef __FreeBSD__ @@ -1017,7 +1031,7 @@ #endif /* __NetBSD__ */ } - if (nr >= DRIVER_IOCTL_COUNT) + if (nr >= DRIVER_IOCTL_COUNT || IOCGROUP(cmd) != DRM_IOCTL_BASE) return EINVAL; ioctl = &DRM(ioctls)[nr]; @@ -1059,6 +1073,7 @@ return DRM_ERR(EINVAL); #endif + DRM_LOCK(); for (;;) { if (dev->lock.hw_lock == NULL) { /* Device has been unregistered */ @@ -1073,11 +1088,17 @@ } /* 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 +1131,7 @@ 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 +1142,7 @@ DRM_KERNEL_CONTEXT ) ) { DRM_ERROR( "\n" ); } + DRM_UNLOCK(); return 0; } Index: programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_fops.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_fops.h,v retrieving revision 1.9 diff -u -r1.9 drm_fops.h --- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_fops.h 3 Oct 2003 07:02:51 -0000 1.9 +++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_fops.h 17 Oct 2003 05:43:06 -0000 @@ -44,10 +44,12 @@ #endif drm_file_t *priv; + DRM_LOCK(); TAILQ_FOREACH(priv, &dev->files, link) if (priv->pid == pid && priv->uid == uid) - return priv; - return NULL; + break; + DRM_UNLOCK(); + return priv; } /* DRM(open) is called whenever a process opens /dev/drm. */ Index: programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_irq.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_irq.h,v retrieving revision 1.1 diff -u -r1.1 drm_irq.h --- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_irq.h 17 Oct 2003 05:13:47 -0000 1.1 +++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_irq.h 17 Oct 2003 05:43:06 -0000 @@ -27,7 +27,19 @@ * Eric Anholt * */ - + +#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 @@ 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 @@ 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 @@ 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 @@ #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 @@ #elif defined(__NetBSD__) pci_intr_disestablish(&dev->pa.pa_pc, dev->irqh); #endif + DRM_SPINUNINIT(dev->irq_lock); return 0; } @@ -187,9 +203,9 @@ 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 @@ 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 @@ } vbl_sig = next; } - - DRM_SPINUNLOCK(&dev->vbl_lock); } #endif Index: programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h,v retrieving revision 1.39 diff -u -r1.39 drm_os_freebsd.h --- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h 17 Oct 2003 03:14:38 -0000 1.39 +++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h 17 Oct 2003 05:43:06 -0000 @@ -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 @@ #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 @@ #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 @@ "drmwtq", (timeout) ); \ splx(s); \ } +#endif #define DRM_WAKEUP( queue ) wakeup( queue ) #define DRM_WAKEUP_INT( queue ) wakeup( queue ) Index: programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_netbsd.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_netbsd.h,v retrieving revision 1.17 diff -u -r1.17 drm_os_netbsd.h --- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_netbsd.h 17 Oct 2003 03:14:38 -0000 1.17 +++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_netbsd.h 17 Oct 2003 05:43:06 -0000 @@ -101,10 +101,10 @@ #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 @@ * 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 @@ #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 @@ #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 @@ #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 */ Index: programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_pci.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_pci.h,v retrieving revision 1.1 diff -u -r1.1 drm_pci.h --- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_pci.h 26 Apr 2003 22:52:39 -0000 1.1 +++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_pci.h 17 Oct 2003 05:43:06 -0000 @@ -44,7 +44,7 @@ { 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); Index: programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_sysctl.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_sysctl.h,v retrieving revision 1.15 diff -u -r1.15 drm_sysctl.h --- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_sysctl.h 3 Oct 2003 07:02:51 -0000 1.15 +++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_sysctl.h 17 Oct 2003 05:43:06 -0000 @@ -173,7 +173,7 @@ 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 { - 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 { - drm_device_t *dev = arg1; + drm_device_t __unused *dev = arg1; int ret; DRM_LOCK();