From patchwork Sat Jun 28 00:04:24 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Derek Basehore X-Patchwork-Id: 4438831 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 03112BEEAA for ; Sat, 28 Jun 2014 00:05:23 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8E9A020397 for ; Sat, 28 Jun 2014 00:05:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 567062038D for ; Sat, 28 Jun 2014 00:05:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753454AbaF1AEn (ORCPT ); Fri, 27 Jun 2014 20:04:43 -0400 Received: from mail-pa0-f73.google.com ([209.85.220.73]:55107 "EHLO mail-pa0-f73.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751990AbaF1AEn (ORCPT ); Fri, 27 Jun 2014 20:04:43 -0400 Received: by mail-pa0-f73.google.com with SMTP id kq14so821569pab.2 for ; Fri, 27 Jun 2014 17:04:42 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=osJg8HrMxnbqzPoIN/gtXl1xmkQDCUniEddZdOmC2vc=; b=L1hALe0zY5CMsGqzRXNnnW9+MxfAfTh+mgc+VAuLsG3p+vbbRc1zOpDJcxyg4nFfJ+ 9FoEksWKMkJ6hMML5FefLT6nMmHmwx3EVWeyZuxLh7YPL0w4XKyDCcfOmxr7jAGc0mxG H1BKxl2FYKNDPuOPf1GQ6YKlm6dSMTDdoGvdYSFHQxmqfQSmoaHpBlUF7ksu1ratR6fQ 1chwWuXFC7ZK7G+EnX4hen5J4osz2vdcL05HWsUbbEm13XkT0ozR715Mah3pqErJSB/k 98ndOl5ngGBL8g7ezwEWnv7Zc1aM3RRpdS9LNh+JdDZGmPhxm+RVpertVOa93JNyKagT dSXw== X-Gm-Message-State: ALoCoQl91PQAcZwpTVC4dK6J3A8HEMTKHd+TJZK7dMvTdWHE8sAADZCaRbIkQEcCBvST9AJBiquB X-Received: by 10.66.137.2 with SMTP id qe2mr13909177pab.43.1403913882474; Fri, 27 Jun 2014 17:04:42 -0700 (PDT) Received: from corp2gmr1-2.hot.corp.google.com (corp2gmr1-2.hot.corp.google.com [172.24.189.93]) by gmr-mx.google.com with ESMTPS id y50si304520yhk.4.2014.06.27.17.04.42 for (version=TLSv1.1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 27 Jun 2014 17:04:42 -0700 (PDT) Received: from ketosis.mtv.corp.google.com (ketosis.mtv.corp.google.com [172.22.73.143]) by corp2gmr1-2.hot.corp.google.com (Postfix) with ESMTP id 3D7A05A44FE; Fri, 27 Jun 2014 17:04:42 -0700 (PDT) Received: by ketosis.mtv.corp.google.com (Postfix, from userid 171518) id CB00280550; Fri, 27 Jun 2014 17:04:41 -0700 (PDT) From: Derek Basehore To: linux-kernel@vger.kernel.org Cc: linux-pm@vger.kernel.org, Laxman Dewangan , Ian Campbell , xen-devel@lists.xenproject.org, Derek Basehore Subject: [PATCH v1 1/2] genirq: Fix error path for resuming irqs Date: Fri, 27 Jun 2014 17:04:24 -0700 Message-Id: <1403913865-31614-1-git-send-email-dbasehore@chromium.org> X-Mailer: git-send-email 2.0.0.526.g5318336 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_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 using ClamSMTP In the case of a late abort to suspend/hibernate, irqs marked with IRQF_EARLY_RESUME will not be enabled. This is due to syscore_resume not getting called on these paths. This can happen with a pm test for platform, a late wakeup irq, and other instances. This change removes the function from syscore and calls it explicitly in suspend, hibernate, etc. This regression was introduced in 9bab0b7f "genirq: Add IRQF_RESUME_EARLY" Signed-off-by: Derek Basehore Tested-by: Konrad Rzeszutek Wilk --- drivers/base/power/main.c | 5 ++++- drivers/xen/manage.c | 5 ++++- include/linux/interrupt.h | 1 + include/linux/pm.h | 2 +- kernel/irq/pm.c | 17 +++-------------- kernel/kexec.c | 2 +- kernel/power/hibernate.c | 6 +++--- kernel/power/suspend.c | 2 +- 8 files changed, 18 insertions(+), 22 deletions(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index bf41296..a087473 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -712,8 +712,10 @@ static void dpm_resume_early(pm_message_t state) * dpm_resume_start - Execute "noirq" and "early" device callbacks. * @state: PM transition of the system being carried out. */ -void dpm_resume_start(pm_message_t state) +void dpm_resume_start(pm_message_t state, bool enable_early_irqs) { + if (enable_early_irqs) + early_resume_device_irqs(); dpm_resume_noirq(state); dpm_resume_early(state); } @@ -1132,6 +1134,7 @@ static int dpm_suspend_noirq(pm_message_t state) if (error) { suspend_stats.failed_suspend_noirq++; dpm_save_failed_step(SUSPEND_SUSPEND_NOIRQ); + early_resume_device_irqs(); dpm_resume_noirq(resume_event(state)); } else { dpm_show_time(starttime, state, "noirq"); diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index c3667b2..d387cdf 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -68,6 +68,7 @@ static int xen_suspend(void *data) err = syscore_suspend(); if (err) { pr_err("%s: system core suspend failed: %d\n", __func__, err); + early_resume_device_irqs(); return err; } @@ -92,6 +93,8 @@ static int xen_suspend(void *data) xen_timer_resume(); } + early_resume_device_irqs(); + syscore_resume(); return 0; @@ -137,7 +140,7 @@ static void do_suspend(void) raw_notifier_call_chain(&xen_resume_notifier, 0, NULL); - dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE); + dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE, false); if (err) { pr_err("failed to start xen_suspend: %d\n", err); diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 698ad05..7f390e3 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -193,6 +193,7 @@ extern void irq_wake_thread(unsigned int irq, void *dev_id); /* The following three functions are for the core kernel use only. */ extern void suspend_device_irqs(void); extern void resume_device_irqs(void); +extern void early_resume_device_irqs(void); #ifdef CONFIG_PM_SLEEP extern int check_wakeup_irqs(void); #else diff --git a/include/linux/pm.h b/include/linux/pm.h index 72c0fe0..ae5b26a 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -677,7 +677,7 @@ struct dev_pm_domain { #ifdef CONFIG_PM_SLEEP extern void device_pm_lock(void); -extern void dpm_resume_start(pm_message_t state); +extern void dpm_resume_start(pm_message_t state, bool enable_early_irqs); extern void dpm_resume_end(pm_message_t state); extern void dpm_resume(pm_message_t state); extern void dpm_complete(pm_message_t state); diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c index abcd6ca..b07dc9c 100644 --- a/kernel/irq/pm.c +++ b/kernel/irq/pm.c @@ -60,26 +60,15 @@ static void resume_irqs(bool want_early) } /** - * irq_pm_syscore_ops - enable interrupt lines early + * early_resume_device_irqs - enable interrupt lines early * * Enable all interrupt lines with %IRQF_EARLY_RESUME set. */ -static void irq_pm_syscore_resume(void) +void early_resume_device_irqs(void) { resume_irqs(true); } - -static struct syscore_ops irq_pm_syscore_ops = { - .resume = irq_pm_syscore_resume, -}; - -static int __init irq_pm_init_ops(void) -{ - register_syscore_ops(&irq_pm_syscore_ops); - return 0; -} - -device_initcall(irq_pm_init_ops); +EXPORT_SYMBOL_GPL(early_resume_device_irqs); /** * resume_device_irqs - enable interrupt lines disabled by suspend_device_irqs() diff --git a/kernel/kexec.c b/kernel/kexec.c index 369f41a..272853b 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -1700,7 +1700,7 @@ int kernel_kexec(void) local_irq_enable(); Enable_cpus: enable_nonboot_cpus(); - dpm_resume_start(PMSG_RESTORE); + dpm_resume_start(PMSG_RESTORE, true); Resume_devices: dpm_resume_end(PMSG_RESTORE); Resume_console: diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index fcc2611..1d6dd56 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -325,7 +325,7 @@ static int create_image(int platform_mode) platform_finish(platform_mode); dpm_resume_start(in_suspend ? - (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); + (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE, true); return error; } @@ -482,7 +482,7 @@ static int resume_target_kernel(bool platform_mode) Cleanup: platform_restore_cleanup(platform_mode); - dpm_resume_start(PMSG_RECOVER); + dpm_resume_start(PMSG_RECOVER, true); return error; } @@ -574,7 +574,7 @@ int hibernation_platform_enter(void) Platform_finish: hibernation_ops->finish(); - dpm_resume_start(PMSG_RESTORE); + dpm_resume_start(PMSG_RESTORE, true); Resume_devices: entering_platform_hibernation = false; diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 4dd8822..3597c72 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -281,7 +281,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) if (need_suspend_ops(state) && suspend_ops->wake) suspend_ops->wake(); - dpm_resume_start(PMSG_RESUME); + dpm_resume_start(PMSG_RESUME, true); Platform_finish: if (need_suspend_ops(state) && suspend_ops->finish)