FAILED: patch "[PATCH] drm/amdgpu: Fix deadlock on runtime suspend" failed to apply to 4.15-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 4.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
aa0aad57909eb321746325951d66af88a83bc956Mon Sep 17 00:00:00 2001
From: Lukas Wunner <[email protected]>
Date: Sun, 11 Feb 2018 10:38:28 +0100
Subject: [PATCH] drm/amdgpu: Fix deadlock on runtime suspend
amdgpu's ->runtime_suspend hook calls drm_kms_helper_poll_disable(), which waits for the output poll worker to finish if it's running.
The output poll worker meanwhile calls pm_runtime_get_sync() in amdgpu's ->detect hooks, which waits for the ongoing suspend to finish, causing a deadlock.
Fix by not acquiring a runtime PM ref if the ->detect hooks are called in the output poll worker's context. This is safe because the poll worker is only enabled while runtime active and we know that ->runtime_suspend waits for it to finish.
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +38 -20
@@ -737,9 +737,11 @@ amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force)enum drm_connector_status ret = connector_status_disconnected;int r; - r =pm_runtime_get_sync (connector->dev->dev); -if (r <0 ) -return connector_status_disconnected; +if (!drm_kms_helper_is_poll_worker ()) { + r =pm_runtime_get_sync (connector->dev->dev); +if (r <0 ) +return connector_status_disconnected; + }if (encoder) {struct amdgpu_encoder *amdgpu_encoder =to_amdgpu_encoder (encoder);
@@ -758,8 +760,12 @@ amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force)/* check acpi lid status ??? */ amdgpu_connector_update_scratch_regs (connector, ret); -pm_runtime_mark_last_busy (connector->dev->dev); -pm_runtime_put_autosuspend (connector->dev->dev); + +if (!drm_kms_helper_is_poll_worker ()) { +pm_runtime_mark_last_busy (connector->dev->dev); +pm_runtime_put_autosuspend (connector->dev->dev); + } +return ret; }
@@ -869,9 +875,11 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)enum drm_connector_status ret = connector_status_disconnected;int r; - r =pm_runtime_get_sync (connector->dev->dev); -if (r <0 ) -return connector_status_disconnected; +if (!drm_kms_helper_is_poll_worker ()) { + r =pm_runtime_get_sync (connector->dev->dev); +if (r <0 ) +return connector_status_disconnected; + } encoder =amdgpu_connector_best_single_encoder (connector);if (!encoder)
@@ -925,8 +933,10 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)amdgpu_connector_update_scratch_regs (connector, ret); out: -pm_runtime_mark_last_busy (connector->dev->dev); -pm_runtime_put_autosuspend (connector->dev->dev); +if (!drm_kms_helper_is_poll_worker ()) { +pm_runtime_mark_last_busy (connector->dev->dev); +pm_runtime_put_autosuspend (connector->dev->dev); + }return ret; }
@@ -989,9 +999,11 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)enum drm_connector_status ret = connector_status_disconnected;bool dret = false, broken_edid = false; - r =pm_runtime_get_sync (connector->dev->dev); -if (r <0 ) -return connector_status_disconnected; +if (!drm_kms_helper_is_poll_worker ()) { + r =pm_runtime_get_sync (connector->dev->dev); +if (r <0 ) +return connector_status_disconnected; + }if (!force &&amdgpu_connector_check_hpd_status_unchanged (connector)) { ret = connector->status;
@@ -1116,8 +1128,10 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)amdgpu_connector_update_scratch_regs (connector, ret); exit: -pm_runtime_mark_last_busy (connector->dev->dev); -pm_runtime_put_autosuspend (connector->dev->dev); +if (!drm_kms_helper_is_poll_worker ()) { +pm_runtime_mark_last_busy (connector->dev->dev); +pm_runtime_put_autosuspend (connector->dev->dev); + }return ret; }
@@ -1360,9 +1374,11 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force)struct drm_encoder *encoder =amdgpu_connector_best_single_encoder (connector);int r; - r =pm_runtime_get_sync (connector->dev->dev); -if (r <0 ) -return connector_status_disconnected; +if (!drm_kms_helper_is_poll_worker ()) { + r =pm_runtime_get_sync (connector->dev->dev); +if (r <0 ) +return connector_status_disconnected; + }if (!force &&amdgpu_connector_check_hpd_status_unchanged (connector)) { ret = connector->status;
@@ -1430,8 +1446,10 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force)amdgpu_connector_update_scratch_regs (connector, ret); out: -pm_runtime_mark_last_busy (connector->dev->dev); -pm_runtime_put_autosuspend (connector->dev->dev); +if (!drm_kms_helper_is_poll_worker ()) { +pm_runtime_mark_last_busy (connector->dev->dev); +pm_runtime_put_autosuspend (connector->dev->dev); + }return ret; }