Commit 15c735e7 authored by Wayne Lin's avatar Wayne Lin Committed by Alex Deucher
Browse files

drm/amd/display: Grab dc_lock before detecting link



[Why & How]
There is chance we change dc state while calling dc_link_detect().
As the result of that, grab the dm.dc_lock before detecting link.

Reviewed-by: default avatarHersen Wu <hersen.wu@amd.com>
Acked-by: default avatarSolomon Chiu <solomon.chiu@amd.com>
Signed-off-by: default avatarWayne Lin <Wayne.Lin@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 3d4de925
Loading
Loading
Loading
Loading
+53 −32
Original line number Diff line number Diff line
@@ -2756,10 +2756,13 @@ static int dm_resume(void *handle)
		if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type))
			DRM_ERROR("KMS: Failed to detect connector\n");

		if (aconnector->base.force && new_connection_type == dc_connection_none)
		if (aconnector->base.force && new_connection_type == dc_connection_none) {
			emulated_link_detect(aconnector->dc_link);
		else
		} else {
			mutex_lock(&dm->dc_lock);
			dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
			mutex_unlock(&dm->dc_lock);
		}

		if (aconnector->fake_enable && aconnector->dc_link->local_sink)
			aconnector->fake_enable = false;
@@ -3090,6 +3093,7 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
#ifdef CONFIG_DRM_AMD_DC_HDCP
	struct dm_connector_state *dm_con_state = to_dm_connector_state(connector->state);
#endif
	bool ret = false;

	if (adev->dm.disable_hpd_irq)
		return;
@@ -3121,8 +3125,11 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)

		if (aconnector->base.force == DRM_FORCE_UNSPECIFIED)
			drm_kms_helper_connector_hotplug_event(connector);

	} else if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD)) {
	} else {
		mutex_lock(&adev->dm.dc_lock);
		ret = dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
		mutex_unlock(&adev->dm.dc_lock);
		if (ret) {
			amdgpu_dm_update_connector_after_detect(aconnector);

			drm_modeset_lock_all(dev);
@@ -3132,6 +3139,7 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
			if (aconnector->base.force == DRM_FORCE_UNSPECIFIED)
				drm_kms_helper_connector_hotplug_event(connector);
		}
	}
	mutex_unlock(&aconnector->hpd_lock);

}
@@ -3325,14 +3333,19 @@ static void handle_hpd_rx_irq(void *param)
			drm_modeset_unlock_all(dev);

			drm_kms_helper_connector_hotplug_event(connector);
		} else if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) {
		} else {
			bool ret = false;

			mutex_lock(&adev->dm.dc_lock);
			ret = dc_link_detect(dc_link, DETECT_REASON_HPDRX);
			mutex_unlock(&adev->dm.dc_lock);

			if (ret) {
				if (aconnector->fake_enable)
					aconnector->fake_enable = false;

				amdgpu_dm_update_connector_after_detect(aconnector);


				drm_modeset_lock_all(dev);
				dm_restore_drm_connector_state(dev, connector);
				drm_modeset_unlock_all(dev);
@@ -3340,6 +3353,7 @@ static void handle_hpd_rx_irq(void *param)
				drm_kms_helper_connector_hotplug_event(connector);
			}
		}
	}
#ifdef CONFIG_DRM_AMD_DC_HDCP
	if (hpd_irq_data.bytes.device_service_irq.bits.CP_IRQ) {
		if (adev->dm.hdcp_workqueue)
@@ -4342,12 +4356,20 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
		if (aconnector->base.force && new_connection_type == dc_connection_none) {
			emulated_link_detect(link);
			amdgpu_dm_update_connector_after_detect(aconnector);
		} else {
			bool ret = false;

			mutex_lock(&dm->dc_lock);
			ret = dc_link_detect(link, DETECT_REASON_BOOT);
			mutex_unlock(&dm->dc_lock);

		} else if (dc_link_detect(link, DETECT_REASON_BOOT)) {
			if (ret) {
				amdgpu_dm_update_connector_after_detect(aconnector);
				register_backlight_device(dm, link);

				if (dm->num_of_edps)
					update_connector_ext_caps(aconnector);

				if (psr_feature_enabled)
					amdgpu_dm_set_psr_caps(link);

@@ -4357,8 +4379,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
				if (link->psr_settings.psr_feature_enabled)
					adev_to_drm(adev)->vblank_disable_immediate = false;
			}


		}
	}

	/* Software is initialized. Now we can register interrupt handlers. */
+10 −1
Original line number Diff line number Diff line
@@ -1239,12 +1239,14 @@ static ssize_t trigger_hotplug(struct file *f, const char __user *buf,
	struct drm_connector *connector = &aconnector->base;
	struct dc_link *link = NULL;
	struct drm_device *dev = connector->dev;
	struct amdgpu_device *adev = drm_to_adev(dev);
	enum dc_connection_type new_connection_type = dc_connection_none;
	char *wr_buf = NULL;
	uint32_t wr_buf_size = 42;
	int max_param_num = 1;
	long param[1] = {0};
	uint8_t param_nums = 0;
	bool ret = false;

	if (!aconnector || !aconnector->dc_link)
		return -EINVAL;
@@ -1280,7 +1282,11 @@ static ssize_t trigger_hotplug(struct file *f, const char __user *buf,
			new_connection_type != dc_connection_none)
			goto unlock;

		if (!dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD))
		mutex_lock(&adev->dm.dc_lock);
		ret = dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
		mutex_unlock(&adev->dm.dc_lock);

		if (!ret)
			goto unlock;

		amdgpu_dm_update_connector_after_detect(aconnector);
@@ -3302,7 +3308,10 @@ static int trigger_hpd_mst_set(void *data, u64 val)
			aconnector = to_amdgpu_dm_connector(connector);
			if (aconnector->dc_link->type == dc_connection_mst_branch &&
			    aconnector->mst_mgr.aux) {
				mutex_lock(&adev->dm.dc_lock);
				dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
				mutex_unlock(&adev->dm.dc_lock);

				drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true);
			}
		}