- SMPng lock the DRM. This is only partial -- there are a few code paths
authorEric Anholt <anholt@freebsd.org>
Sun, 19 Oct 2003 23:35:58 +0000 (23:35 +0000)
committerEric Anholt <anholt@freebsd.org>
Sun, 19 Oct 2003 23:35:58 +0000 (23:35 +0000)
    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.

26 files changed:
bsd-core/ati_pcigart.c
bsd-core/drmP.h
bsd-core/drm_auth.c
bsd-core/drm_bufs.c
bsd-core/drm_dma.c
bsd-core/drm_drv.c
bsd-core/drm_fops.c
bsd-core/drm_irq.c
bsd-core/drm_os_freebsd.h
bsd-core/drm_os_netbsd.h
bsd-core/drm_pci.c
bsd-core/drm_sysctl.c
bsd-core/drm_vm.c
bsd/ati_pcigart.h
bsd/drmP.h
bsd/drm_auth.h
bsd/drm_bufs.h
bsd/drm_dma.h
bsd/drm_drv.h
bsd/drm_fops.h
bsd/drm_irq.h
bsd/drm_os_freebsd.h
bsd/drm_os_netbsd.h
bsd/drm_pci.h
bsd/drm_sysctl.h
bsd/drm_vm.h

index 0a05dda..9aa2192 100644 (file)
@@ -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;
index c39df16..6791537 100644 (file)
@@ -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 );
 
index 6f819ad..9e34b35 100644 (file)
@@ -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);
index 4c33763..cdd2359 100644 (file)
@@ -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 */
-
index d585240..8d87c38 100644 (file)
@@ -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);
 }
 
 
index 8a9e303..731f31d 100644 (file)
@@ -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;
 }
index b44254b..3c4553d 100644 (file)
@@ -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
index 3366ff1..f984118 100644 (file)
  *    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
 
index 3894f54..320db34 100644 (file)
 #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
  * 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 )
index 47e710c..7653b05 100644 (file)
@@ -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 */
index aa065b6..1d8b593 100644 (file)
@@ -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);
        
index 270b394..fe586d4 100644 (file)
@@ -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();
index da81532..9e9f1e1 100644 (file)
@@ -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;
index 0a05dda..9aa2192 100644 (file)
@@ -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;
index c39df16..6791537 100644 (file)
@@ -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 );
 
index 6f819ad..9e34b35 100644 (file)
@@ -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);
index 4c33763..cdd2359 100644 (file)
@@ -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 */
-
index d585240..8d87c38 100644 (file)
@@ -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);
 }
 
 
index 8a9e303..731f31d 100644 (file)
@@ -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;
 }
index b44254b..3c4553d 100644 (file)
@@ -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
index 3366ff1..f984118 100644 (file)
  *    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
 
index 3894f54..320db34 100644 (file)
 #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
  * 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 )
index 47e710c..7653b05 100644 (file)
@@ -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 */
index aa065b6..1d8b593 100644 (file)
@@ -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);
        
index 270b394..fe586d4 100644 (file)
@@ -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();
index da81532..9e9f1e1 100644 (file)
@@ -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;