diff options
author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2014-08-11 06:15:35 -0400 |
---|---|---|
committer | Jani Nikula <jani.nikula@intel.com> | 2014-08-18 03:42:40 -0400 |
commit | 208bf9fdcd3575aa4a5d48b3e0295f7cdaf6fc44 (patch) | |
tree | b33603d0c3129b59cc5b3d695e3bee8ea9d06354 /drivers/gpu/drm | |
parent | 7d1311b93e58ed55f3a31cc8f94c4b8fe988a2b9 (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.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_tv.c | 7 |
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 | |||
712 | out: | 717 | out: |
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 | |||
8467 | retry: | 8465 | retry: |
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 | ||
8583 | void intel_release_load_detect_pipe(struct drm_connector *connector, | 8578 | void 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 | |||
8617 | unlock: | ||
8618 | drm_modeset_drop_locks(ctx); | ||
8619 | drm_modeset_acquire_fini(ctx); | ||
8620 | } | 8609 | } |
8621 | 8610 | ||
8622 | static int i9xx_pll_refclk(struct drm_device *dev, | 8611 | static 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 | ||
12685 | static bool | 12672 | static 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); |
832 | void intel_release_load_detect_pipe(struct drm_connector *connector, | 832 | void 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); | ||
835 | int intel_pin_and_fence_fb_obj(struct drm_device *dev, | 834 | int 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 | ||