Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+21 -24
+20 -23
drivers/gpu/drm/i915/intel_dp_mst.c
··· 109 109 110 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 114 ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr); 115 115 if (ret) { ··· 134 134 /* and this can also fail */ 135 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 139 intel_dp->active_mst_links--; 140 - intel_mst->port = NULL; 140 + 141 + intel_mst->connector = NULL; 141 142 if (intel_dp->active_mst_links == 0) { 142 143 intel_dig_port->base.post_disable(&intel_dig_port->base); 143 144 intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); ··· 178 177 found->encoder = encoder; 179 178 180 179 DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); 181 - intel_mst->port = found->port; 180 + 181 + intel_mst->connector = found; 182 182 183 183 if (intel_dp->active_mst_links == 0) { 184 184 intel_prepare_ddi_buffer(&intel_dig_port->base); ··· 197 195 } 198 196 199 197 ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr, 200 - intel_mst->port, 198 + intel_mst->connector->port, 201 199 intel_crtc->config->pbn, &slots); 202 200 if (ret == false) { 203 201 DRM_ERROR("failed to allocate vcpi\n"); ··· 246 244 { 247 245 struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); 248 246 *pipe = intel_mst->pipe; 249 - if (intel_mst->port) 247 + if (intel_mst->connector) 250 248 return true; 251 249 return false; 252 250 } ··· 310 308 struct edid *edid; 311 309 int ret; 312 310 313 - edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port); 314 - if (!edid) 315 - return 0; 311 + if (!intel_dp) { 312 + return intel_connector_update_modes(connector, NULL); 313 + } 316 314 315 + edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port); 317 316 ret = intel_connector_update_modes(connector, edid); 318 317 kfree(edid); 319 318 ··· 327 324 struct intel_connector *intel_connector = to_intel_connector(connector); 328 325 struct intel_dp *intel_dp = intel_connector->mst_port; 329 326 327 + if (!intel_dp) 328 + return connector_status_disconnected; 330 329 return drm_dp_mst_detect_port(connector, &intel_dp->mst_mgr, intel_connector->port); 331 330 } 332 331 ··· 394 389 struct intel_dp *intel_dp = intel_connector->mst_port; 395 390 struct intel_crtc *crtc = to_intel_crtc(state->crtc); 396 391 392 + if (!intel_dp) 393 + return NULL; 397 394 return &intel_dp->mst_encoders[crtc->pipe]->base.base; 398 395 } 399 396 ··· 403 396 { 404 397 struct intel_connector *intel_connector = to_intel_connector(connector); 405 398 struct intel_dp *intel_dp = intel_connector->mst_port; 399 + if (!intel_dp) 400 + return NULL; 406 401 return &intel_dp->mst_encoders[0]->base.base; 407 402 } 408 403 ··· 515 506 516 507 /* need to nuke the connector */ 517 508 drm_modeset_lock_all(dev); 518 - if (connector->state->crtc) { 519 - struct drm_mode_set set; 520 - int ret; 521 - 522 - memset(&set, 0, sizeof(set)); 523 - set.crtc = connector->state->crtc, 524 - 525 - ret = drm_atomic_helper_set_config(&set); 526 - 527 - WARN(ret, "Disabling mst crtc failed with %i\n", ret); 528 - } 529 - 530 509 intel_connector_remove_from_fbdev(intel_connector); 531 - drm_connector_cleanup(connector); 510 + intel_connector->mst_port = NULL; 532 511 drm_modeset_unlock_all(dev); 533 512 534 - kfree(intel_connector); 513 + drm_connector_unreference(&intel_connector->base); 535 514 DRM_DEBUG_KMS("\n"); 536 515 } 537 516
+1 -1
drivers/gpu/drm/i915/intel_drv.h
··· 883 883 struct intel_encoder base; 884 884 enum pipe pipe; 885 885 struct intel_digital_port *primary; 886 - void *port; /* store this opaque as its illegal to dereference it */ 886 + struct intel_connector *connector; 887 887 }; 888 888 889 889 static inline enum dpio_channel