diff options
author | Wayne Lin <Wayne.Lin@amd.com> | 2022-05-31 17:46:24 +0800 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2022-07-13 11:25:17 -0400 |
commit | 15c735e7990fdabb466a3341b6b2dfefd987127e (patch) | |
tree | 475ae30c83f972ad12ea39349ca90650ff05a689 /drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |
parent | 3d4de925356177dad0fb5869d1ea537cfa033009 (diff) | |
download | lwn-15c735e7990fdabb466a3341b6b2dfefd987127e.tar.gz lwn-15c735e7990fdabb466a3341b6b2dfefd987127e.zip |
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: Hersen Wu <hersen.wu@amd.com>
Acked-by: Solomon Chiu <solomon.chiu@amd.com>
Signed-off-by: Wayne Lin <Wayne.Lin@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 85 |
1 files changed, 53 insertions, 32 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 ea22bdae7a6e..081d28a92bbe 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -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,16 +3125,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); @@ -3325,19 +3333,25 @@ out: 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 @@ -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) { 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. */ |