summaryrefslogtreecommitdiff
path: root/bsd-core/drm_lock.c
diff options
context:
space:
mode:
authorEric Anholt <anholt@freebsd.org>2004-11-06 20:27:19 +0000
committerEric Anholt <anholt@freebsd.org>2004-11-06 20:27:19 +0000
commitae7a1713139f1eacec9cc1629cacef0394e270cc (patch)
treeea0f4e8439bc006c04695b396dd860ddfb16cc55 /bsd-core/drm_lock.c
parentcca29ac9becffc7d5fc8204c706621b842c3557d (diff)
Move the lock/unlock ioctls to a more logical place, in drm_lock.c.
Diffstat (limited to 'bsd-core/drm_lock.c')
-rw-r--r--bsd-core/drm_lock.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/bsd-core/drm_lock.c b/bsd-core/drm_lock.c
index 843fe567..af6f6a74 100644
--- a/bsd-core/drm_lock.c
+++ b/bsd-core/drm_lock.c
@@ -94,3 +94,82 @@ int drm_lock_free(drm_device_t *dev,
return 0;
}
+int drm_lock(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_lock_t lock;
+ int ret = 0;
+
+ DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t *)data, sizeof(lock));
+
+ if (lock.context == DRM_KERNEL_CONTEXT) {
+ DRM_ERROR("Process %d using kernel context %d\n",
+ DRM_CURRENTPID, lock.context);
+ return EINVAL;
+ }
+
+ DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
+ lock.context, DRM_CURRENTPID, dev->lock.hw_lock->lock, lock.flags);
+
+ if (dev->use_dma_queue && lock.context < 0)
+ return EINVAL;
+
+ DRM_LOCK();
+ for (;;) {
+ if (drm_lock_take(&dev->lock.hw_lock->lock, lock.context)) {
+ dev->lock.filp = (void *)(uintptr_t)DRM_CURRENTPID;
+ dev->lock.lock_time = jiffies;
+ atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
+ break; /* Got lock */
+ }
+
+ /* Contention */
+#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)
+ return ret;
+
+ /* XXX: Add signal blocking here */
+
+ if (dev->dma_quiescent != NULL && (lock.flags & _DRM_LOCK_QUIESCENT))
+ dev->dma_quiescent(dev);
+
+ return 0;
+}
+
+int drm_unlock(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_lock_t lock;
+
+ DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t *)data, sizeof(lock));
+
+ if (lock.context == DRM_KERNEL_CONTEXT) {
+ DRM_ERROR("Process %d using kernel context %d\n",
+ DRM_CURRENTPID, lock.context);
+ return EINVAL;
+ }
+
+ atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
+
+ DRM_LOCK();
+ drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
+
+ if (drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) {
+ DRM_ERROR("\n");
+ }
+ DRM_UNLOCK();
+
+ return 0;
+}