⬢ DragonFlyBSD Kernel Audit
DF-4910 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -383,6 +383,17 @@ static void dm_dp_destroy_mst_connector(
 	DRM_INFO("DM_MST: Disabling connector: %p [id: %d] [master: %p]\n",
 				aconnector, connector->base.id, aconnector->mst_port);
 
+	/*
+	 * Serialize with the mode_config.mutex-protected probe path
+	 * (drm_helper_probe_single_connector_modes ->
+	 * dm_dp_mst_get_modes), which does an unlocked-looking
+	 * check-then-set on aconnector->dc_sink and assigns
+	 * dc_sink->priv. Our only caller, drm_dp_destroy_connector_work()
+	 * (drm_dp_mst_topology.c), invokes this callback holding no locks,
+	 * so acquiring mode_config.mutex here cannot deadlock.
+	 */
+	mutex_lock(&dev->mode_config.mutex);
+
 	aconnector->port = NULL;
 	if (aconnector->dc_sink) {
 		amdgpu_dm_update_freesync_caps(connector, NULL);
@@ -392,6 +403,8 @@ static void dm_dp_destroy_mst_connector(
 		aconnector->dc_sink = NULL;
 	}
 
+	mutex_unlock(&dev->mode_config.mutex);
+
 	drm_connector_unregister(connector);
 	if (adev->mode_info.rfbdev)
 		drm_fb_helper_remove_one_connector(&adev->mode_info.rfbdev->helper, connector);