From patchwork Fri Feb 10 22:25:01 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Lindgren X-Patchwork-Id: 9567565 X-Patchwork-Delegate: rjw@sisk.pl Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id D9866602B6 for ; Fri, 10 Feb 2017 22:25:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C96EF285E5 for ; Fri, 10 Feb 2017 22:25:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BE12C285D2; Fri, 10 Feb 2017 22:25:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 69C81285CF for ; Fri, 10 Feb 2017 22:25:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752174AbdBJWZU (ORCPT ); Fri, 10 Feb 2017 17:25:20 -0500 Received: from muru.com ([72.249.23.125]:34602 "EHLO muru.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751938AbdBJWZQ (ORCPT ); Fri, 10 Feb 2017 17:25:16 -0500 Received: from sampyla.muru.com. (localhost [127.0.0.1]) by muru.com (Postfix) with ESMTP id 9F57D83A5; Fri, 10 Feb 2017 22:26:32 +0000 (UTC) From: Tony Lindgren To: "Rafael J . Wysocki" , Alan Stern Cc: Brian Norris , Dmitry Torokhov , Greg Kroah-Hartman , Grygorii Strashko , Len Brown , Nishanth Menon , Pavel Machek , Ulf Hansson , linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, linux-omap@vger.kernel.org Subject: [PATCH 2/2] PM / wakeirq: Fix spurious wake-up events for dedicated wakeirqs Date: Fri, 10 Feb 2017 14:25:01 -0800 Message-Id: <20170210222501.7948-3-tony@atomide.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20170210222501.7948-1-tony@atomide.com> References: <20170210222501.7948-1-tony@atomide.com> 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 From: Grygorii Strashko Dedicated wakeirq is a one time event to wake-up the system from low-power state and then call pm_runtime_resume() on the device wired with the dedicated wakeirq. Sometimes dedicated wakeirqs can get deferred if they trigger after we call disable_irq_nosync() in dev_pm_disable_wake_irq(). This can happen if pm_runtime_get() is called around the same time a wakeirq fires. If an interrupt fires after disable_irq_nosync(), by default it will get tagged with IRQS_PENDING and will run later on when the interrupt is enabled again. Deferred wakeirqs usually just produce pointless wake-up events. But they can also cause suspend to fail if the deferred wakeirq fires during dpm_suspend_noirq() for example. So we really don't want to see the deferred wakeirqs triggering after the device has resumed. Let's fix the issue by setting IRQ_DISABLE_UNLAZY flag for the dedicated wakeirqs. The other option would be to implement irq_disable() in the dedicated wakeirq controller, but that's not a generic solution. For reference below is what happens with a IRQ_TYPE_EDGE_BOTH IRQ type wakeirq: - resume by dedicated IRQ (EDGE_FALLING) - suspend_enter() .... - arch_suspend_enable_irqs() |- dedicated IRQ armed and fired |- irq_pm_check_wakeup() |- disarm, disable IRQ and mark as IRQS_PENDING .... - dpm_resume_noirq() |- resume_device_irqs() |- __enable_irq() |- check_irq_resend() |- handle_threaded_wake_irq() |- dedicated IRQ processed |- device_wakeup_disarm_wake_irqs() |- disable_irq_wake() .... !-> dedicated IRQ (EDGE_RISING) -| handle_edge_irq() |- IRQ disabled: mask_ack_irq and mark as IRQS_PENDING .... - subsequent suspend .... |- dpm_suspend_noirq() |- device_wakeup_arm_wake_irqs() |- __enable_irq() |- check_irq_resend() (a) |- handle_threaded_wake_irq() |- pm_wakeup_event() --> abort suspend .... |- suspend_device_irqs() |- suspend_device_irq() |- dedicated IRQ armed .... (b) |- resend_irqs |- irq_pm_check_wakeup() |- IRQ armed -> abort suspend because of pending IRQ System suspend can be aborted at points (a)-not armed or (b)-armed. Fixes: 4990d4fe327b ("PM / Wakeirq: Add automated device wake IRQ handling") Signed-off-by: Grygorii Strashko [tony@atomide.com: added a comment, updated the description] Tested-by: Tony Lindgren Signed-off-by: Tony Lindgren --- drivers/base/power/wakeirq.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c --- a/drivers/base/power/wakeirq.c +++ b/drivers/base/power/wakeirq.c @@ -183,6 +183,9 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq) wirq->irq = irq; irq_set_status_flags(irq, IRQ_NOAUTOEN); + /* Prevent deferred spurious wakeirqs with disable_irq_nosync() */ + irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY); + /* * Consumer device may need to power up and restore state * so we use a threaded irq.