diff options
author | Jesse Barnes <jbarnes@hobbes.lan> | 2008-06-10 17:31:54 -0700 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2008-06-10 17:31:54 -0700 |
commit | a1d96007241a78dd2b4a718df8e0568fe7994c22 (patch) | |
tree | b7a4bfaa77ddf957a6ade0c47d91e14a45b91659 /linux-core/drm_lock.c | |
parent | c987e76d953b6aecbfb69058fc4c387aa3fb33c9 (diff) | |
parent | 500c81d194115fb3c4b97d742519689478eeb4e8 (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.c | 58 |
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) { |