From e5b4f19417b75a2d7c1e36934f60a3e836c4337e Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Sun, 24 Aug 2008 17:00:00 +1000 Subject: 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 --- drivers/gpu/drm/drm_irq.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/drm_irq.c') 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) { struct drm_device *dev = (struct drm_device *)data; unsigned long irqflags; - + void (*tasklet_func)(struct drm_device *); + spin_lock_irqsave(&dev->tasklet_lock, irqflags); + tasklet_func = dev->locked_tasklet_func; + spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); - if (!dev->locked_tasklet_func || + if (!tasklet_func || !drm_lock_take(&dev->lock, DRM_KERNEL_CONTEXT)) { - spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); return; } dev->lock.lock_time = jiffies; atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); - dev->locked_tasklet_func(dev); + spin_lock_irqsave(&dev->tasklet_lock, irqflags); + tasklet_func = dev->locked_tasklet_func; + dev->locked_tasklet_func = NULL; + spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); + + if (tasklet_func != NULL) + tasklet_func(dev); drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT); - - dev->locked_tasklet_func = NULL; - - spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); } /** -- cgit v1.2.3