Received: by 10.223.185.116 with SMTP id b49csp982522wrg; Sun, 11 Feb 2018 01:42:03 -0800 (PST) X-Google-Smtp-Source: AH8x2271ePNP/HtPmbuY1D7HME71ij/e0QZV1tnohIZNIN58KJz6NqKOLYzqI0lBK8j5WMCAED5e X-Received: by 2002:a17:902:b216:: with SMTP id t22-v6mr7813895plr.414.1518342123603; Sun, 11 Feb 2018 01:42:03 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518342123; cv=none; d=google.com; s=arc-20160816; b=e5od2xfadArJdR96OnvyPfS/Cd3gu8U+DFgefNRTNu/AQMOsIrxlpFjdHQ34BFjQoZ zsYjdDKcG410cTBwyuc43xMaKyXAzwv2rccdIw1TD9ijev7WJDASZ/rFwg/sciiBHiSE N/GGqPh4BFAwOLRSVNCWXx0AqsBF7h9pUSv4NVEiyTHoqXNMnrhEhCtbNlytLnALiBYJ fb0JLWcZp/xPYiF5/4LrbPMV+M4JCMqFCeGl3Olvj0ZhRdse7nPnpDcLjm0x7FNVYoSr m5rKnNWea2wGTkygh25pE0kAyCDg029H0XS9+PSDqmQBk9EeqD/M+qOokNOzqDlRffOt kF/w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:date:from:references :in-reply-to:message-id:arc-authentication-results; bh=J4aNk5sOPE5VcgrmB1rNG/gpjKIVRSSnFbGXlYLgv8s=; b=kizbDhPVNL/tC3hcP1NYSXyo42V7cJ7hQAjru9rQkNxoIkKqssIPvlMusMfoWW8MOr TPY+C1+p7fGXZDlJCJf1AhwSA2Nq/KiAfsVrZv+5E4zLLyp86hDcz+YZAih9QYRsXfKK YOFXMg4Tr8jxPef9gWpcHz0vKWUHcukTZAKw9MRYM6Y+RsLHr0QzlZ7nY7lJAYUlm7Jt YOeDgiLMzwE30tHHxvWER6HSiXhbenb64vGoXGASHfWdWNJ+/3mv4VnSI5bEkfkUeabE UjSnFaTma/mTT5sUYjD5wxrXEovTalDDKd161JMXJQeNTf8nzFYTE4RU/gnUDGi0dD7O zyRw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id j186si571444pge.177.2018.02.11.01.41.49; Sun, 11 Feb 2018 01:42:03 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753371AbeBKJkl (ORCPT + 99 others); Sun, 11 Feb 2018 04:40:41 -0500 Received: from mailout3.hostsharing.net ([176.9.242.54]:43045 "EHLO mailout3.hostsharing.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752834AbeBKJkk (ORCPT ); Sun, 11 Feb 2018 04:40:40 -0500 Received: from h08.hostsharing.net (h08.hostsharing.net [83.223.95.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "*.hostsharing.net", Issuer "COMODO RSA Domain Validation Secure Server CA" (not verified)) by mailout3.hostsharing.net (Postfix) with ESMTPS id B7A76100B08B0; Sun, 11 Feb 2018 10:40:48 +0100 (CET) Received: from localhost (6-38-90-81.adsl.cmo.de [81.90.38.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by h08.hostsharing.net (Postfix) with ESMTPSA id 4B56E603E052; Sun, 11 Feb 2018 10:40:37 +0100 (CET) X-Mailbox-Line: From 4c9bf72aacae1eef062bd134cd112e0770a7f121 Mon Sep 17 00:00:00 2001 Message-Id: <4c9bf72aacae1eef062bd134cd112e0770a7f121.1518338789.git.lukas@wunner.de> In-Reply-To: References: From: Lukas Wunner Date: Sun, 11 Feb 2018 10:38:28 +0100 Subject: [PATCH 5/5] drm/amdgpu: Fix deadlock on runtime suspend To: Tejun Heo , Lai Jiangshan , Alex Deucher , Dave Airlie , Ben Skeggs Cc: dri-devel@lists.freedesktop.org, Peter Wu , nouveau@lists.freedesktop.org, Lyude Paul , Hans de Goede , Pierre Moreau , linux-kernel@vger.kernel.org, Ismo Toijala , intel-gfx@lists.freedesktop.org, Liviu Dudau , Archit Taneja Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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. Fixes: d38ceaf99ed0 ("drm/amdgpu: add core driver (v4)") Cc: stable@vger.kernel.org # v4.2+: 1234567890ab: workqueue: Allow retrieval of current task's work struct Cc: stable@vger.kernel.org # v4.2+: 1234567890ab: drm: Allow determining if current task is output poll worker Cc: Alex Deucher Signed-off-by: Lukas Wunner --- drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 58 +++++++++++++++++--------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 8ca3783f2deb..74d2efaec52f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -736,9 +736,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); @@ -757,8 +759,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; } @@ -868,9 +874,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) @@ -924,8 +932,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; } @@ -988,9 +998,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; @@ -1115,8 +1127,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; } @@ -1359,9 +1373,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; @@ -1429,8 +1445,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; } -- 2.15.1