diff options
author | Dave Airlie <airlied@redhat.com> | 2016-03-08 20:14:38 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-05-04 22:52:07 -0400 |
commit | 0552f7651bc233e5407ab06ba97a9d7c25e19580 (patch) | |
tree | aa9578663848ec66d4fb7f3076a286b5bb98ef9b /drivers/gpu/drm/i915/intel_dp_mst.c | |
parent | d2307dea14a4f14a4b5db01b6d40a30fa6117e6c (diff) |
drm/i915/mst: use reference counted connectors. (v3)
Don't just free the connector when we get the destroy callback.
Drop a reference to it, and set it's mst_port to NULL so
no more mst work is done on it.
v2: core mst accepts NULLs fine. Cleanup EDID code properly.
v3: drop the extra reference we were taking.
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp_mst.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp_mst.c | 43 |
1 files changed, 20 insertions, 23 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 94b4e833dadd..b6bf7fd0b806 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c | |||
@@ -109,7 +109,7 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder) | |||
109 | 109 | ||
110 | DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); | 110 | DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); |
111 | 111 | ||
112 | drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, intel_mst->port); | 112 | drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, intel_mst->connector->port); |
113 | 113 | ||
114 | ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr); | 114 | ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr); |
115 | if (ret) { | 115 | if (ret) { |
@@ -134,10 +134,11 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder) | |||
134 | /* and this can also fail */ | 134 | /* and this can also fail */ |
135 | drm_dp_update_payload_part2(&intel_dp->mst_mgr); | 135 | drm_dp_update_payload_part2(&intel_dp->mst_mgr); |
136 | 136 | ||
137 | drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, intel_mst->port); | 137 | drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, intel_mst->connector->port); |
138 | 138 | ||
139 | intel_dp->active_mst_links--; | 139 | intel_dp->active_mst_links--; |
140 | intel_mst->port = NULL; | 140 | |
141 | intel_mst->connector = NULL; | ||
141 | if (intel_dp->active_mst_links == 0) { | 142 | if (intel_dp->active_mst_links == 0) { |
142 | intel_dig_port->base.post_disable(&intel_dig_port->base); | 143 | intel_dig_port->base.post_disable(&intel_dig_port->base); |
143 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); | 144 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); |
@@ -177,7 +178,8 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder) | |||
177 | found->encoder = encoder; | 178 | found->encoder = encoder; |
178 | 179 | ||
179 | DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); | 180 | DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); |
180 | intel_mst->port = found->port; | 181 | |
182 | intel_mst->connector = found; | ||
181 | 183 | ||
182 | if (intel_dp->active_mst_links == 0) { | 184 | if (intel_dp->active_mst_links == 0) { |
183 | intel_prepare_ddi_buffer(&intel_dig_port->base); | 185 | intel_prepare_ddi_buffer(&intel_dig_port->base); |
@@ -195,7 +197,7 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder) | |||
195 | } | 197 | } |
196 | 198 | ||
197 | ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr, | 199 | ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr, |
198 | intel_mst->port, | 200 | intel_mst->connector->port, |
199 | intel_crtc->config->pbn, &slots); | 201 | intel_crtc->config->pbn, &slots); |
200 | if (ret == false) { | 202 | if (ret == false) { |
201 | DRM_ERROR("failed to allocate vcpi\n"); | 203 | DRM_ERROR("failed to allocate vcpi\n"); |
@@ -244,7 +246,7 @@ static bool intel_dp_mst_enc_get_hw_state(struct intel_encoder *encoder, | |||
244 | { | 246 | { |
245 | struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); | 247 | struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); |
246 | *pipe = intel_mst->pipe; | 248 | *pipe = intel_mst->pipe; |
247 | if (intel_mst->port) | 249 | if (intel_mst->connector) |
248 | return true; | 250 | return true; |
249 | return false; | 251 | return false; |
250 | } | 252 | } |
@@ -308,10 +310,11 @@ static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector) | |||
308 | struct edid *edid; | 310 | struct edid *edid; |
309 | int ret; | 311 | int ret; |
310 | 312 | ||
311 | edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port); | 313 | if (!intel_dp) { |
312 | if (!edid) | 314 | return intel_connector_update_modes(connector, NULL); |
313 | return 0; | 315 | } |
314 | 316 | ||
317 | edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port); | ||
315 | ret = intel_connector_update_modes(connector, edid); | 318 | ret = intel_connector_update_modes(connector, edid); |
316 | kfree(edid); | 319 | kfree(edid); |
317 | 320 | ||
@@ -324,6 +327,8 @@ intel_dp_mst_detect(struct drm_connector *connector, bool force) | |||
324 | struct intel_connector *intel_connector = to_intel_connector(connector); | 327 | struct intel_connector *intel_connector = to_intel_connector(connector); |
325 | struct intel_dp *intel_dp = intel_connector->mst_port; | 328 | struct intel_dp *intel_dp = intel_connector->mst_port; |
326 | 329 | ||
330 | if (!intel_dp) | ||
331 | return connector_status_disconnected; | ||
327 | return drm_dp_mst_detect_port(connector, &intel_dp->mst_mgr, intel_connector->port); | 332 | return drm_dp_mst_detect_port(connector, &intel_dp->mst_mgr, intel_connector->port); |
328 | } | 333 | } |
329 | 334 | ||
@@ -389,6 +394,8 @@ static struct drm_encoder *intel_mst_atomic_best_encoder(struct drm_connector *c | |||
389 | struct intel_dp *intel_dp = intel_connector->mst_port; | 394 | struct intel_dp *intel_dp = intel_connector->mst_port; |
390 | struct intel_crtc *crtc = to_intel_crtc(state->crtc); | 395 | struct intel_crtc *crtc = to_intel_crtc(state->crtc); |
391 | 396 | ||
397 | if (!intel_dp) | ||
398 | return NULL; | ||
392 | return &intel_dp->mst_encoders[crtc->pipe]->base.base; | 399 | return &intel_dp->mst_encoders[crtc->pipe]->base.base; |
393 | } | 400 | } |
394 | 401 | ||
@@ -396,6 +403,8 @@ static struct drm_encoder *intel_mst_best_encoder(struct drm_connector *connecto | |||
396 | { | 403 | { |
397 | struct intel_connector *intel_connector = to_intel_connector(connector); | 404 | struct intel_connector *intel_connector = to_intel_connector(connector); |
398 | struct intel_dp *intel_dp = intel_connector->mst_port; | 405 | struct intel_dp *intel_dp = intel_connector->mst_port; |
406 | if (!intel_dp) | ||
407 | return NULL; | ||
399 | return &intel_dp->mst_encoders[0]->base.base; | 408 | return &intel_dp->mst_encoders[0]->base.base; |
400 | } | 409 | } |
401 | 410 | ||
@@ -506,23 +515,11 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, | |||
506 | 515 | ||
507 | /* need to nuke the connector */ | 516 | /* need to nuke the connector */ |
508 | drm_modeset_lock_all(dev); | 517 | drm_modeset_lock_all(dev); |
509 | if (connector->state->crtc) { | ||
510 | struct drm_mode_set set; | ||
511 | int ret; | ||
512 | |||
513 | memset(&set, 0, sizeof(set)); | ||
514 | set.crtc = connector->state->crtc, | ||
515 | |||
516 | ret = drm_atomic_helper_set_config(&set); | ||
517 | |||
518 | WARN(ret, "Disabling mst crtc failed with %i\n", ret); | ||
519 | } | ||
520 | |||
521 | intel_connector_remove_from_fbdev(intel_connector); | 518 | intel_connector_remove_from_fbdev(intel_connector); |
522 | drm_connector_cleanup(connector); | 519 | intel_connector->mst_port = NULL; |
523 | drm_modeset_unlock_all(dev); | 520 | drm_modeset_unlock_all(dev); |
524 | 521 | ||
525 | kfree(intel_connector); | 522 | drm_connector_unreference(&intel_connector->base); |
526 | DRM_DEBUG_KMS("\n"); | 523 | DRM_DEBUG_KMS("\n"); |
527 | } | 524 | } |
528 | 525 | ||