Received: by 2002:a05:6a10:a852:0:0:0:0 with SMTP id d18csp361586pxy; Wed, 5 May 2021 04:12:09 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxU5dc4ojXA3iRgW/SFkRDD2nhj9daoCv5b3LgYLON38OpjBvunukMCD5EYYK6UmRrsMWPk X-Received: by 2002:a63:4f50:: with SMTP id p16mr6775571pgl.245.1620213128856; Wed, 05 May 2021 04:12:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1620213128; cv=none; d=google.com; s=arc-20160816; b=CIU/HNHvZcnv/GpHSiS6f5dx2CtjNuOf6itE9s0NYzmuTImX/1TF+WgAA9Vbvpjq6L UshKCjFOPOThYuwCiMgzJGlicpdqbNywJbCN+he3G4SomkPVEnSxXQ/d0tcH7OLCGzYa E3wKAbb7qIKpKZefCXIGCEMRQen0xclWWo9AwO0Ku/W5e8e1xGpXSKfHbzpguNNuXTf4 0zHk51M8PNlL+KforWZv3Jr/MZxtPtU9jhAzy8yVq5kmDrArMW2IVPtcZS7L6EFphp2G hZCRlE8HTzawm+WBP6p8dIZveSZoSRSqRc0XhAA2EJPlgJlbedY0Md5RCssq9Aizk2wg rAhg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from; bh=BFkSS9BPBtz7g58m14LvgY4IY8j1oioUvEfYpKeBuHY=; b=u/U1oO2aPBl58nRSRVpBc/Oyq5L66yfkmaclhcZTpGnHfiN8l9Fju7rr6AGaDpEffd kXQrB0dlL44YY+riRiZcS6qYgseNmD0QWavXyhkb75Lwar3GSWNQ+m7hK2i3gZn1/oER G02h4mPmbQv2xeUS8sjvuDT3xfNEgbNKKyNPqkrrsQUKwQ10TlXs869Skfdh7u3XV6NN AMeIYfqARtfLDpd+1RXfXjxU+hA8ab/KwFEMtcPQkiMDMvHZNC360bdBNIEPjpE4DCWt 57j/09BjiVfdH/WI9yewfrqkq1u5RahrLNoeOFgFzuDpaFecDWgwb0iT4+EBqdNZMXsy MjFw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id h16si80481pgg.516.2021.05.05.04.11.56; Wed, 05 May 2021 04:12:08 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232764AbhEELK2 (ORCPT + 99 others); Wed, 5 May 2021 07:10:28 -0400 Received: from muru.com ([72.249.23.125]:51880 "EHLO muru.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232517AbhEELKW (ORCPT ); Wed, 5 May 2021 07:10:22 -0400 Received: from hillo.muru.com (localhost [127.0.0.1]) by muru.com (Postfix) with ESMTP id AABA980DB; Wed, 5 May 2021 11:09:26 +0000 (UTC) From: Tony Lindgren To: "Rafael J . Wysocki" Cc: Ulf Hansson , linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, Laurent Pinchart , Sebastian Reichel , Tomi Valkeinen Subject: [PATCH] PM: runtime: Fix unpaired parent child_count for force_resume Date: Wed, 5 May 2021 14:09:15 +0300 Message-Id: <20210505110915.6861-1-tony@atomide.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org As pm_runtime_need_not_resume() relies also on usage_count, it can return a different value in pm_runtime_force_suspend() compared to when called in pm_runtime_force_resume(). Different return values can happen if anything calls PM runtime functions in between, and causes the parent child_count to increase on every resume. So far I've seen the issue only for omapdrm that does complicated things with PM runtime calls during system suspend for legacy reasons: omap_atomic_commit_tail() for omapdrm.0 dispc_runtime_get() wakes up 58000000.dss as it's the dispc parent dispc_runtime_resume() rpm_resume() increases parent child_count dispc_runtime_put() won't idle, PM runtime suspend blocked pm_runtime_force_suspend() for 58000000.dss, !pm_runtime_need_not_resume() __update_runtime_status() system suspended pm_runtime_force_resume() for 58000000.dss, pm_runtime_need_not_resume() pm_runtime_enable() only called because of pm_runtime_need_not_resume() omap_atomic_commit_tail() for omapdrm.0 dispc_runtime_get() wakes up 58000000.dss as it's the dispc parent dispc_runtime_resume() rpm_resume() increases parent child_count dispc_runtime_put() won't idle, PM runtime suspend blocked ... rpm_suspend for 58000000.dss but parent child_count is now unbalanced Let's fix the issue by adding a flag for needs_force_resume and use it in pm_runtime_force_resume() instead of pm_runtime_need_not_resume(). Additionally omapdrm system suspend could be simplified later on to avoid lots of unnecessary PM runtime calls and the complexity it adds. The driver can just use internal functions that are shared between the PM runtime and system suspend related functions. Fixes: 4918e1f87c5f ("PM / runtime: Rework pm_runtime_force_suspend/resume()") Cc: Laurent Pinchart Cc: Sebastian Reichel Cc: Tomi Valkeinen Signed-off-by: Tony Lindgren --- drivers/base/power/runtime.c | 10 +++++++--- include/linux/pm.h | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1637,6 +1637,7 @@ void pm_runtime_init(struct device *dev) dev->power.request_pending = false; dev->power.request = RPM_REQ_NONE; dev->power.deferred_resume = false; + dev->power.needs_force_resume = 0; INIT_WORK(&dev->power.work, pm_runtime_work); dev->power.timer_expires = 0; @@ -1804,10 +1805,12 @@ int pm_runtime_force_suspend(struct device *dev) * its parent, but set its status to RPM_SUSPENDED anyway in case this * function will be called again for it in the meantime. */ - if (pm_runtime_need_not_resume(dev)) + if (pm_runtime_need_not_resume(dev)) { pm_runtime_set_suspended(dev); - else + } else { __update_runtime_status(dev, RPM_SUSPENDED); + dev->power.needs_force_resume = 1; + } return 0; @@ -1834,7 +1837,7 @@ int pm_runtime_force_resume(struct device *dev) int (*callback)(struct device *); int ret = 0; - if (!pm_runtime_status_suspended(dev) || pm_runtime_need_not_resume(dev)) + if (!pm_runtime_status_suspended(dev) || !dev->power.needs_force_resume) goto out; /* @@ -1853,6 +1856,7 @@ int pm_runtime_force_resume(struct device *dev) pm_runtime_mark_last_busy(dev); out: + dev->power.needs_force_resume = 0; pm_runtime_enable(dev); return ret; } diff --git a/include/linux/pm.h b/include/linux/pm.h --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -602,6 +602,7 @@ struct dev_pm_info { unsigned int idle_notification:1; unsigned int request_pending:1; unsigned int deferred_resume:1; + unsigned int needs_force_resume:1; unsigned int runtime_auto:1; bool ignore_children:1; unsigned int no_callbacks:1; -- 2.31.1