aboutsummaryrefslogtreecommitdiff
path: root/linux-core/drm_lock.c
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@hobbes.lan>2008-06-10 17:31:54 -0700
committerJesse Barnes <jbarnes@virtuousgeek.org>2008-06-10 17:31:54 -0700
commita1d96007241a78dd2b4a718df8e0568fe7994c22 (patch)
treeb7a4bfaa77ddf957a6ade0c47d91e14a45b91659 /linux-core/drm_lock.c
parentc987e76d953b6aecbfb69058fc4c387aa3fb33c9 (diff)
parent500c81d194115fb3c4b97d742519689478eeb4e8 (diff)
Merge commit 'origin/drm-gem' into modesetting-gem
Passed the compile test; it's ready to ship. Conflicts: libdrm/Makefile.am linux-core/Makefile.kernel linux-core/drmP.h linux-core/drm_memrange.c linux-core/drm_stub.c shared-core/drm.h shared-core/i915_dma.c shared-core/i915_drv.h shared-core/i915_irq.c
Diffstat (limited to 'linux-core/drm_lock.c')
-rw-r--r--linux-core/drm_lock.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/linux-core/drm_lock.c b/linux-core/drm_lock.c
index 6bbf1444..d2fb1feb 100644
--- a/linux-core/drm_lock.c
+++ b/linux-core/drm_lock.c
@@ -384,6 +384,64 @@ void drm_idlelock_release(struct drm_lock_data *lock_data)
}
EXPORT_SYMBOL(drm_idlelock_release);
+/**
+ * Takes the lock on behalf of the client if needed, using the kernel context.
+ *
+ * This allows us to hide the hardware lock when it's required for protection
+ * of data structures (such as command ringbuffer) shared with the X Server, an
+
+ * a way for us to transition to lockless for those requests when the X Server
+ * stops accessing the ringbuffer directly, without having to update the
+ * other userland clients.
+ */
+int drm_client_lock_take(struct drm_device *dev, struct drm_file *file_priv)
+{
+ struct drm_master *master = file_priv->master;
+ int ret;
+ unsigned long irqflags;
+
+ /* If the client has the lock, we're already done. */
+ if (drm_i_have_hw_lock(dev, file_priv))
+ return 0;
+
+ mutex_unlock (&dev->struct_mutex);
+ /* Client doesn't hold the lock. Block taking the lock with the kernel
+ * context on behalf of the client, and return whether we were
+ * successful.
+ */
+ spin_lock_irqsave(&master->lock.spinlock, irqflags);
+ master->lock.user_waiters++;
+ spin_unlock_irqrestore(&master->lock.spinlock, irqflags);
+ ret = wait_event_interruptible(master->lock.lock_queue,
+ drm_lock_take(&master->lock,
+ DRM_KERNEL_CONTEXT));
+ spin_lock_irqsave(&master->lock.spinlock, irqflags);
+ master->lock.user_waiters--;
+ if (ret != 0) {
+ spin_unlock_irqrestore(&master->lock.spinlock, irqflags);
+ } else {
+ master->lock.file_priv = file_priv;
+ master->lock.lock_time = jiffies;
+ master->lock.kernel_held = 1;
+ file_priv->lock_count++;
+ spin_unlock_irqrestore(&master->lock.spinlock, irqflags);
+ }
+ mutex_lock (&dev->struct_mutex);
+ return ret;
+}
+EXPORT_SYMBOL(drm_client_lock_take);
+
+void drm_client_lock_release(struct drm_device *dev, struct drm_file *file_priv)
+{
+ struct drm_master *master = file_priv->master;
+
+ if (master->lock.kernel_held) {
+ master->lock.kernel_held = 0;
+ master->lock.file_priv = NULL;
+ drm_lock_free(&master->lock, DRM_KERNEL_CONTEXT);
+ }
+}
+EXPORT_SYMBOL(drm_client_lock_release);
int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv)
{