From a1d9e5abafe60ca2b7f96cadd1013695ada4ac41 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sun, 7 Nov 2004 04:11:15 +0000 Subject: Refine the locking of the DRM. Most significant is covering the driver ioctls with dev_lock, which is a major step toward being able to remove Giant. Covers some new pieces (dev->unique*) in the core, and avoids one call down into system internals with the drm lock held, which is usually bad (FreeBSD LOR #23, #27). --- bsd-core/drm_vm.c | 75 ++++++++++++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 40 deletions(-) (limited to 'bsd-core/drm_vm.c') diff --git a/bsd-core/drm_vm.c b/bsd-core/drm_vm.c index f3558b9e..1b5d4d3f 100644 --- a/bsd-core/drm_vm.c +++ b/bsd-core/drm_vm.c @@ -25,35 +25,6 @@ #include "drmP.h" #include "drm.h" -#if defined(__FreeBSD__) && __FreeBSD_version >= 500102 -static int drm_dma_mmap(struct cdev *kdev, vm_offset_t offset, - vm_paddr_t *paddr, int prot) -#elif defined(__FreeBSD__) -static int drm_dma_mmap(dev_t kdev, vm_offset_t offset, int prot) -#elif defined(__NetBSD__) || defined(__OpenBSD__) -static paddr_t drm_dma_mmap(dev_t kdev, vm_offset_t offset, int prot) -#endif -{ - DRM_DEVICE; - drm_device_dma_t *dma = dev->dma; - unsigned long physical; - unsigned long page; - - if (dma == NULL || dma->pagelist == NULL) - return -1; - - page = offset >> PAGE_SHIFT; - physical = dma->pagelist[page]; - - DRM_DEBUG("0x%08lx (page %lu) => 0x%08lx\n", (long)offset, page, physical); -#if defined(__FreeBSD__) && __FreeBSD_version >= 500102 - *paddr = physical; - return 0; -#else - return atop(physical); -#endif -} - #if defined(__FreeBSD__) && __FreeBSD_version >= 500102 int drm_mmap(struct cdev *kdev, vm_offset_t offset, vm_paddr_t *paddr, int prot) @@ -67,20 +38,40 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot) drm_local_map_t *map = NULL; drm_map_list_entry_t *listentry = NULL; drm_file_t *priv; + drm_map_type_t type; - DRM_GET_PRIV_WITH_RETURN(priv, (DRMFILE)(uintptr_t)DRM_CURRENTPID); + DRM_LOCK(); + priv = drm_find_file_by_proc(dev, DRM_CURPROC); + DRM_UNLOCK(); + if (priv == NULL) { + DRM_ERROR("can't find authenticator\n"); + return EINVAL; + } if (!priv->authenticated) return DRM_ERR(EACCES); - if (dev->dma - && offset >= 0 - && offset < ptoa(dev->dma->page_count)) + DRM_SPINLOCK(&dev->dma_lock); + if (dev->dma && offset >= 0 && offset < ptoa(dev->dma->page_count)) { + drm_device_dma_t *dma = dev->dma; + + if (dma->pagelist != NULL) { + unsigned long page = offset >> PAGE_SHIFT; + unsigned long phys = dma->pagelist[page]; + #if defined(__FreeBSD__) && __FreeBSD_version >= 500102 - return drm_dma_mmap(kdev, offset, paddr, prot); + *paddr = phys; + DRM_SPINUNLOCK(&dev->dma_lock); + return 0; #else - return drm_dma_mmap(kdev, offset, prot); -#endif + return atop(phys); +#endif + } else { + DRM_SPINUNLOCK(&dev->dma_lock); + return -1; + } + } + DRM_SPINUNLOCK(&dev->dma_lock); /* A sequential search of a linked list is fine here because: 1) there will only be @@ -89,23 +80,27 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot) once, so it doesn't have to be optimized for performance, even if the list was a bit longer. */ + DRM_LOCK(); TAILQ_FOREACH(listentry, dev->maplist, link) { map = listentry->map; -/* DRM_DEBUG("considering 0x%x..0x%x\n", map->offset, map->offset + map->size - 1);*/ - if (offset >= map->offset - && offset < map->offset + map->size) break; + if (offset >= map->offset && offset < map->offset + map->size) + break; } if (!listentry) { + DRM_UNLOCK(); DRM_DEBUG("can't find map\n"); return -1; } if (((map->flags&_DRM_RESTRICTED) && DRM_SUSER(DRM_CURPROC))) { + DRM_UNLOCK(); DRM_DEBUG("restricted map\n"); return -1; } + type = map->type; + DRM_UNLOCK(); - switch (map->type) { + switch (type) { case _DRM_FRAME_BUFFER: case _DRM_REGISTERS: case _DRM_AGP: -- cgit v1.2.3