diff options
| author | Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> | 2008-05-06 22:22:39 -0400 |
|---|---|---|
| committer | Dave Airlie <airlied@linux.ie> | 2008-05-06 22:22:39 -0400 |
| commit | f116cc561eae0a426b8fa6b3e22e80ba0bcf7aee (patch) | |
| tree | 4af813d3ccdfdeb261bc892409cf4ed59d136930 | |
| parent | af6061af0d9f84a4665f88186dc1ff9e4fb78330 (diff) | |
drm: disable tasklets not IRQs when taking the drm lock spinlock
Signed-off-by: Dave Airlie <airlied@redhat.com>
| -rw-r--r-- | drivers/char/drm/drm_fops.c | 7 | ||||
| -rw-r--r-- | drivers/char/drm/drm_lock.c | 35 |
2 files changed, 17 insertions, 25 deletions
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c index 68f0da801ed..d2e6da85f58 100644 --- a/drivers/char/drm/drm_fops.c +++ b/drivers/char/drm/drm_fops.c | |||
| @@ -323,7 +323,6 @@ int drm_release(struct inode *inode, struct file *filp) | |||
| 323 | struct drm_file *file_priv = filp->private_data; | 323 | struct drm_file *file_priv = filp->private_data; |
| 324 | struct drm_device *dev = file_priv->minor->dev; | 324 | struct drm_device *dev = file_priv->minor->dev; |
| 325 | int retcode = 0; | 325 | int retcode = 0; |
| 326 | unsigned long irqflags; | ||
| 327 | 326 | ||
| 328 | lock_kernel(); | 327 | lock_kernel(); |
| 329 | 328 | ||
| @@ -355,11 +354,9 @@ int drm_release(struct inode *inode, struct file *filp) | |||
| 355 | */ | 354 | */ |
| 356 | 355 | ||
| 357 | do{ | 356 | do{ |
| 358 | spin_lock_irqsave(&dev->lock.spinlock, | 357 | spin_lock_bh(&dev->lock.spinlock); |
| 359 | irqflags); | ||
| 360 | locked = dev->lock.idle_has_lock; | 358 | locked = dev->lock.idle_has_lock; |
| 361 | spin_unlock_irqrestore(&dev->lock.spinlock, | 359 | spin_unlock_bh(&dev->lock.spinlock); |
| 362 | irqflags); | ||
| 363 | if (locked) | 360 | if (locked) |
| 364 | break; | 361 | break; |
| 365 | schedule(); | 362 | schedule(); |
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c index 12dcdd1832f..0998723cde7 100644 --- a/drivers/char/drm/drm_lock.c +++ b/drivers/char/drm/drm_lock.c | |||
| @@ -53,7 +53,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
| 53 | DECLARE_WAITQUEUE(entry, current); | 53 | DECLARE_WAITQUEUE(entry, current); |
| 54 | struct drm_lock *lock = data; | 54 | struct drm_lock *lock = data; |
| 55 | int ret = 0; | 55 | int ret = 0; |
| 56 | unsigned long irqflags; | ||
| 57 | 56 | ||
| 58 | ++file_priv->lock_count; | 57 | ++file_priv->lock_count; |
| 59 | 58 | ||
| @@ -72,9 +71,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
| 72 | return -EINVAL; | 71 | return -EINVAL; |
| 73 | 72 | ||
| 74 | add_wait_queue(&dev->lock.lock_queue, &entry); | 73 | add_wait_queue(&dev->lock.lock_queue, &entry); |
| 75 | spin_lock_irqsave(&dev->lock.spinlock, irqflags); | 74 | spin_lock_bh(&dev->lock.spinlock); |
| 76 | dev->lock.user_waiters++; | 75 | dev->lock.user_waiters++; |
| 77 | spin_unlock_irqrestore(&dev->lock.spinlock, irqflags); | 76 | spin_unlock_bh(&dev->lock.spinlock); |
| 78 | for (;;) { | 77 | for (;;) { |
| 79 | __set_current_state(TASK_INTERRUPTIBLE); | 78 | __set_current_state(TASK_INTERRUPTIBLE); |
| 80 | if (!dev->lock.hw_lock) { | 79 | if (!dev->lock.hw_lock) { |
| @@ -96,9 +95,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
| 96 | break; | 95 | break; |
| 97 | } | 96 | } |
| 98 | } | 97 | } |
| 99 | spin_lock_irqsave(&dev->lock.spinlock, irqflags); | 98 | spin_lock_bh(&dev->lock.spinlock); |
| 100 | dev->lock.user_waiters--; | 99 | dev->lock.user_waiters--; |
| 101 | spin_unlock_irqrestore(&dev->lock.spinlock, irqflags); | 100 | spin_unlock_bh(&dev->lock.spinlock); |
| 102 | __set_current_state(TASK_RUNNING); | 101 | __set_current_state(TASK_RUNNING); |
| 103 | remove_wait_queue(&dev->lock.lock_queue, &entry); | 102 | remove_wait_queue(&dev->lock.lock_queue, &entry); |
| 104 | 103 | ||
| @@ -199,9 +198,8 @@ int drm_lock_take(struct drm_lock_data *lock_data, | |||
| 199 | { | 198 | { |
| 200 | unsigned int old, new, prev; | 199 | unsigned int old, new, prev; |
| 201 | volatile unsigned int *lock = &lock_data->hw_lock->lock; | 200 | volatile unsigned int *lock = &lock_data->hw_lock->lock; |
| 202 | unsigned long irqflags; | ||
| 203 | 201 | ||
| 204 | spin_lock_irqsave(&lock_data->spinlock, irqflags); | 202 | spin_lock_bh(&lock_data->spinlock); |
| 205 | do { | 203 | do { |
| 206 | old = *lock; | 204 | old = *lock; |
| 207 | if (old & _DRM_LOCK_HELD) | 205 | if (old & _DRM_LOCK_HELD) |
| @@ -213,7 +211,7 @@ int drm_lock_take(struct drm_lock_data *lock_data, | |||
| 213 | } | 211 | } |
| 214 | prev = cmpxchg(lock, old, new); | 212 | prev = cmpxchg(lock, old, new); |
| 215 | } while (prev != old); | 213 | } while (prev != old); |
| 216 | spin_unlock_irqrestore(&lock_data->spinlock, irqflags); | 214 | spin_unlock_bh(&lock_data->spinlock); |
| 217 | 215 | ||
| 218 | if (_DRM_LOCKING_CONTEXT(old) == context) { | 216 | if (_DRM_LOCKING_CONTEXT(old) == context) { |
| 219 | if (old & _DRM_LOCK_HELD) { | 217 | if (old & _DRM_LOCK_HELD) { |
| @@ -274,16 +272,15 @@ int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context) | |||
| 274 | { | 272 | { |
| 275 | unsigned int old, new, prev; | 273 | unsigned int old, new, prev; |
| 276 | volatile unsigned int *lock = &lock_data->hw_lock->lock; | 274 | volatile unsigned int *lock = &lock_data->hw_lock->lock; |
| 277 | unsigned long irqflags; | ||
| 278 | 275 | ||
| 279 | spin_lock_irqsave(&lock_data->spinlock, irqflags); | 276 | spin_lock_bh(&lock_data->spinlock); |
| 280 | if (lock_data->kernel_waiters != 0) { | 277 | if (lock_data->kernel_waiters != 0) { |
| 281 | drm_lock_transfer(lock_data, 0); | 278 | drm_lock_transfer(lock_data, 0); |
| 282 | lock_data->idle_has_lock = 1; | 279 | lock_data->idle_has_lock = 1; |
| 283 | spin_unlock_irqrestore(&lock_data->spinlock, irqflags); | 280 | spin_unlock_bh(&lock_data->spinlock); |
| 284 | return 1; | 281 | return 1; |
| 285 | } | 282 | } |
| 286 | spin_unlock_irqrestore(&lock_data->spinlock, irqflags); | 283 | spin_unlock_bh(&lock_data->spinlock); |
| 287 | 284 | ||
| 288 | do { | 285 | do { |
| 289 | old = *lock; | 286 | old = *lock; |
| @@ -347,20 +344,19 @@ static int drm_notifier(void *priv) | |||
| 347 | void drm_idlelock_take(struct drm_lock_data *lock_data) | 344 | void drm_idlelock_take(struct drm_lock_data *lock_data) |
| 348 | { | 345 | { |
| 349 | int ret = 0; | 346 | int ret = 0; |
| 350 | unsigned long irqflags; | ||
| 351 | 347 | ||
| 352 | spin_lock_irqsave(&lock_data->spinlock, irqflags); | 348 | spin_lock_bh(&lock_data->spinlock); |
| 353 | lock_data->kernel_waiters++; | 349 | lock_data->kernel_waiters++; |
| 354 | if (!lock_data->idle_has_lock) { | 350 | if (!lock_data->idle_has_lock) { |
| 355 | 351 | ||
| 356 | spin_unlock_irqrestore(&lock_data->spinlock, irqflags); | 352 | spin_unlock_bh(&lock_data->spinlock); |
| 357 | ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT); | 353 | ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT); |
| 358 | spin_lock_irqsave(&lock_data->spinlock, irqflags); | 354 | spin_lock_bh(&lock_data->spinlock); |
| 359 | 355 | ||
| 360 | if (ret == 1) | 356 | if (ret == 1) |
| 361 | lock_data->idle_has_lock = 1; | 357 | lock_data->idle_has_lock = 1; |
| 362 | } | 358 | } |
| 363 | spin_unlock_irqrestore(&lock_data->spinlock, irqflags); | 359 | spin_unlock_bh(&lock_data->spinlock); |
| 364 | } | 360 | } |
| 365 | EXPORT_SYMBOL(drm_idlelock_take); | 361 | EXPORT_SYMBOL(drm_idlelock_take); |
| 366 | 362 | ||
| @@ -368,9 +364,8 @@ void drm_idlelock_release(struct drm_lock_data *lock_data) | |||
| 368 | { | 364 | { |
| 369 | unsigned int old, prev; | 365 | unsigned int old, prev; |
| 370 | volatile unsigned int *lock = &lock_data->hw_lock->lock; | 366 | volatile unsigned int *lock = &lock_data->hw_lock->lock; |
| 371 | unsigned long irqflags; | ||
| 372 | 367 | ||
| 373 | spin_lock_irqsave(&lock_data->spinlock, irqflags); | 368 | spin_lock_bh(&lock_data->spinlock); |
| 374 | if (--lock_data->kernel_waiters == 0) { | 369 | if (--lock_data->kernel_waiters == 0) { |
| 375 | if (lock_data->idle_has_lock) { | 370 | if (lock_data->idle_has_lock) { |
| 376 | do { | 371 | do { |
| @@ -381,7 +376,7 @@ void drm_idlelock_release(struct drm_lock_data *lock_data) | |||
| 381 | lock_data->idle_has_lock = 0; | 376 | lock_data->idle_has_lock = 0; |
| 382 | } | 377 | } |
| 383 | } | 378 | } |
| 384 | spin_unlock_irqrestore(&lock_data->spinlock, irqflags); | 379 | spin_unlock_bh(&lock_data->spinlock); |
| 385 | } | 380 | } |
| 386 | EXPORT_SYMBOL(drm_idlelock_release); | 381 | EXPORT_SYMBOL(drm_idlelock_release); |
| 387 | 382 | ||
