Skip to content

Commit

Permalink
drm: disable tasklets not IRQs when taking the drm lock spinlock
Browse files Browse the repository at this point in the history
Signed-off-by: Dave Airlie <airlied@redhat.com>
  • Loading branch information
Thomas Hellstrom authored and Dave Airlie committed May 7, 2008
1 parent af6061a commit f116cc5
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 25 deletions.
7 changes: 2 additions & 5 deletions drivers/char/drm/drm_fops.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,6 @@ int drm_release(struct inode *inode, struct file *filp)
struct drm_file *file_priv = filp->private_data;
struct drm_device *dev = file_priv->minor->dev;
int retcode = 0;
unsigned long irqflags;

lock_kernel();

Expand Down Expand Up @@ -355,11 +354,9 @@ int drm_release(struct inode *inode, struct file *filp)
*/

do{
spin_lock_irqsave(&dev->lock.spinlock,
irqflags);
spin_lock_bh(&dev->lock.spinlock);
locked = dev->lock.idle_has_lock;
spin_unlock_irqrestore(&dev->lock.spinlock,
irqflags);
spin_unlock_bh(&dev->lock.spinlock);
if (locked)
break;
schedule();
Expand Down
35 changes: 15 additions & 20 deletions drivers/char/drm/drm_lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
DECLARE_WAITQUEUE(entry, current);
struct drm_lock *lock = data;
int ret = 0;
unsigned long irqflags;

++file_priv->lock_count;

Expand All @@ -72,9 +71,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
return -EINVAL;

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++;
spin_unlock_irqrestore(&dev->lock.spinlock, irqflags);
spin_unlock_bh(&dev->lock.spinlock);
for (;;) {
__set_current_state(TASK_INTERRUPTIBLE);
if (!dev->lock.hw_lock) {
Expand All @@ -96,9 +95,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
break;
}
}
spin_lock_irqsave(&dev->lock.spinlock, irqflags);
spin_lock_bh(&dev->lock.spinlock);
dev->lock.user_waiters--;
spin_unlock_irqrestore(&dev->lock.spinlock, irqflags);
spin_unlock_bh(&dev->lock.spinlock);
__set_current_state(TASK_RUNNING);
remove_wait_queue(&dev->lock.lock_queue, &entry);

Expand Down Expand Up @@ -199,9 +198,8 @@ int drm_lock_take(struct drm_lock_data *lock_data,
{
unsigned int old, new, prev;
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 {
old = *lock;
if (old & _DRM_LOCK_HELD)
Expand All @@ -213,7 +211,7 @@ int drm_lock_take(struct drm_lock_data *lock_data,
}
prev = cmpxchg(lock, old, new);
} while (prev != old);
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
spin_unlock_bh(&lock_data->spinlock);

if (_DRM_LOCKING_CONTEXT(old) == context) {
if (old & _DRM_LOCK_HELD) {
Expand Down Expand Up @@ -274,16 +272,15 @@ int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
{
unsigned int old, new, prev;
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) {
drm_lock_transfer(lock_data, 0);
lock_data->idle_has_lock = 1;
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
spin_unlock_bh(&lock_data->spinlock);
return 1;
}
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
spin_unlock_bh(&lock_data->spinlock);

do {
old = *lock;
Expand Down Expand Up @@ -347,30 +344,28 @@ static int drm_notifier(void *priv)
void drm_idlelock_take(struct drm_lock_data *lock_data)
{
int ret = 0;
unsigned long irqflags;

spin_lock_irqsave(&lock_data->spinlock, irqflags);
spin_lock_bh(&lock_data->spinlock);
lock_data->kernel_waiters++;
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);
spin_lock_irqsave(&lock_data->spinlock, irqflags);
spin_lock_bh(&lock_data->spinlock);

if (ret == 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);

void drm_idlelock_release(struct drm_lock_data *lock_data)
{
unsigned int old, prev;
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->idle_has_lock) {
do {
Expand All @@ -381,7 +376,7 @@ void drm_idlelock_release(struct drm_lock_data *lock_data)
lock_data->idle_has_lock = 0;
}
}
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
spin_unlock_bh(&lock_data->spinlock);
}
EXPORT_SYMBOL(drm_idlelock_release);

Expand Down

0 comments on commit f116cc5

Please sign in to comment.