From patchwork Tue Aug 30 22:20:25 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rafael Wysocki X-Patchwork-Id: 1114542 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter2.kernel.org (8.14.4/8.14.4) with ESMTP id p7UMM5su014392 for ; Tue, 30 Aug 2011 22:22:05 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752791Ab1H3WVS (ORCPT ); Tue, 30 Aug 2011 18:21:18 -0400 Received: from ogre.sisk.pl ([217.79.144.158]:49763 "EHLO ogre.sisk.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752662Ab1H3WVN (ORCPT ); Tue, 30 Aug 2011 18:21:13 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by ogre.sisk.pl (Postfix) with ESMTP id F00221BAC7C; Tue, 30 Aug 2011 23:38:04 +0200 (CEST) Received: from ogre.sisk.pl ([127.0.0.1]) by localhost (ogre.sisk.pl [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 12789-04; Tue, 30 Aug 2011 23:37:43 +0200 (CEST) Received: from ferrari.rjw.lan (220-bem-13.acn.waw.pl [82.210.184.220]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ogre.sisk.pl (Postfix) with ESMTP id 7FF061BACCD; Tue, 30 Aug 2011 23:37:43 +0200 (CEST) From: "Rafael J. Wysocki" To: Linux PM mailing list Subject: [PATCH 2/5] PM / Runtime: Do not run callbacks under lock for power.irq_safe set Date: Wed, 31 Aug 2011 00:20:25 +0200 User-Agent: KMail/1.13.6 (Linux/3.1.0-rc4+; KDE/4.6.0; x86_64; ; ) Cc: LKML , "Linux-sh list" , Magnus Damm , Kevin Hilman , jean.pihet@newoldbits.com References: <201108310017.03103.rjw@sisk.pl> In-Reply-To: <201108310017.03103.rjw@sisk.pl> MIME-Version: 1.0 Message-Id: <201108310020.26104.rjw@sisk.pl> X-Virus-Scanned: amavisd-new at ogre.sisk.pl using MkS_Vir for Linux Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter2.kernel.org [140.211.167.43]); Tue, 30 Aug 2011 22:22:06 +0000 (UTC) From: Rafael J. Wysocki The rpm_suspend() and rpm_resume() routines execute subsystem or PM domain callbacks under power.lock if power.irq_safe is set for the given device. This is inconsistent with that rpm_idle() does after commit 02b2677 (PM / Runtime: Allow _put_sync() from interrupts-disabled context) and is problematic for subsystems and PM domains wanting to use power.lock for synchronization in their runtime PM callbacks. For this reason, make runtime PM core functions always release power.lock before invoking subsystem or PM domain callbacks. Signed-off-by: Rafael J. Wysocki --- drivers/base/power/runtime.c | 50 ++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 22 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-sh" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Index: linux/drivers/base/power/runtime.c =================================================================== --- linux.orig/drivers/base/power/runtime.c +++ linux/drivers/base/power/runtime.c @@ -155,6 +155,31 @@ static int rpm_check_suspend_allowed(str } /** + * __rpm_callback - Run a given runtime PM callback for a given device. + * @cb: Runtime PM callback to run. + * @dev: Device to run the callback for. + */ +static int __rpm_callback(int (*cb)(struct device *), struct device *dev) + __releases(&dev->power.lock) __acquires(&dev->power.lock) +{ + int retval; + + if (dev->power.irq_safe) + spin_unlock(&dev->power.lock); + else + spin_unlock_irq(&dev->power.lock); + + retval = cb(dev); + + if (dev->power.irq_safe) + spin_lock(&dev->power.lock); + else + spin_lock_irq(&dev->power.lock); + + return retval; +} + +/** * rpm_idle - Notify device bus type if the device can be suspended. * @dev: Device to notify the bus type about. * @rpmflags: Flag bits. @@ -225,19 +250,8 @@ static int rpm_idle(struct device *dev, else callback = NULL; - if (callback) { - if (dev->power.irq_safe) - spin_unlock(&dev->power.lock); - else - spin_unlock_irq(&dev->power.lock); - - callback(dev); - - if (dev->power.irq_safe) - spin_lock(&dev->power.lock); - else - spin_lock_irq(&dev->power.lock); - } + if (callback) + __rpm_callback(callback, dev); dev->power.idle_notification = false; wake_up_all(&dev->power.wait_queue); @@ -252,22 +266,14 @@ static int rpm_idle(struct device *dev, * @dev: Device to run the callback for. */ static int rpm_callback(int (*cb)(struct device *), struct device *dev) - __releases(&dev->power.lock) __acquires(&dev->power.lock) { int retval; if (!cb) return -ENOSYS; - if (dev->power.irq_safe) { - retval = cb(dev); - } else { - spin_unlock_irq(&dev->power.lock); - - retval = cb(dev); + retval = __rpm_callback(cb, dev); - spin_lock_irq(&dev->power.lock); - } dev->power.runtime_error = retval; return retval != -EACCES ? retval : -EIO; }