Received: by 10.213.65.68 with SMTP id h4csp532065imn; Fri, 16 Mar 2018 10:35:34 -0700 (PDT) X-Google-Smtp-Source: AG47ELu5P+fwCQ4jtEAoaO00vX0nksELZK3dRG+39ZUFX9hQf1N0okxfYLegUojbwG6qCSWu0UTf X-Received: by 10.101.71.138 with SMTP id e10mr2121235pgs.317.1521221734119; Fri, 16 Mar 2018 10:35:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521221734; cv=none; d=google.com; s=arc-20160816; b=WI+Pi+jvqsAxRWUDieg02yahXCn+293dM9qDr1/lCzraDF32Unvm9k6jyQYguGsjN1 59sdR7m12x7/8GDDNqy0VsdyVqTW7FRjdPtypyQyklbP+4u3LfrQ8z1S4R2bG8K8+w+G ddsb68hch3VisZ2+aVU4cQnCpZZAY8TB36Fx062bcG3SyjB3lh0XayhCBWzz9V175DY3 zbY6aR4EWwcO99XiiHrHU3y65mXblKGih8rHR2qWU9zFGIY8ZTF8C/5VhWP/KwbwwweN 5BJ+kYiYUzKag7UlsxRxVimpnRgLXFUJE3My5MWd3Ce1JD/gqwSNl3+h7bXLapzlS6xX BojQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=0YdSRuqgC6OTplfVSHGgPFbrPLGueWcNwiqkPJAHyRI=; b=hLrUcA4xEIqhL2HF1JWTJMPF3s+vUYt0XSM7gLsi/TeKgfHva7P3Xt344UypIYtxRy O+Za4kCVWzeBCXhba6exGU7gyXhCdpTW891flrf5fQh/MJW7VKo1qvrzdWbE1Ta/VKMN ftHPvSOKK3nKLqEeX2JwiE/tIS3fGQcz4uj7NmRxFpydFkxNS5Bu6+dLOcSubBKPQlqk ZmewCwTSHlQOnugnNTKwLNrQo0i/SF2LDToCg2v2b7BcqtJbWF0i6FiSygc+cK9RJmCK bP7a8i96TVGYo2/aOKNhk6x1DMGV58MFd/v00z2ZgoLIO56+yU6zS+g+5f1bVnz5Q+u0 z8qQ== 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 u2-v6si6460580plm.476.2018.03.16.10.35.19; Fri, 16 Mar 2018 10:35:34 -0700 (PDT) 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 S1753816AbeCPReO (ORCPT + 99 others); Fri, 16 Mar 2018 13:34:14 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:34092 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753920AbeCPP1I (ORCPT ); Fri, 16 Mar 2018 11:27:08 -0400 Received: from localhost (LFbn-1-12247-202.w90-92.abo.wanadoo.fr [90.92.61.202]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id C4546124A; Fri, 16 Mar 2018 15:27:07 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Ismo Toijala , Alex Deucher , Dave Airlie , Lyude Paul , Lukas Wunner Subject: [PATCH 4.4 08/63] drm/radeon: Fix deadlock on runtime suspend Date: Fri, 16 Mar 2018 16:22:40 +0100 Message-Id: <20180316152301.007767775@linuxfoundation.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180316152259.964532775@linuxfoundation.org> References: <20180316152259.964532775@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.4-stable review patch. If anyone has any objections, please let me know. ------------------ From: Lukas Wunner commit 15734feff2bdac24aa3266c437cffa42851990e3 upstream. radeon'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 radeon'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. Stack trace for posterity: INFO: task kworker/0:3:31847 blocked for more than 120 seconds Workqueue: events output_poll_execute [drm_kms_helper] Call Trace: schedule+0x3c/0x90 rpm_resume+0x1e2/0x690 __pm_runtime_resume+0x3f/0x60 radeon_lvds_detect+0x39/0xf0 [radeon] output_poll_execute+0xda/0x1e0 [drm_kms_helper] process_one_work+0x14b/0x440 worker_thread+0x48/0x4a0 INFO: task kworker/2:0:10493 blocked for more than 120 seconds. Workqueue: pm pm_runtime_work Call Trace: schedule+0x3c/0x90 schedule_timeout+0x1b3/0x240 wait_for_common+0xc2/0x180 wait_for_completion+0x1d/0x20 flush_work+0xfc/0x1a0 __cancel_work_timer+0xa5/0x1d0 cancel_delayed_work_sync+0x13/0x20 drm_kms_helper_poll_disable+0x1f/0x30 [drm_kms_helper] radeon_pmops_runtime_suspend+0x3d/0xa0 [radeon] pci_pm_runtime_suspend+0x61/0x1a0 vga_switcheroo_runtime_suspend+0x21/0x70 __rpm_callback+0x32/0x70 rpm_callback+0x24/0x80 rpm_suspend+0x12b/0x640 pm_runtime_work+0x6f/0xb0 process_one_work+0x14b/0x440 worker_thread+0x48/0x4a0 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94147 Fixes: 10ebc0bc0934 ("drm/radeon: add runtime PM support (v2)") Cc: stable@vger.kernel.org # v3.13+: 27d4ee03078a: workqueue: Allow retrieval of current task's work struct Cc: stable@vger.kernel.org # v3.13+: 25c058ccaf2e: drm: Allow determining if current task is output poll worker Cc: Ismo Toijala Cc: Alex Deucher Cc: Dave Airlie Reviewed-by: Lyude Paul Signed-off-by: Lukas Wunner Link: https://patchwork.freedesktop.org/patch/msgid/64ea02c44f91dda19bc563902b97bbc699040392.1518338789.git.lukas@wunner.de Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_connectors.c | 74 +++++++++++++++++++---------- 1 file changed, 49 insertions(+), 25 deletions(-) --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -891,9 +891,11 @@ radeon_lvds_detect(struct drm_connector 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 radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); @@ -916,8 +918,12 @@ radeon_lvds_detect(struct drm_connector /* check acpi lid status ??? */ radeon_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; } @@ -1020,9 +1026,11 @@ radeon_vga_detect(struct drm_connector * 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 = radeon_best_single_encoder(connector); if (!encoder) @@ -1089,8 +1097,10 @@ radeon_vga_detect(struct drm_connector * radeon_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; } @@ -1153,9 +1163,11 @@ radeon_tv_detect(struct drm_connector *c if (!radeon_connector->dac_load_detect) return ret; - 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 = radeon_best_single_encoder(connector); if (!encoder) @@ -1167,8 +1179,12 @@ radeon_tv_detect(struct drm_connector *c if (ret == connector_status_connected) ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false); radeon_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; } @@ -1230,9 +1246,11 @@ radeon_dvi_detect(struct drm_connector * 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 (radeon_connector->detected_hpd_without_ddc) { force = true; @@ -1415,8 +1433,10 @@ out: } 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; } @@ -1666,9 +1686,11 @@ radeon_dp_detect(struct drm_connector *c if (radeon_dig_connector->is_mst) return connector_status_disconnected; - 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 && radeon_check_hpd_status_unchanged(connector)) { ret = connector->status; @@ -1755,8 +1777,10 @@ radeon_dp_detect(struct drm_connector *c } 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; }