diff options
author | Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> | 2008-08-24 03:00:00 -0400 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2008-08-24 16:35:21 -0400 |
commit | e5b4f19417b75a2d7c1e36934f60a3e836c4337e (patch) | |
tree | 1daed2d024ce8f1b0ce586ceb29159d908a9bb4b | |
parent | 649ffc06a62bf487b78440669bdfeb637f1d675b (diff) |
drm: don't call the vblank tasklet with irqs disabled.
If a specific tasklet shares data with irq context,
it needs to take a private irq-blocking spinlock within
the tasklet itself.
Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r-- | drivers/gpu/drm/drm_irq.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_lock.c | 12 |
2 files changed, 17 insertions, 15 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 089c015c01d1..53f0e5af1cc8 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
@@ -400,27 +400,31 @@ static void drm_locked_tasklet_func(unsigned long data) | |||
400 | { | 400 | { |
401 | struct drm_device *dev = (struct drm_device *)data; | 401 | struct drm_device *dev = (struct drm_device *)data; |
402 | unsigned long irqflags; | 402 | unsigned long irqflags; |
403 | 403 | void (*tasklet_func)(struct drm_device *); | |
404 | |||
404 | spin_lock_irqsave(&dev->tasklet_lock, irqflags); | 405 | spin_lock_irqsave(&dev->tasklet_lock, irqflags); |
406 | tasklet_func = dev->locked_tasklet_func; | ||
407 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | ||
405 | 408 | ||
406 | if (!dev->locked_tasklet_func || | 409 | if (!tasklet_func || |
407 | !drm_lock_take(&dev->lock, | 410 | !drm_lock_take(&dev->lock, |
408 | DRM_KERNEL_CONTEXT)) { | 411 | DRM_KERNEL_CONTEXT)) { |
409 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | ||
410 | return; | 412 | return; |
411 | } | 413 | } |
412 | 414 | ||
413 | dev->lock.lock_time = jiffies; | 415 | dev->lock.lock_time = jiffies; |
414 | atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); | 416 | atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); |
415 | 417 | ||
416 | dev->locked_tasklet_func(dev); | 418 | spin_lock_irqsave(&dev->tasklet_lock, irqflags); |
419 | tasklet_func = dev->locked_tasklet_func; | ||
420 | dev->locked_tasklet_func = NULL; | ||
421 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | ||
422 | |||
423 | if (tasklet_func != NULL) | ||
424 | tasklet_func(dev); | ||
417 | 425 | ||
418 | drm_lock_free(&dev->lock, | 426 | drm_lock_free(&dev->lock, |
419 | DRM_KERNEL_CONTEXT); | 427 | DRM_KERNEL_CONTEXT); |
420 | |||
421 | dev->locked_tasklet_func = NULL; | ||
422 | |||
423 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | ||
424 | } | 428 | } |
425 | 429 | ||
426 | /** | 430 | /** |
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index 0998723cde79..d78e0dc18245 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c | |||
@@ -150,6 +150,7 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
150 | { | 150 | { |
151 | struct drm_lock *lock = data; | 151 | struct drm_lock *lock = data; |
152 | unsigned long irqflags; | 152 | unsigned long irqflags; |
153 | void (*tasklet_func)(struct drm_device *); | ||
153 | 154 | ||
154 | if (lock->context == DRM_KERNEL_CONTEXT) { | 155 | if (lock->context == DRM_KERNEL_CONTEXT) { |
155 | DRM_ERROR("Process %d using kernel context %d\n", | 156 | DRM_ERROR("Process %d using kernel context %d\n", |
@@ -158,14 +159,11 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
158 | } | 159 | } |
159 | 160 | ||
160 | spin_lock_irqsave(&dev->tasklet_lock, irqflags); | 161 | spin_lock_irqsave(&dev->tasklet_lock, irqflags); |
161 | 162 | tasklet_func = dev->locked_tasklet_func; | |
162 | if (dev->locked_tasklet_func) { | 163 | dev->locked_tasklet_func = NULL; |
163 | dev->locked_tasklet_func(dev); | ||
164 | |||
165 | dev->locked_tasklet_func = NULL; | ||
166 | } | ||
167 | |||
168 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | 164 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); |
165 | if (tasklet_func != NULL) | ||
166 | tasklet_func(dev); | ||
169 | 167 | ||
170 | atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]); | 168 | atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]); |
171 | 169 | ||