From: Wayne Lin <wayne....@amd.com>

[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: Hersen Wu <hersen...@amd.com>
Acked-by: Solomon Chiu <solomon.c...@amd.com>
Signed-off-by: Wayne Lin <wayne....@amd.com>
Tested-by: Daniel Wheeler <daniel.whee...@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 85 ++++++++++++-------
 .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 11 ++-
 2 files changed, 63 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index de1c139ae279..000d34a7b6b4 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -2716,10 +2716,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;
@@ -3050,6 +3053,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;
@@ -3081,16 +3085,20 @@ 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 {
+               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)) {
-               amdgpu_dm_update_connector_after_detect(aconnector);
-
-               drm_modeset_lock_all(dev);
-               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)
-                       drm_kms_helper_connector_hotplug_event(connector);
+                       if (aconnector->base.force == DRM_FORCE_UNSPECIFIED)
+                               
drm_kms_helper_connector_hotplug_event(connector);
+               }
        }
        mutex_unlock(&aconnector->hpd_lock);
 
@@ -3285,19 +3293,25 @@ 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;
 
-                       if (aconnector->fake_enable)
-                               aconnector->fake_enable = false;
+                       mutex_lock(&adev->dm.dc_lock);
+                       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);
-                       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);
 
-                       drm_kms_helper_connector_hotplug_event(connector);
+                               
drm_kms_helper_connector_hotplug_event(connector);
+                       }
                }
        }
 #ifdef CONFIG_DRM_AMD_DC_HDCP
@@ -4302,23 +4316,30 @@ 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;
 
-               } else if (dc_link_detect(link, DETECT_REASON_BOOT)) {
-                       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;
-               }
+                       mutex_lock(&dm->dc_lock);
+                       ret = dc_link_detect(link, DETECT_REASON_BOOT);
+                       mutex_unlock(&dm->dc_lock);
 
+                       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. */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index 01c98ad06cf0..e0646db6fdbf 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -1243,12 +1243,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;
@@ -1284,7 +1286,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);
@@ -3306,7 +3312,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);
                        }
                }
-- 
2.25.1

Reply via email to