drm/i915: Change locking for struct_mutex, v3.
authorMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Tue, 18 Aug 2015 11:40:05 +0000 (13:40 +0200)
committerMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Mon, 2 Nov 2015 14:50:24 +0000 (15:50 +0100)
struct_mutex is being locked for every plane in intel_prepare_plane_fb
and intel_cleanup_plane_fb.

Require the caller to hold the mutex, and only acquire the mutex for
each helper call. This way the lock only needs to be acquired
twice in ->atomic_commit(). Once for pinning new framebuffers at the
start, the second time for unpinning old framebuffer.

Changes since v1:
- Use mutex_lock_interruptible instead of i915 variant,
  to prevent a deadlock when called from the reset code.
Changes since v2:
- Clarify struct_mutex is locked by the caller.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: Matt Roper <matthew.d.roper@intel.com> #v1
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
drivers/gpu/drm/i915/intel_display.c

index 36e7e29ea266ccd9a21bdd8e6999ccf8650a163a..8393759782d0eb841f412e6380c3b94e87f07f24 100644 (file)
@@ -13165,8 +13165,13 @@ static int intel_atomic_prepare_commit(struct drm_device *dev,
                        return ret;
        }
 
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+
        ret = drm_atomic_helper_prepare_planes(dev, state);
 
+       mutex_unlock(&dev->struct_mutex);
        return ret;
 }
 
@@ -13268,7 +13273,10 @@ static int intel_atomic_commit(struct drm_device *dev,
        /* FIXME: add subpixel order */
 
        drm_atomic_helper_wait_for_vblanks(dev, state);
+
+       mutex_lock(&dev->struct_mutex);
        drm_atomic_helper_cleanup_planes(dev, state);
+       mutex_unlock(&dev->struct_mutex);
 
        if (any_ms)
                intel_modeset_check_state(dev, state);
@@ -13437,6 +13445,8 @@ static void intel_shared_dpll_init(struct drm_device *dev)
  * bits.  Some older platforms need special physical address handling for
  * cursor planes.
  *
+ * Must be called with struct_mutex held.
+ *
  * Returns 0 on success, negative error code on failure.
  */
 int
@@ -13453,10 +13463,6 @@ intel_prepare_plane_fb(struct drm_plane *plane,
        if (!obj && !old_obj)
                return 0;
 
-       ret = i915_mutex_lock_interruptible(dev);
-       if (ret)
-               return ret;
-
        if (old_obj) {
                struct drm_crtc_state *crtc_state =
                        drm_atomic_get_existing_crtc_state(new_state->state, plane->state->crtc);
@@ -13477,7 +13483,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
 
                /* Swallow -EIO errors to allow updates during hw lockup. */
                if (ret && ret != -EIO)
-                       goto out;
+                       return ret;
        }
 
        if (!obj) {
@@ -13495,9 +13501,6 @@ intel_prepare_plane_fb(struct drm_plane *plane,
        if (ret == 0)
                i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit);
 
-out:
-       mutex_unlock(&dev->struct_mutex);
-
        return ret;
 }
 
@@ -13507,6 +13510,8 @@ out:
  * @fb: old framebuffer that was on plane
  *
  * Cleans up a framebuffer that has just been removed from a plane.
+ *
+ * Must be called with struct_mutex held.
  */
 void
 intel_cleanup_plane_fb(struct drm_plane *plane,
@@ -13520,7 +13525,6 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
        if (!obj && !old_obj)
                return;
 
-       mutex_lock(&dev->struct_mutex);
        if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR ||
            !INTEL_INFO(dev)->cursor_needs_physical))
                intel_unpin_fb_obj(old_state->fb, old_state);
@@ -13529,7 +13533,6 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
        if ((old_obj && (old_obj->frontbuffer_bits & intel_plane->frontbuffer_bit)) ||
            (obj && !(obj->frontbuffer_bits & intel_plane->frontbuffer_bit)))
                i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit);
-       mutex_unlock(&dev->struct_mutex);
 }
 
 int