aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2014-08-11 06:15:35 -0400
committerJani Nikula <jani.nikula@intel.com>2014-08-18 03:42:40 -0400
commit208bf9fdcd3575aa4a5d48b3e0295f7cdaf6fc44 (patch)
treeb33603d0c3129b59cc5b3d695e3bee8ea9d06354 /drivers/gpu/drm
parent7d1311b93e58ed55f3a31cc8f94c4b8fe988a2b9 (diff)
drm/i915: Fix locking for intel_enable_pipe_a()
intel_enable_pipe_a() gets called with all the modeset locks already held (by drm_modeset_lock_all()), so trying to grab the same locks using another drm_modeset_acquire_ctx is going to fail miserably. Move most of the drm_modeset_acquire_ctx handling (init/drop/fini) out from intel_{get,release}_load_detect_pipe() into the callers (intel_{crt,tv}_detect()). Only the actual locking and backoff handling is left in intel_get_load_detect_pipe(). And in intel_enable_pipe_a() we just share the mode_config.acquire_ctx from drm_modeset_lock_all() which is already holding all the relevant locks. It's perfectly legal to lock the same ww_mutex multiple times using the same ww_acquire_ctx. drm_modeset_lock() will convert the returned -EALREADY into 0, so the caller doesn't need to do antyhing special. Fixes a hang on resume on my 830. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: stable@vger.kernel.org Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c7
-rw-r--r--drivers/gpu/drm/i915/intel_display.c21
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h3
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c7
4 files changed, 17 insertions, 21 deletions
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 2efaf8e8d9c4..e8abfce40976 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -699,16 +699,21 @@ intel_crt_detect(struct drm_connector *connector, bool force)
699 goto out; 699 goto out;
700 } 700 }
701 701
702 drm_modeset_acquire_init(&ctx, 0);
703
702 /* for pre-945g platforms use load detect */ 704 /* for pre-945g platforms use load detect */
703 if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) { 705 if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) {
704 if (intel_crt_detect_ddc(connector)) 706 if (intel_crt_detect_ddc(connector))
705 status = connector_status_connected; 707 status = connector_status_connected;
706 else 708 else
707 status = intel_crt_load_detect(crt); 709 status = intel_crt_load_detect(crt);
708 intel_release_load_detect_pipe(connector, &tmp, &ctx); 710 intel_release_load_detect_pipe(connector, &tmp);
709 } else 711 } else
710 status = connector_status_unknown; 712 status = connector_status_unknown;
711 713
714 drm_modeset_drop_locks(&ctx);
715 drm_modeset_acquire_fini(&ctx);
716
712out: 717out:
713 intel_display_power_put(dev_priv, power_domain); 718 intel_display_power_put(dev_priv, power_domain);
714 return status; 719 return status;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 018fb7222f60..f02c80d4039c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8462,8 +8462,6 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
8462 connector->base.id, connector->name, 8462 connector->base.id, connector->name,
8463 encoder->base.id, encoder->name); 8463 encoder->base.id, encoder->name);
8464 8464
8465 drm_modeset_acquire_init(ctx, 0);
8466
8467retry: 8465retry:
8468 ret = drm_modeset_lock(&config->connection_mutex, ctx); 8466 ret = drm_modeset_lock(&config->connection_mutex, ctx);
8469 if (ret) 8467 if (ret)
@@ -8574,15 +8572,11 @@ fail_unlock:
8574 goto retry; 8572 goto retry;
8575 } 8573 }
8576 8574
8577 drm_modeset_drop_locks(ctx);
8578 drm_modeset_acquire_fini(ctx);
8579
8580 return false; 8575 return false;
8581} 8576}
8582 8577
8583void intel_release_load_detect_pipe(struct drm_connector *connector, 8578void intel_release_load_detect_pipe(struct drm_connector *connector,
8584 struct intel_load_detect_pipe *old, 8579 struct intel_load_detect_pipe *old)
8585 struct drm_modeset_acquire_ctx *ctx)
8586{ 8580{
8587 struct intel_encoder *intel_encoder = 8581 struct intel_encoder *intel_encoder =
8588 intel_attached_encoder(connector); 8582 intel_attached_encoder(connector);
@@ -8606,17 +8600,12 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
8606 drm_framebuffer_unreference(old->release_fb); 8600 drm_framebuffer_unreference(old->release_fb);
8607 } 8601 }
8608 8602
8609 goto unlock;
8610 return; 8603 return;
8611 } 8604 }
8612 8605
8613 /* Switch crtc and encoder back off if necessary */ 8606 /* Switch crtc and encoder back off if necessary */
8614 if (old->dpms_mode != DRM_MODE_DPMS_ON) 8607 if (old->dpms_mode != DRM_MODE_DPMS_ON)
8615 connector->funcs->dpms(connector, old->dpms_mode); 8608 connector->funcs->dpms(connector, old->dpms_mode);
8616
8617unlock:
8618 drm_modeset_drop_locks(ctx);
8619 drm_modeset_acquire_fini(ctx);
8620} 8609}
8621 8610
8622static int i9xx_pll_refclk(struct drm_device *dev, 8611static int i9xx_pll_refclk(struct drm_device *dev,
@@ -12659,7 +12648,7 @@ static void intel_enable_pipe_a(struct drm_device *dev)
12659 struct intel_connector *connector; 12648 struct intel_connector *connector;
12660 struct drm_connector *crt = NULL; 12649 struct drm_connector *crt = NULL;
12661 struct intel_load_detect_pipe load_detect_temp; 12650 struct intel_load_detect_pipe load_detect_temp;
12662 struct drm_modeset_acquire_ctx ctx; 12651 struct drm_modeset_acquire_ctx *ctx = dev->mode_config.acquire_ctx;
12663 12652
12664 /* We can't just switch on the pipe A, we need to set things up with a 12653 /* We can't just switch on the pipe A, we need to set things up with a
12665 * proper mode and output configuration. As a gross hack, enable pipe A 12654 * proper mode and output configuration. As a gross hack, enable pipe A
@@ -12676,10 +12665,8 @@ static void intel_enable_pipe_a(struct drm_device *dev)
12676 if (!crt) 12665 if (!crt)
12677 return; 12666 return;
12678 12667
12679 if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, &ctx)) 12668 if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, ctx))
12680 intel_release_load_detect_pipe(crt, &load_detect_temp, &ctx); 12669 intel_release_load_detect_pipe(crt, &load_detect_temp);
12681
12682
12683} 12670}
12684 12671
12685static bool 12672static bool
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 4b2664bd5b81..fe3431f96900 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -830,8 +830,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
830 struct intel_load_detect_pipe *old, 830 struct intel_load_detect_pipe *old,
831 struct drm_modeset_acquire_ctx *ctx); 831 struct drm_modeset_acquire_ctx *ctx);
832void intel_release_load_detect_pipe(struct drm_connector *connector, 832void intel_release_load_detect_pipe(struct drm_connector *connector,
833 struct intel_load_detect_pipe *old, 833 struct intel_load_detect_pipe *old);
834 struct drm_modeset_acquire_ctx *ctx);
835int intel_pin_and_fence_fb_obj(struct drm_device *dev, 834int intel_pin_and_fence_fb_obj(struct drm_device *dev,
836 struct drm_i915_gem_object *obj, 835 struct drm_i915_gem_object *obj,
837 struct intel_engine_cs *pipelined); 836 struct intel_engine_cs *pipelined);
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index e211eef4b7e4..32186a656816 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1323,11 +1323,16 @@ intel_tv_detect(struct drm_connector *connector, bool force)
1323 struct intel_load_detect_pipe tmp; 1323 struct intel_load_detect_pipe tmp;
1324 struct drm_modeset_acquire_ctx ctx; 1324 struct drm_modeset_acquire_ctx ctx;
1325 1325
1326 drm_modeset_acquire_init(&ctx, 0);
1327
1326 if (intel_get_load_detect_pipe(connector, &mode, &tmp, &ctx)) { 1328 if (intel_get_load_detect_pipe(connector, &mode, &tmp, &ctx)) {
1327 type = intel_tv_detect_type(intel_tv, connector); 1329 type = intel_tv_detect_type(intel_tv, connector);
1328 intel_release_load_detect_pipe(connector, &tmp, &ctx); 1330 intel_release_load_detect_pipe(connector, &tmp);
1329 } else 1331 } else
1330 return connector_status_unknown; 1332 return connector_status_unknown;
1333
1334 drm_modeset_drop_locks(&ctx);
1335 drm_modeset_acquire_fini(&ctx);
1331 } else 1336 } else
1332 return connector->status; 1337 return connector->status;
1333 1338