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>
This commit is contained in:
parent
7d1311b93e
commit
208bf9fdcd
@ -699,16 +699,21 @@ intel_crt_detect(struct drm_connector *connector, bool force)
|
||||
goto out;
|
||||
}
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
|
||||
/* for pre-945g platforms use load detect */
|
||||
if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) {
|
||||
if (intel_crt_detect_ddc(connector))
|
||||
status = connector_status_connected;
|
||||
else
|
||||
status = intel_crt_load_detect(crt);
|
||||
intel_release_load_detect_pipe(connector, &tmp, &ctx);
|
||||
intel_release_load_detect_pipe(connector, &tmp);
|
||||
} else
|
||||
status = connector_status_unknown;
|
||||
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
|
||||
out:
|
||||
intel_display_power_put(dev_priv, power_domain);
|
||||
return status;
|
||||
|
@ -8462,8 +8462,6 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
|
||||
connector->base.id, connector->name,
|
||||
encoder->base.id, encoder->name);
|
||||
|
||||
drm_modeset_acquire_init(ctx, 0);
|
||||
|
||||
retry:
|
||||
ret = drm_modeset_lock(&config->connection_mutex, ctx);
|
||||
if (ret)
|
||||
@ -8574,15 +8572,11 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
|
||||
goto retry;
|
||||
}
|
||||
|
||||
drm_modeset_drop_locks(ctx);
|
||||
drm_modeset_acquire_fini(ctx);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void intel_release_load_detect_pipe(struct drm_connector *connector,
|
||||
struct intel_load_detect_pipe *old,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
struct intel_load_detect_pipe *old)
|
||||
{
|
||||
struct intel_encoder *intel_encoder =
|
||||
intel_attached_encoder(connector);
|
||||
@ -8606,17 +8600,12 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
|
||||
drm_framebuffer_unreference(old->release_fb);
|
||||
}
|
||||
|
||||
goto unlock;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Switch crtc and encoder back off if necessary */
|
||||
if (old->dpms_mode != DRM_MODE_DPMS_ON)
|
||||
connector->funcs->dpms(connector, old->dpms_mode);
|
||||
|
||||
unlock:
|
||||
drm_modeset_drop_locks(ctx);
|
||||
drm_modeset_acquire_fini(ctx);
|
||||
}
|
||||
|
||||
static int i9xx_pll_refclk(struct drm_device *dev,
|
||||
@ -12659,7 +12648,7 @@ static void intel_enable_pipe_a(struct drm_device *dev)
|
||||
struct intel_connector *connector;
|
||||
struct drm_connector *crt = NULL;
|
||||
struct intel_load_detect_pipe load_detect_temp;
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
struct drm_modeset_acquire_ctx *ctx = dev->mode_config.acquire_ctx;
|
||||
|
||||
/* We can't just switch on the pipe A, we need to set things up with a
|
||||
* 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)
|
||||
if (!crt)
|
||||
return;
|
||||
|
||||
if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, &ctx))
|
||||
intel_release_load_detect_pipe(crt, &load_detect_temp, &ctx);
|
||||
|
||||
|
||||
if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, ctx))
|
||||
intel_release_load_detect_pipe(crt, &load_detect_temp);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -830,8 +830,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
|
||||
struct intel_load_detect_pipe *old,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
void intel_release_load_detect_pipe(struct drm_connector *connector,
|
||||
struct intel_load_detect_pipe *old,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
struct intel_load_detect_pipe *old);
|
||||
int intel_pin_and_fence_fb_obj(struct drm_device *dev,
|
||||
struct drm_i915_gem_object *obj,
|
||||
struct intel_engine_cs *pipelined);
|
||||
|
@ -1323,11 +1323,16 @@ intel_tv_detect(struct drm_connector *connector, bool force)
|
||||
struct intel_load_detect_pipe tmp;
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
|
||||
if (intel_get_load_detect_pipe(connector, &mode, &tmp, &ctx)) {
|
||||
type = intel_tv_detect_type(intel_tv, connector);
|
||||
intel_release_load_detect_pipe(connector, &tmp, &ctx);
|
||||
intel_release_load_detect_pipe(connector, &tmp);
|
||||
} else
|
||||
return connector_status_unknown;
|
||||
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
} else
|
||||
return connector->status;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user