From patchwork Fri Apr 25 10:44:55 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 29052 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-oa0-f69.google.com (mail-oa0-f69.google.com [209.85.219.69]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id EBE46203AC for ; Fri, 25 Apr 2014 10:45:08 +0000 (UTC) Received: by mail-oa0-f69.google.com with SMTP id i4sf20727012oah.8 for ; Fri, 25 Apr 2014 03:45:07 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:x-original-sender:x-original-authentication-results :precedence:mailing-list:list-id:list-post:list-help:list-archive :list-unsubscribe; bh=MoBk8Q2iu64TYXs5KNg+hzIRaORXWtygQ9qoVtTGIr8=; b=lg9bdtdvoEG/4Wf3aOA2i2D2xdTM3dS6cIHvdDbk8znhhxrk0wNoalkFlb+QrSaskQ IRld0teTObLUecuNrTs0kE0xoqxze2rlSvD9um8vLUuofzIRZXSKim0XMvPQDl8levwG uAznwZBmSbxqVTBwldYNvn0niWnKHuEFSFi/BWvNJNHHyFnwf9EzS9s6kLGWHkr0YBXz dHU3QpaX0tBOXBFDoCQckuW2lBAvlP+wucxSGbcOvFU1b+WWF1ts0n2JTfJKak7GoSS5 L4sLfUoVeTX1syWPRAAbx7P/GouyhtXYBJRB+Tshg5V5GMcyLThJ6INjCmLEBLKNIaBW OTcw== X-Gm-Message-State: ALoCoQlYLrgqzT4RDzeQO91y5SaZyY+RR33FM5+qvt0ucjSvLo4GJ5lEVHs86p/A94E6PBxJ22BZ X-Received: by 10.43.94.71 with SMTP id bx7mr3629120icc.2.1398422707638; Fri, 25 Apr 2014 03:45:07 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.101.213 with SMTP id u79ls1444113qge.79.gmail; Fri, 25 Apr 2014 03:45:07 -0700 (PDT) X-Received: by 10.220.167.2 with SMTP id o2mr6219733vcy.8.1398422707544; Fri, 25 Apr 2014 03:45:07 -0700 (PDT) Received: from mail-ve0-f170.google.com (mail-ve0-f170.google.com [209.85.128.170]) by mx.google.com with ESMTPS id b5si1603996vej.137.2014.04.25.03.45.07 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 25 Apr 2014 03:45:07 -0700 (PDT) Received-SPF: none (google.com: patch+caf_=patchwork-forward=linaro.org@linaro.org does not designate permitted sender hosts) client-ip=209.85.128.170; Received: by mail-ve0-f170.google.com with SMTP id pa12so4544566veb.29 for ; Fri, 25 Apr 2014 03:45:07 -0700 (PDT) X-Received: by 10.220.147.16 with SMTP id j16mr6226535vcv.14.1398422707422; Fri, 25 Apr 2014 03:45:07 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.221.72 with SMTP id ib8csp87680vcb; Fri, 25 Apr 2014 03:45:06 -0700 (PDT) X-Received: by 10.152.10.72 with SMTP id g8mr716886lab.50.1398422706169; Fri, 25 Apr 2014 03:45:06 -0700 (PDT) Received: from mail-la0-f50.google.com (mail-la0-f50.google.com [209.85.215.50]) by mx.google.com with ESMTPS id sz4si5339787lbb.120.2014.04.25.03.45.05 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 25 Apr 2014 03:45:06 -0700 (PDT) Received-SPF: none (google.com: ulf.hansson@linaro.org does not designate permitted sender hosts) client-ip=209.85.215.50; Received: by mail-la0-f50.google.com with SMTP id pv20so2895657lab.23 for ; Fri, 25 Apr 2014 03:45:05 -0700 (PDT) X-Received: by 10.152.3.72 with SMTP id a8mr1774892laa.33.1398422705556; Fri, 25 Apr 2014 03:45:05 -0700 (PDT) Received: from linaro-ulf.lan (90-231-160-185-no158.tbcn.telia.com. [90.231.160.185]) by mx.google.com with ESMTPSA id z2sm336395lae.7.2014.04.25.03.45.03 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 25 Apr 2014 03:45:04 -0700 (PDT) From: Ulf Hansson To: "Rafael J. Wysocki" , Len Brown , Pavel Machek , linux-pm@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, Kevin Hilman , Alan Stern , Greg Kroah-Hartman , Daniel Lezcano , Tomasz Figa , Ulf Hansson Subject: [PATCH] PM / Sleep: Fall back to subsystem level PM callbacks for PM domains Date: Fri, 25 Apr 2014 12:44:55 +0200 Message-Id: <1398422695-2295-1-git-send-email-ulf.hansson@linaro.org> X-Mailer: git-send-email 1.7.9.5 X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: ulf.hansson@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: patch+caf_=patchwork-forward=linaro.org@linaro.org does not designate permitted sender hosts) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Previously once the PM core found a PM domain pointer for a device, but which didn't have a valid PM callback, it falled back to try the driver's PM callback. In this scenario, change the behavior of the PM core to try out the other subsystem level PM callbacks, before it moves on to the driver. This gives provision for PM domains to easier re-use subsystem level code to handle the needed operations. Signed-off-by: Ulf Hansson --- Documentation/power/devices.txt | 6 +++-- drivers/base/power/main.c | 55 +++++++++++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index 47d46df..c875056 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt @@ -303,8 +303,10 @@ The PM domain, type, class and bus callbacks may in turn invoke device- or driver-specific methods stored in dev->driver->pm, but they don't have to do that. -If the subsystem callback chosen for execution is not present, the PM core will -execute the corresponding method from dev->driver->pm instead if there is one. +If a PM domain exist, but the callback chosen for execution isn't present, the +PM core will fall back to try the other subsystem level callbacks. Finally, if +no subsystem level callback is found, it executes the corresponding method from +dev->driver->pm instead if there is one. Entering System Suspend diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 86d5e4f..e604db9 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -490,7 +490,11 @@ static int device_resume_noirq(struct device *dev, pm_message_t state, bool asyn if (dev->pm_domain) { info = "noirq power domain "; callback = pm_noirq_op(&dev->pm_domain->ops, state); - } else if (dev->type && dev->type->pm) { + if (callback) + goto End; + } + + if (dev->type && dev->type->pm) { info = "noirq type "; callback = pm_noirq_op(dev->type->pm, state); } else if (dev->class && dev->class->pm) { @@ -506,6 +510,7 @@ static int device_resume_noirq(struct device *dev, pm_message_t state, bool asyn callback = pm_noirq_op(dev->driver->pm, state); } + End: error = dpm_run_callback(callback, dev, state, info); dev->power.is_noirq_suspended = false; @@ -616,7 +621,11 @@ static int device_resume_early(struct device *dev, pm_message_t state, bool asyn if (dev->pm_domain) { info = "early power domain "; callback = pm_late_early_op(&dev->pm_domain->ops, state); - } else if (dev->type && dev->type->pm) { + if (callback) + goto End; + } + + if (dev->type && dev->type->pm) { info = "early type "; callback = pm_late_early_op(dev->type->pm, state); } else if (dev->class && dev->class->pm) { @@ -632,6 +641,7 @@ static int device_resume_early(struct device *dev, pm_message_t state, bool asyn callback = pm_late_early_op(dev->driver->pm, state); } + End: error = dpm_run_callback(callback, dev, state, info); dev->power.is_late_suspended = false; @@ -751,7 +761,8 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) if (dev->pm_domain) { info = "power domain "; callback = pm_op(&dev->pm_domain->ops, state); - goto Driver; + if (callback) + goto End; } if (dev->type && dev->type->pm) { @@ -889,7 +900,11 @@ static void device_complete(struct device *dev, pm_message_t state) if (dev->pm_domain) { info = "completing power domain "; callback = dev->pm_domain->ops.complete; - } else if (dev->type && dev->type->pm) { + if (callback) + goto End; + } + + if (dev->type && dev->type->pm) { info = "completing type "; callback = dev->type->pm->complete; } else if (dev->class && dev->class->pm) { @@ -905,6 +920,7 @@ static void device_complete(struct device *dev, pm_message_t state) callback = dev->driver->pm->complete; } + End: if (callback) { pm_dev_dbg(dev, state, info); callback(dev); @@ -1015,7 +1031,11 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a if (dev->pm_domain) { info = "noirq power domain "; callback = pm_noirq_op(&dev->pm_domain->ops, state); - } else if (dev->type && dev->type->pm) { + if (callback) + goto End; + } + + if (dev->type && dev->type->pm) { info = "noirq type "; callback = pm_noirq_op(dev->type->pm, state); } else if (dev->class && dev->class->pm) { @@ -1031,6 +1051,7 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a callback = pm_noirq_op(dev->driver->pm, state); } + End: error = dpm_run_callback(callback, dev, state, info); if (!error) dev->power.is_noirq_suspended = true; @@ -1154,7 +1175,11 @@ static int __device_suspend_late(struct device *dev, pm_message_t state, bool as if (dev->pm_domain) { info = "late power domain "; callback = pm_late_early_op(&dev->pm_domain->ops, state); - } else if (dev->type && dev->type->pm) { + if (callback) + goto End; + } + + if (dev->type && dev->type->pm) { info = "late type "; callback = pm_late_early_op(dev->type->pm, state); } else if (dev->class && dev->class->pm) { @@ -1170,6 +1195,7 @@ static int __device_suspend_late(struct device *dev, pm_message_t state, bool as callback = pm_late_early_op(dev->driver->pm, state); } + End: error = dpm_run_callback(callback, dev, state, info); if (!error) dev->power.is_late_suspended = true; @@ -1338,20 +1364,21 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) if (dev->pm_domain) { info = "power domain "; callback = pm_op(&dev->pm_domain->ops, state); - goto Run; + if (callback) + goto Run; } if (dev->type && dev->type->pm) { info = "type "; callback = pm_op(dev->type->pm, state); - goto Run; + goto Driver; } if (dev->class) { if (dev->class->pm) { info = "class "; callback = pm_op(dev->class->pm, state); - goto Run; + goto Driver; } else if (dev->class->suspend) { pm_dev_dbg(dev, state, "legacy class "); error = legacy_suspend(dev, state, dev->class->suspend, @@ -1372,12 +1399,13 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) } } - Run: + Driver: if (!callback && dev->driver && dev->driver->pm) { info = "driver "; callback = pm_op(dev->driver->pm, state); } + Run: error = dpm_run_callback(callback, dev, state, info); End: @@ -1507,7 +1535,11 @@ static int device_prepare(struct device *dev, pm_message_t state) if (dev->pm_domain) { info = "preparing power domain "; callback = dev->pm_domain->ops.prepare; - } else if (dev->type && dev->type->pm) { + if (callback) + goto End; + } + + if (dev->type && dev->type->pm) { info = "preparing type "; callback = dev->type->pm->prepare; } else if (dev->class && dev->class->pm) { @@ -1523,6 +1555,7 @@ static int device_prepare(struct device *dev, pm_message_t state) callback = dev->driver->pm->prepare; } + End: if (callback) { error = callback(dev); suspend_report_result(callback, error);