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

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
...@@ -2756,10 +2756,13 @@ static int dm_resume(void *handle) ...@@ -2756,10 +2756,13 @@ static int dm_resume(void *handle)
if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type)) if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type))
DRM_ERROR("KMS: Failed to detect connector\n"); 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); emulated_link_detect(aconnector->dc_link);
else } else {
mutex_lock(&dm->dc_lock);
dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD); dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
mutex_unlock(&dm->dc_lock);
}
if (aconnector->fake_enable && aconnector->dc_link->local_sink) if (aconnector->fake_enable && aconnector->dc_link->local_sink)
aconnector->fake_enable = false; aconnector->fake_enable = false;
...@@ -3090,6 +3093,7 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector) ...@@ -3090,6 +3093,7 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
#ifdef CONFIG_DRM_AMD_DC_HDCP #ifdef CONFIG_DRM_AMD_DC_HDCP
struct dm_connector_state *dm_con_state = to_dm_connector_state(connector->state); struct dm_connector_state *dm_con_state = to_dm_connector_state(connector->state);
#endif #endif
bool ret = false;
if (adev->dm.disable_hpd_irq) if (adev->dm.disable_hpd_irq)
return; return;
...@@ -3121,16 +3125,20 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector) ...@@ -3121,16 +3125,20 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
if (aconnector->base.force == DRM_FORCE_UNSPECIFIED) if (aconnector->base.force == DRM_FORCE_UNSPECIFIED)
drm_kms_helper_connector_hotplug_event(connector); drm_kms_helper_connector_hotplug_event(connector);
} 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);
} else if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD)) { drm_modeset_lock_all(dev);
amdgpu_dm_update_connector_after_detect(aconnector); dm_restore_drm_connector_state(dev, connector);
drm_modeset_unlock_all(dev);
drm_modeset_lock_all(dev);
dm_restore_drm_connector_state(dev, connector);
drm_modeset_unlock_all(dev);
if (aconnector->base.force == DRM_FORCE_UNSPECIFIED) if (aconnector->base.force == DRM_FORCE_UNSPECIFIED)
drm_kms_helper_connector_hotplug_event(connector); drm_kms_helper_connector_hotplug_event(connector);
}
} }
mutex_unlock(&aconnector->hpd_lock); mutex_unlock(&aconnector->hpd_lock);
...@@ -3325,19 +3333,25 @@ static void handle_hpd_rx_irq(void *param) ...@@ -3325,19 +3333,25 @@ static void handle_hpd_rx_irq(void *param)
drm_modeset_unlock_all(dev); drm_modeset_unlock_all(dev);
drm_kms_helper_connector_hotplug_event(connector); drm_kms_helper_connector_hotplug_event(connector);
} else if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) { } else {
bool ret = false;
if (aconnector->fake_enable) mutex_lock(&adev->dm.dc_lock);
aconnector->fake_enable = false; ret = dc_link_detect(dc_link, DETECT_REASON_HPDRX);
mutex_unlock(&adev->dm.dc_lock);
amdgpu_dm_update_connector_after_detect(aconnector); if (ret) {
if (aconnector->fake_enable)
aconnector->fake_enable = false;
amdgpu_dm_update_connector_after_detect(aconnector);
drm_modeset_lock_all(dev); drm_modeset_lock_all(dev);
dm_restore_drm_connector_state(dev, connector); dm_restore_drm_connector_state(dev, connector);
drm_modeset_unlock_all(dev); drm_modeset_unlock_all(dev);
drm_kms_helper_connector_hotplug_event(connector); drm_kms_helper_connector_hotplug_event(connector);
}
} }
} }
#ifdef CONFIG_DRM_AMD_DC_HDCP #ifdef CONFIG_DRM_AMD_DC_HDCP
...@@ -4342,23 +4356,30 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) ...@@ -4342,23 +4356,30 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
if (aconnector->base.force && new_connection_type == dc_connection_none) { if (aconnector->base.force && new_connection_type == dc_connection_none) {
emulated_link_detect(link); emulated_link_detect(link);
amdgpu_dm_update_connector_after_detect(aconnector); amdgpu_dm_update_connector_after_detect(aconnector);
} else {
bool ret = false;
} else if (dc_link_detect(link, DETECT_REASON_BOOT)) { mutex_lock(&dm->dc_lock);
amdgpu_dm_update_connector_after_detect(aconnector); ret = dc_link_detect(link, DETECT_REASON_BOOT);
register_backlight_device(dm, link); mutex_unlock(&dm->dc_lock);
if (dm->num_of_edps)
update_connector_ext_caps(aconnector);
if (psr_feature_enabled)
amdgpu_dm_set_psr_caps(link);
/* TODO: Fix vblank control helpers to delay PSR entry to allow this when
* PSR is also supported.
*/
if (link->psr_settings.psr_feature_enabled)
adev_to_drm(adev)->vblank_disable_immediate = false;
}
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);
/* TODO: Fix vblank control helpers to delay PSR entry to allow this when
* PSR is also supported.
*/
if (link->psr_settings.psr_feature_enabled)
adev_to_drm(adev)->vblank_disable_immediate = false;
}
}
} }
/* Software is initialized. Now we can register interrupt handlers. */ /* Software is initialized. Now we can register interrupt handlers. */
......
...@@ -1239,12 +1239,14 @@ static ssize_t trigger_hotplug(struct file *f, const char __user *buf, ...@@ -1239,12 +1239,14 @@ static ssize_t trigger_hotplug(struct file *f, const char __user *buf,
struct drm_connector *connector = &aconnector->base; struct drm_connector *connector = &aconnector->base;
struct dc_link *link = NULL; struct dc_link *link = NULL;
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct amdgpu_device *adev = drm_to_adev(dev);
enum dc_connection_type new_connection_type = dc_connection_none; enum dc_connection_type new_connection_type = dc_connection_none;
char *wr_buf = NULL; char *wr_buf = NULL;
uint32_t wr_buf_size = 42; uint32_t wr_buf_size = 42;
int max_param_num = 1; int max_param_num = 1;
long param[1] = {0}; long param[1] = {0};
uint8_t param_nums = 0; uint8_t param_nums = 0;
bool ret = false;
if (!aconnector || !aconnector->dc_link) if (!aconnector || !aconnector->dc_link)
return -EINVAL; return -EINVAL;
...@@ -1280,7 +1282,11 @@ static ssize_t trigger_hotplug(struct file *f, const char __user *buf, ...@@ -1280,7 +1282,11 @@ static ssize_t trigger_hotplug(struct file *f, const char __user *buf,
new_connection_type != dc_connection_none) new_connection_type != dc_connection_none)
goto unlock; 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; goto unlock;
amdgpu_dm_update_connector_after_detect(aconnector); amdgpu_dm_update_connector_after_detect(aconnector);
...@@ -3302,7 +3308,10 @@ static int trigger_hpd_mst_set(void *data, u64 val) ...@@ -3302,7 +3308,10 @@ static int trigger_hpd_mst_set(void *data, u64 val)
aconnector = to_amdgpu_dm_connector(connector); aconnector = to_amdgpu_dm_connector(connector);
if (aconnector->dc_link->type == dc_connection_mst_branch && if (aconnector->dc_link->type == dc_connection_mst_branch &&
aconnector->mst_mgr.aux) { aconnector->mst_mgr.aux) {
mutex_lock(&adev->dm.dc_lock);
dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD); 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); drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment