From patchwork Sat Jul 23 04:56:07 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Colin Cross X-Patchwork-Id: 1001572 Received: from smtp1.linux-foundation.org (smtp1.linux-foundation.org [140.211.169.13]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p6N50gqu008617 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL) for ; Sat, 23 Jul 2011 05:01:03 GMT Received: from daredevil.linux-foundation.org (localhost [127.0.0.1]) by smtp1.linux-foundation.org (8.14.2/8.13.5/Debian-3ubuntu1.1) with ESMTP id p6N4vJSm010367; Fri, 22 Jul 2011 21:57:20 -0700 Received: from smtp-out.google.com (smtp-out.google.com [216.239.44.51]) by smtp1.linux-foundation.org (8.14.2/8.13.5/Debian-3ubuntu1.1) with ESMTP id p6N4vEAi010357 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 22 Jul 2011 21:57:16 -0700 Received: from hpaq12.eem.corp.google.com (hpaq12.eem.corp.google.com [172.25.149.12]) by smtp-out.google.com with ESMTP id p6N4v9Jc014202; Fri, 22 Jul 2011 21:57:09 -0700 Received: from walnut.mtv.corp.google.com (walnut.mtv.corp.google.com [172.18.102.62]) by hpaq12.eem.corp.google.com with ESMTP id p6N4uw3Q022827; Fri, 22 Jul 2011 21:56:59 -0700 Received: by walnut.mtv.corp.google.com (Postfix, from userid 99897) id 8628D25773C; Fri, 22 Jul 2011 21:56:58 -0700 (PDT) From: Colin Cross To: linux-pm@lists.linux-foundation.org Date: Fri, 22 Jul 2011 21:56:07 -0700 Message-Id: <1311396967-16721-1-git-send-email-ccross@android.com> X-Mailer: git-send-email 1.7.4.1 X-System-Of-Record: true Received-SPF: pass (localhost is always allowed.) X-Spam-Status: No, hits=-6.223 required=5 tests=AWL, BAYES_00, OSDL_HEADER_SPF_PASS, OSDL_HEADER_SUBJECT_BRACKETED, PATCH_SUBJECT_OSDL X-Spam-Checker-Version: SpamAssassin 3.2.4-osdl_revision__1.47__ X-MIMEDefang-Filter: lf$Revision: 1.188 $ X-Scanned-By: MIMEDefang 2.63 on 140.211.169.21 Cc: linux-kernel@vger.kernel.org, Colin Cross Subject: [linux-pm] [PATCH] PM: runtime: add might_sleep to PM runtime functions X-BeenThere: linux-pm@lists.linux-foundation.org X-Mailman-Version: 2.1.9 Precedence: list List-Id: Linux power management List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-pm-bounces@lists.linux-foundation.org Errors-To: linux-pm-bounces@lists.linux-foundation.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Sat, 23 Jul 2011 05:01:03 +0000 (UTC) The list of functions that can be called in atomic context is non-intuitive (pm_runtime_put_sync can not, but pm_runtime_put_sync_suspend can, if pm_runtime_irq_safe has been called?). The code is actively misleading - the entry points all start with spin_lock_irqsave, suggesting they are safe to call in atomic context, but may later enable interrupts. Add might_sleep_if to all the __pm_runtime_* entry points to enforce correct usage. Also add pm_runtime_put_sync_autosuspend to the list of functions that can be called in atomic context. Signed-off-by: Colin Cross --- Documentation/power/runtime_pm.txt | 1 + drivers/base/power/runtime.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index b24875b..22852b3 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -469,6 +469,7 @@ pm_runtime_autosuspend() pm_runtime_resume() pm_runtime_get_sync() pm_runtime_put_sync_suspend() +pm_runtime_put_sync_autosuspend() 5. Run-time PM Initialization, Device Probing and Removal diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 0d4587b..fdc4567 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -732,6 +732,8 @@ int __pm_runtime_idle(struct device *dev, int rpmflags) unsigned long flags; int retval; + might_sleep_if(!(rpmflags & RPM_ASYNC)); + if (rpmflags & RPM_GET_PUT) { if (!atomic_dec_and_test(&dev->power.usage_count)) return 0; @@ -754,13 +756,16 @@ EXPORT_SYMBOL_GPL(__pm_runtime_idle); * return immediately if it is larger than zero. Then carry out a suspend, * either synchronous or asynchronous. * - * This routine may be called in atomic context if the RPM_ASYNC flag is set. + * This routine may be called in atomic context if the RPM_ASYNC flag is set, + * or if pm_runtime_irq_safe() has been called. */ int __pm_runtime_suspend(struct device *dev, int rpmflags) { unsigned long flags; int retval; + might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe); + if (rpmflags & RPM_GET_PUT) { if (!atomic_dec_and_test(&dev->power.usage_count)) return 0; @@ -782,13 +787,16 @@ EXPORT_SYMBOL_GPL(__pm_runtime_suspend); * If the RPM_GET_PUT flag is set, increment the device's usage count. Then * carry out a resume, either synchronous or asynchronous. * - * This routine may be called in atomic context if the RPM_ASYNC flag is set. + * This routine may be called in atomic context if the RPM_ASYNC flag is set, + * or if pm_runtime_irq_safe() has been called. */ int __pm_runtime_resume(struct device *dev, int rpmflags) { unsigned long flags; int retval; + might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe); + if (rpmflags & RPM_GET_PUT) atomic_inc(&dev->power.usage_count); @@ -978,6 +986,8 @@ EXPORT_SYMBOL_GPL(pm_runtime_barrier); */ void __pm_runtime_disable(struct device *dev, bool check_resume) { + might_sleep(); + spin_lock_irq(&dev->power.lock); if (dev->power.disable_depth > 0) { @@ -1184,6 +1194,8 @@ void __pm_runtime_use_autosuspend(struct device *dev, bool use) { int old_delay, old_use; + might_sleep(); + spin_lock_irq(&dev->power.lock); old_delay = dev->power.autosuspend_delay; old_use = dev->power.use_autosuspend;