From f935675f0c07f87da2facc4c144d511e6da48240 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 18 Aug 2015 13:40:05 +0200 Subject: [PATCH] drm/i915: Change locking for struct_mutex, v3. 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 Reviewed-by: Matt Roper #v1 Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 36e7e29ea266..8393759782d0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -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 -- 2.20.1