]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
drm/i915: Hold the spinlock whilst resetting unpin_work along error path
authorChris Wilson <chris@chris-wilson.co.uk>
Thu, 27 May 2010 12:18:13 +0000 (13:18 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 2 Aug 2010 17:30:04 +0000 (10:30 -0700)
commit 468f0b44ce4b002ca7d9260f802a341854752c02 upstream.

Delay taking the mutex until we need to and ensure that we hold the
spinlock when resetting unpin_work on the error path. Also defer the
debugging print messages until after we have released the spinlock.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Kristian Høgsberg <krh@bitplanet.net>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/gpu/drm/i915/intel_display.c

index 188f50ee1f43fdbcc0a8361d72af55afa7f61f70..8cde72858dd91b93a09309ef15d768bc7964e816 100644 (file)
@@ -4239,8 +4239,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        if (work == NULL)
                return -ENOMEM;
 
-       mutex_lock(&dev->struct_mutex);
-
        work->event = event;
        work->dev = crtc->dev;
        intel_fb = to_intel_framebuffer(crtc->fb);
@@ -4250,10 +4248,10 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        /* We borrow the event spin lock for protecting unpin_work */
        spin_lock_irqsave(&dev->event_lock, flags);
        if (intel_crtc->unpin_work) {
-               DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
                spin_unlock_irqrestore(&dev->event_lock, flags);
                kfree(work);
-               mutex_unlock(&dev->struct_mutex);
+
+               DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
                return -EBUSY;
        }
        intel_crtc->unpin_work = work;
@@ -4262,13 +4260,19 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        intel_fb = to_intel_framebuffer(fb);
        obj = intel_fb->obj;
 
+       mutex_lock(&dev->struct_mutex);
        ret = intel_pin_and_fence_fb_obj(dev, obj);
        if (ret != 0) {
-               DRM_DEBUG_DRIVER("flip queue: %p pin & fence failed\n",
-                         to_intel_bo(obj));
-               kfree(work);
-               intel_crtc->unpin_work = NULL;
                mutex_unlock(&dev->struct_mutex);
+
+               spin_lock_irqsave(&dev->event_lock, flags);
+               intel_crtc->unpin_work = NULL;
+               spin_unlock_irqrestore(&dev->event_lock, flags);
+
+               kfree(work);
+
+               DRM_DEBUG_DRIVER("flip queue: %p pin & fence failed\n",
+                                to_intel_bo(obj));
                return ret;
        }