summaryrefslogtreecommitdiff
path: root/bsd-core/drm_vm.c
diff options
context:
space:
mode:
authorEric Anholt <anholt@freebsd.org>2004-11-07 04:11:15 +0000
committerEric Anholt <anholt@freebsd.org>2004-11-07 04:11:15 +0000
commita1d9e5abafe60ca2b7f96cadd1013695ada4ac41 (patch)
treeff8a462ecf2fea9ee35c8988ac0d9a37b7206808 /bsd-core/drm_vm.c
parentc5bededa5130a58273448188c04c15bc9c1097f3 (diff)
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).
Diffstat (limited to 'bsd-core/drm_vm.c')
-rw-r--r--bsd-core/drm_vm.c75
1 files changed, 35 insertions, 40 deletions
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
@@ -26,35 +26,6 @@
#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)
#elif defined(__FreeBSD__)
@@ -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: