Commit f116cc56 authored by Thomas Hellstrom's avatar Thomas Hellstrom Committed by Dave Airlie

drm: disable tasklets not IRQs when taking the drm lock spinlock

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent af6061af
...@@ -323,7 +323,6 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -323,7 +323,6 @@ int drm_release(struct inode *inode, struct file *filp)
struct drm_file *file_priv = filp->private_data; struct drm_file *file_priv = filp->private_data;
struct drm_device *dev = file_priv->minor->dev; struct drm_device *dev = file_priv->minor->dev;
int retcode = 0; int retcode = 0;
unsigned long irqflags;
lock_kernel(); lock_kernel();
...@@ -355,11 +354,9 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -355,11 +354,9 @@ int drm_release(struct inode *inode, struct file *filp)
*/ */
do{ do{
spin_lock_irqsave(&dev->lock.spinlock, spin_lock_bh(&dev->lock.spinlock);
irqflags);
locked = dev->lock.idle_has_lock; locked = dev->lock.idle_has_lock;
spin_unlock_irqrestore(&dev->lock.spinlock, spin_unlock_bh(&dev->lock.spinlock);
irqflags);
if (locked) if (locked)
break; break;
schedule(); schedule();
......
...@@ -53,7 +53,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) ...@@ -53,7 +53,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
DECLARE_WAITQUEUE(entry, current); DECLARE_WAITQUEUE(entry, current);
struct drm_lock *lock = data; struct drm_lock *lock = data;
int ret = 0; int ret = 0;
unsigned long irqflags;
++file_priv->lock_count; ++file_priv->lock_count;
...@@ -72,9 +71,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) ...@@ -72,9 +71,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
return -EINVAL; return -EINVAL;
add_wait_queue(&dev->lock.lock_queue, &entry); add_wait_queue(&dev->lock.lock_queue, &entry);
spin_lock_irqsave(&dev->lock.spinlock, irqflags); spin_lock_bh(&dev->lock.spinlock);
dev->lock.user_waiters++; dev->lock.user_waiters++;
spin_unlock_irqrestore(&dev->lock.spinlock, irqflags); spin_unlock_bh(&dev->lock.spinlock);
for (;;) { for (;;) {
__set_current_state(TASK_INTERRUPTIBLE); __set_current_state(TASK_INTERRUPTIBLE);
if (!dev->lock.hw_lock) { if (!dev->lock.hw_lock) {
...@@ -96,9 +95,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) ...@@ -96,9 +95,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
break; break;
} }
} }
spin_lock_irqsave(&dev->lock.spinlock, irqflags); spin_lock_bh(&dev->lock.spinlock);
dev->lock.user_waiters--; dev->lock.user_waiters--;
spin_unlock_irqrestore(&dev->lock.spinlock, irqflags); spin_unlock_bh(&dev->lock.spinlock);
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
remove_wait_queue(&dev->lock.lock_queue, &entry); remove_wait_queue(&dev->lock.lock_queue, &entry);
...@@ -199,9 +198,8 @@ int drm_lock_take(struct drm_lock_data *lock_data, ...@@ -199,9 +198,8 @@ int drm_lock_take(struct drm_lock_data *lock_data,
{ {
unsigned int old, new, prev; unsigned int old, new, prev;
volatile unsigned int *lock = &lock_data->hw_lock->lock; volatile unsigned int *lock = &lock_data->hw_lock->lock;
unsigned long irqflags;
spin_lock_irqsave(&lock_data->spinlock, irqflags); spin_lock_bh(&lock_data->spinlock);
do { do {
old = *lock; old = *lock;
if (old & _DRM_LOCK_HELD) if (old & _DRM_LOCK_HELD)
...@@ -213,7 +211,7 @@ int drm_lock_take(struct drm_lock_data *lock_data, ...@@ -213,7 +211,7 @@ int drm_lock_take(struct drm_lock_data *lock_data,
} }
prev = cmpxchg(lock, old, new); prev = cmpxchg(lock, old, new);
} while (prev != old); } while (prev != old);
spin_unlock_irqrestore(&lock_data->spinlock, irqflags); spin_unlock_bh(&lock_data->spinlock);
if (_DRM_LOCKING_CONTEXT(old) == context) { if (_DRM_LOCKING_CONTEXT(old) == context) {
if (old & _DRM_LOCK_HELD) { if (old & _DRM_LOCK_HELD) {
...@@ -274,16 +272,15 @@ int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context) ...@@ -274,16 +272,15 @@ int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
{ {
unsigned int old, new, prev; unsigned int old, new, prev;
volatile unsigned int *lock = &lock_data->hw_lock->lock; volatile unsigned int *lock = &lock_data->hw_lock->lock;
unsigned long irqflags;
spin_lock_irqsave(&lock_data->spinlock, irqflags); spin_lock_bh(&lock_data->spinlock);
if (lock_data->kernel_waiters != 0) { if (lock_data->kernel_waiters != 0) {
drm_lock_transfer(lock_data, 0); drm_lock_transfer(lock_data, 0);
lock_data->idle_has_lock = 1; lock_data->idle_has_lock = 1;
spin_unlock_irqrestore(&lock_data->spinlock, irqflags); spin_unlock_bh(&lock_data->spinlock);
return 1; return 1;
} }
spin_unlock_irqrestore(&lock_data->spinlock, irqflags); spin_unlock_bh(&lock_data->spinlock);
do { do {
old = *lock; old = *lock;
...@@ -347,20 +344,19 @@ static int drm_notifier(void *priv) ...@@ -347,20 +344,19 @@ static int drm_notifier(void *priv)
void drm_idlelock_take(struct drm_lock_data *lock_data) void drm_idlelock_take(struct drm_lock_data *lock_data)
{ {
int ret = 0; int ret = 0;
unsigned long irqflags;
spin_lock_irqsave(&lock_data->spinlock, irqflags); spin_lock_bh(&lock_data->spinlock);
lock_data->kernel_waiters++; lock_data->kernel_waiters++;
if (!lock_data->idle_has_lock) { if (!lock_data->idle_has_lock) {
spin_unlock_irqrestore(&lock_data->spinlock, irqflags); spin_unlock_bh(&lock_data->spinlock);
ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT); ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT);
spin_lock_irqsave(&lock_data->spinlock, irqflags); spin_lock_bh(&lock_data->spinlock);
if (ret == 1) if (ret == 1)
lock_data->idle_has_lock = 1; lock_data->idle_has_lock = 1;
} }
spin_unlock_irqrestore(&lock_data->spinlock, irqflags); spin_unlock_bh(&lock_data->spinlock);
} }
EXPORT_SYMBOL(drm_idlelock_take); EXPORT_SYMBOL(drm_idlelock_take);
...@@ -368,9 +364,8 @@ void drm_idlelock_release(struct drm_lock_data *lock_data) ...@@ -368,9 +364,8 @@ void drm_idlelock_release(struct drm_lock_data *lock_data)
{ {
unsigned int old, prev; unsigned int old, prev;
volatile unsigned int *lock = &lock_data->hw_lock->lock; volatile unsigned int *lock = &lock_data->hw_lock->lock;
unsigned long irqflags;
spin_lock_irqsave(&lock_data->spinlock, irqflags); spin_lock_bh(&lock_data->spinlock);
if (--lock_data->kernel_waiters == 0) { if (--lock_data->kernel_waiters == 0) {
if (lock_data->idle_has_lock) { if (lock_data->idle_has_lock) {
do { do {
...@@ -381,7 +376,7 @@ void drm_idlelock_release(struct drm_lock_data *lock_data) ...@@ -381,7 +376,7 @@ void drm_idlelock_release(struct drm_lock_data *lock_data)
lock_data->idle_has_lock = 0; lock_data->idle_has_lock = 0;
} }
} }
spin_unlock_irqrestore(&lock_data->spinlock, irqflags); spin_unlock_bh(&lock_data->spinlock);
} }
EXPORT_SYMBOL(drm_idlelock_release); EXPORT_SYMBOL(drm_idlelock_release);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment