From patchwork Mon Jun 2 10:29:12 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Bj=C3=B8rn_Mork?= X-Patchwork-Id: 4281111 Return-Path: X-Original-To: patchwork-linux-pm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 8B97BBEEA7 for ; Mon, 2 Jun 2014 10:29:25 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 710C220351 for ; Mon, 2 Jun 2014 10:29:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 54F2A20263 for ; Mon, 2 Jun 2014 10:29:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753854AbaFBK3V (ORCPT ); Mon, 2 Jun 2014 06:29:21 -0400 Received: from canardo.mork.no ([148.122.252.1]:47758 "EHLO canardo.mork.no" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753610AbaFBK3V (ORCPT ); Mon, 2 Jun 2014 06:29:21 -0400 Received: from canardo.mork.no (ip6-localhost [IPv6:::1]) by canardo.mork.no (8.14.4/8.14.4) with ESMTP id s52ATH8O032080 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 2 Jun 2014 12:29:17 +0200 Received: (from bjorn@localhost) by canardo.mork.no (8.14.4/8.14.4/Submit) id s52ATGOY032079; Mon, 2 Jun 2014 12:29:16 +0200 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= To: linux-pm@vger.kernel.org Cc: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Subject: [RFC] PM / Runtime: Make autosuspend_delay == 0 work as intended Date: Mon, 2 Jun 2014 12:29:12 +0200 Message-Id: <1401704952-32046-1-git-send-email-bjorn@mork.no> X-Mailer: git-send-email 1.7.10.4 MIME-Version: 1.0 X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: clamav-milter 0.98.1 at canardo X-Virus-Status: Clean Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP OK, I don't like the result I came up with here. So I am sending this as an RFC in the hope that smarter people than me can come up with something nicer. I hope the patch illustrates my problem: While trying do debug some runtime suspend issues in a driver, I temporarily set autosuspend to 0 to deliberately make it aggressive enough for my driver to fail. I was surprised to learn than this effectively *disabled* autosuspend if the driver ever return -EBUSY from the runtime suspend callback. I believe that is too unexpected to be acceptable. Either we should not allow 0, or we should make it work at least as well as 1. Bjørn 8<-------------- We should always reschedule if the driver runtime suspend callback returns -EBUSY and the driver updated the last_busy time. But if autosuspend_delay is 0, then this cannot be detected because pm_runtime_autosuspend_expiration() always returns 0. Fix by rescheduling if autosuspend_delay is 0. Signed-off-by: Bjørn Mork --- drivers/base/power/runtime.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 67c7938e430b..c52e630a2e54 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -421,6 +421,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) { int (*callback)(struct device *); struct device *parent = NULL; + unsigned long retry_delay = 0; int retval; trace_rpm_suspend(dev, rpmflags); @@ -441,7 +442,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) /* If the autosuspend_delay time hasn't expired yet, reschedule. */ if ((rpmflags & RPM_AUTO) && dev->power.runtime_status != RPM_SUSPENDING) { - unsigned long expires = pm_runtime_autosuspend_expiration(dev); + unsigned long expires = pm_runtime_autosuspend_expiration(dev) + retry_delay; if (expires != 0) { /* Pending requests need to be canceled. */ @@ -571,8 +572,11 @@ static int rpm_suspend(struct device *dev, int rpmflags) * reschedule another autosuspend. */ if ((rpmflags & RPM_AUTO) && - pm_runtime_autosuspend_expiration(dev) != 0) + (pm_runtime_autosuspend_expiration(dev) != 0 || + ACCESS_ONCE(dev->power.autosuspend_delay) == 0)) { + retry_delay++; goto repeat; + } } else { pm_runtime_cancel_pending(dev); }