From: boris.brezillon@free-electrons.com (Boris Brezillon)
To: linux-arm-kernel@lists.infradead.org
Subject: [RFC PATCH 0/3] genirq: mixing IRQF_NO_SUSPEND and wakeup sources on shared IRQs
Date: Thu, 26 Feb 2015 09:03:47 +0100 [thread overview]
Message-ID: <20150226090347.777c47ec@bbrezillon> (raw)
In-Reply-To: <2154999.DTKV1bGBcx@vostro.rjw.lan>
Hi Rafael,
On Wed, 25 Feb 2015 22:59:36 +0100
"Rafael J. Wysocki" <rjw@rjwysocki.net> wrote:
> On Tuesday, February 24, 2015 10:55:59 AM Boris Brezillon wrote:
> > Hello,
> >
> > I put the IRQF_NO_SUSPEND_SAFE/IRQF_TIMER_SIBLING_OK/WHATEVER_NAME_YOU_CHOOSE
> > debate aside to concentrate on another problem pointed out by Rafael and
> > Mark: the fact that we cannot mix IRQF_NO_SUSPEND and wakeup sources on
> > a shared IRQ line.
> >
> > This is because the wakeup code is prevailing the IRQF_NO_SUSPEND case
> > and will trigger a system wakeup as soon as the IRQ line is tagged as a
> > wakeup source.
> >
> > This series propose an approach to deal with such cases by doing the
> > following:
> > 1/ Prevent any system wakeup when at least one of the IRQ user has set
> > the IRQF_NO_SUSPEND flag
> > 2/ Adapt IRQ handlers so that they can safely be called in suspended
> > state
> > 3/ Let drivers decide when the system should be woken up
> >
> > Let me know what you think of this approach.
>
> So I have the appended patch that should deal with all that too (it doesn't
> rework drivers that need to share NO_SUSPEND IRQs and do wakeup, but that
> can be done on top of it in a straightforward way).
>
> The idea is quite simple. By default, the core replaces the interrupt handlers
> of everyone sharing NO_SUSPEND lines and not using IRQF_NO_SUSPEND with a null
> handler always returning IRQ_NONE at the suspend_device_irqs() time (the
> rationale being that if you don't use IRQF_NO_SUSPEND, then your device has
> no reason to generate interrupts after that point). The original handlers are
> then restored by resume_device_irqs().
>
> However, if the IRQ is configured for wakeup, there may be a reason to generate
> interrupts from a device not using IRQF_NO_SUSPEND. For that, the patch adds
> IRQF_COND_SUSPEND that, if set, will prevent the default behavior described
> above from being applied to irqactions using it if the IRQs in question are
> configured for wakeup. Of course, the users of IRQF_COND_SUSPEND are supposed
> to implement wakeup detection in their interrupt handlers and then call
> pm_system_wakeup() if necessary.
That patch sounds good to me.
Could you send it on its own to the appropriate MLs ?
Thomas, Peter, Mark, could you share you opinion ?
I know I'm a bit insistent on this fix, but I'd really like to get away
from this warning backtrace (and the associated problems behind it) as
soon as possible.
>
> So your patch [3/3] could be redone on top of this AFAICS.
Absolutely.
Thanks.
Boris
>
> Rafael
>
>
> ---
> include/linux/interrupt.h | 10 +++++++++
> kernel/irq/pm.c | 49 ++++++++++++++++++++++++++++++++++++++++++----
> 2 files changed, 55 insertions(+), 4 deletions(-)
>
> Index: linux-pm/include/linux/interrupt.h
> ===================================================================
> --- linux-pm.orig/include/linux/interrupt.h
> +++ linux-pm/include/linux/interrupt.h
> @@ -57,6 +57,11 @@
> * IRQF_NO_THREAD - Interrupt cannot be threaded
> * IRQF_EARLY_RESUME - Resume IRQ early during syscore instead of at device
> * resume time.
> + * IRQF_COND_SUSPEND - If the IRQ is shared with a NO_SUSPEND user and it is
> + * configured for system wakeup, execute this interrup handler
> + * after suspending interrupts as it may be necessary to detect
> + * wakeup. Users need to implement system wakeup detection in
> + * their interrupt handlers.
> */
> #define IRQF_DISABLED 0x00000020
> #define IRQF_SHARED 0x00000080
> @@ -70,6 +75,7 @@
> #define IRQF_FORCE_RESUME 0x00008000
> #define IRQF_NO_THREAD 0x00010000
> #define IRQF_EARLY_RESUME 0x00020000
> +#define IRQF_COND_SUSPEND 0x00040000
>
> #define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND | IRQF_NO_THREAD)
>
> @@ -101,6 +107,7 @@ typedef irqreturn_t (*irq_handler_t)(int
> * @thread_flags: flags related to @thread
> * @thread_mask: bitmask for keeping track of @thread activity
> * @dir: pointer to the proc/irq/NN/name entry
> + * @saved_handler: address of the original interrupt handler function
> */
> struct irqaction {
> irq_handler_t handler;
> @@ -115,6 +122,9 @@ struct irqaction {
> unsigned long thread_mask;
> const char *name;
> struct proc_dir_entry *dir;
> +#ifdef CONFIG_PM_SLEEP
> + irq_handler_t saved_handler;
> +#endif
> } ____cacheline_internodealigned_in_smp;
>
> extern irqreturn_t no_action(int cpl, void *dev_id);
> Index: linux-pm/kernel/irq/pm.c
> ===================================================================
> --- linux-pm.orig/kernel/irq/pm.c
> +++ linux-pm/kernel/irq/pm.c
> @@ -43,9 +43,6 @@ void irq_pm_install_action(struct irq_de
>
> if (action->flags & IRQF_NO_SUSPEND)
> desc->no_suspend_depth++;
> -
> - WARN_ON_ONCE(desc->no_suspend_depth &&
> - desc->no_suspend_depth != desc->nr_actions);
> }
>
> /*
> @@ -63,11 +60,53 @@ void irq_pm_remove_action(struct irq_des
> desc->no_suspend_depth--;
> }
>
> +static irqreturn_t irq_pm_null_handler(int irq, void *context)
> +{
> + return IRQ_NONE;
> +}
> +
> +static void prepare_no_suspend_irq(struct irq_desc *desc)
> +{
> + struct irqaction *action;
> +
> + for (action = desc->action; action; action = action->next) {
> + if (action->flags & IRQF_NO_SUSPEND)
> + continue;
> +
> + if ((action->flags & IRQF_COND_SUSPEND) &&
> + irqd_is_wakeup_set(&desc->irq_data))
> + continue;
> +
> + action->saved_handler = action->handler;
> + action->handler = irq_pm_null_handler;
> + }
> +}
> +
> +static void restore_no_suspend_irq(struct irq_desc *desc)
> +{
> + struct irqaction *action;
> +
> + for (action = desc->action; action; action = action->next) {
> + if (action->flags & IRQF_NO_SUSPEND)
> + continue;
> +
> + if (action->saved_handler) {
> + action->handler = action->saved_handler;
> + action->saved_handler = NULL;
> + }
> + }
> +}
> +
> static bool suspend_device_irq(struct irq_desc *desc, int irq)
> {
> - if (!desc->action || desc->no_suspend_depth)
> + if (!desc->action)
> return false;
>
> + if (desc->no_suspend_depth) {
> + prepare_no_suspend_irq(desc);
> + return false;
> + }
> +
> if (irqd_is_wakeup_set(&desc->irq_data)) {
> irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED);
> /*
> @@ -135,6 +174,8 @@ static void resume_irq(struct irq_desc *
> if (desc->istate & IRQS_SUSPENDED)
> goto resume;
>
> + restore_no_suspend_irq(desc);
> +
> /* Force resume the interrupt? */
> if (!desc->force_resume_depth)
> return;
>
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
WARNING: multiple messages have this Message-ID (diff)
From: Boris Brezillon <boris.brezillon@free-electrons.com>
To: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Thomas Gleixner <tglx@linutronix.de>,
Jason Cooper <jason@lakedaemon.net>,
Peter Zijlstra <peterz@infradead.org>,
Mark Rutland <mark.rutland@arm.com>,
linux-kernel@vger.kernel.org,
Nicolas Ferre <nicolas.ferre@atmel.com>,
Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>,
Alexandre Belloni <alexandre.belloni@free-electrons.com>,
linux-arm-kernel@lists.infradead.org
Subject: Re: [RFC PATCH 0/3] genirq: mixing IRQF_NO_SUSPEND and wakeup sources on shared IRQs
Date: Thu, 26 Feb 2015 09:03:47 +0100 [thread overview]
Message-ID: <20150226090347.777c47ec@bbrezillon> (raw)
In-Reply-To: <2154999.DTKV1bGBcx@vostro.rjw.lan>
Hi Rafael,
On Wed, 25 Feb 2015 22:59:36 +0100
"Rafael J. Wysocki" <rjw@rjwysocki.net> wrote:
> On Tuesday, February 24, 2015 10:55:59 AM Boris Brezillon wrote:
> > Hello,
> >
> > I put the IRQF_NO_SUSPEND_SAFE/IRQF_TIMER_SIBLING_OK/WHATEVER_NAME_YOU_CHOOSE
> > debate aside to concentrate on another problem pointed out by Rafael and
> > Mark: the fact that we cannot mix IRQF_NO_SUSPEND and wakeup sources on
> > a shared IRQ line.
> >
> > This is because the wakeup code is prevailing the IRQF_NO_SUSPEND case
> > and will trigger a system wakeup as soon as the IRQ line is tagged as a
> > wakeup source.
> >
> > This series propose an approach to deal with such cases by doing the
> > following:
> > 1/ Prevent any system wakeup when at least one of the IRQ user has set
> > the IRQF_NO_SUSPEND flag
> > 2/ Adapt IRQ handlers so that they can safely be called in suspended
> > state
> > 3/ Let drivers decide when the system should be woken up
> >
> > Let me know what you think of this approach.
>
> So I have the appended patch that should deal with all that too (it doesn't
> rework drivers that need to share NO_SUSPEND IRQs and do wakeup, but that
> can be done on top of it in a straightforward way).
>
> The idea is quite simple. By default, the core replaces the interrupt handlers
> of everyone sharing NO_SUSPEND lines and not using IRQF_NO_SUSPEND with a null
> handler always returning IRQ_NONE at the suspend_device_irqs() time (the
> rationale being that if you don't use IRQF_NO_SUSPEND, then your device has
> no reason to generate interrupts after that point). The original handlers are
> then restored by resume_device_irqs().
>
> However, if the IRQ is configured for wakeup, there may be a reason to generate
> interrupts from a device not using IRQF_NO_SUSPEND. For that, the patch adds
> IRQF_COND_SUSPEND that, if set, will prevent the default behavior described
> above from being applied to irqactions using it if the IRQs in question are
> configured for wakeup. Of course, the users of IRQF_COND_SUSPEND are supposed
> to implement wakeup detection in their interrupt handlers and then call
> pm_system_wakeup() if necessary.
That patch sounds good to me.
Could you send it on its own to the appropriate MLs ?
Thomas, Peter, Mark, could you share you opinion ?
I know I'm a bit insistent on this fix, but I'd really like to get away
from this warning backtrace (and the associated problems behind it) as
soon as possible.
>
> So your patch [3/3] could be redone on top of this AFAICS.
Absolutely.
Thanks.
Boris
>
> Rafael
>
>
> ---
> include/linux/interrupt.h | 10 +++++++++
> kernel/irq/pm.c | 49 ++++++++++++++++++++++++++++++++++++++++++----
> 2 files changed, 55 insertions(+), 4 deletions(-)
>
> Index: linux-pm/include/linux/interrupt.h
> ===================================================================
> --- linux-pm.orig/include/linux/interrupt.h
> +++ linux-pm/include/linux/interrupt.h
> @@ -57,6 +57,11 @@
> * IRQF_NO_THREAD - Interrupt cannot be threaded
> * IRQF_EARLY_RESUME - Resume IRQ early during syscore instead of at device
> * resume time.
> + * IRQF_COND_SUSPEND - If the IRQ is shared with a NO_SUSPEND user and it is
> + * configured for system wakeup, execute this interrup handler
> + * after suspending interrupts as it may be necessary to detect
> + * wakeup. Users need to implement system wakeup detection in
> + * their interrupt handlers.
> */
> #define IRQF_DISABLED 0x00000020
> #define IRQF_SHARED 0x00000080
> @@ -70,6 +75,7 @@
> #define IRQF_FORCE_RESUME 0x00008000
> #define IRQF_NO_THREAD 0x00010000
> #define IRQF_EARLY_RESUME 0x00020000
> +#define IRQF_COND_SUSPEND 0x00040000
>
> #define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND | IRQF_NO_THREAD)
>
> @@ -101,6 +107,7 @@ typedef irqreturn_t (*irq_handler_t)(int
> * @thread_flags: flags related to @thread
> * @thread_mask: bitmask for keeping track of @thread activity
> * @dir: pointer to the proc/irq/NN/name entry
> + * @saved_handler: address of the original interrupt handler function
> */
> struct irqaction {
> irq_handler_t handler;
> @@ -115,6 +122,9 @@ struct irqaction {
> unsigned long thread_mask;
> const char *name;
> struct proc_dir_entry *dir;
> +#ifdef CONFIG_PM_SLEEP
> + irq_handler_t saved_handler;
> +#endif
> } ____cacheline_internodealigned_in_smp;
>
> extern irqreturn_t no_action(int cpl, void *dev_id);
> Index: linux-pm/kernel/irq/pm.c
> ===================================================================
> --- linux-pm.orig/kernel/irq/pm.c
> +++ linux-pm/kernel/irq/pm.c
> @@ -43,9 +43,6 @@ void irq_pm_install_action(struct irq_de
>
> if (action->flags & IRQF_NO_SUSPEND)
> desc->no_suspend_depth++;
> -
> - WARN_ON_ONCE(desc->no_suspend_depth &&
> - desc->no_suspend_depth != desc->nr_actions);
> }
>
> /*
> @@ -63,11 +60,53 @@ void irq_pm_remove_action(struct irq_des
> desc->no_suspend_depth--;
> }
>
> +static irqreturn_t irq_pm_null_handler(int irq, void *context)
> +{
> + return IRQ_NONE;
> +}
> +
> +static void prepare_no_suspend_irq(struct irq_desc *desc)
> +{
> + struct irqaction *action;
> +
> + for (action = desc->action; action; action = action->next) {
> + if (action->flags & IRQF_NO_SUSPEND)
> + continue;
> +
> + if ((action->flags & IRQF_COND_SUSPEND) &&
> + irqd_is_wakeup_set(&desc->irq_data))
> + continue;
> +
> + action->saved_handler = action->handler;
> + action->handler = irq_pm_null_handler;
> + }
> +}
> +
> +static void restore_no_suspend_irq(struct irq_desc *desc)
> +{
> + struct irqaction *action;
> +
> + for (action = desc->action; action; action = action->next) {
> + if (action->flags & IRQF_NO_SUSPEND)
> + continue;
> +
> + if (action->saved_handler) {
> + action->handler = action->saved_handler;
> + action->saved_handler = NULL;
> + }
> + }
> +}
> +
> static bool suspend_device_irq(struct irq_desc *desc, int irq)
> {
> - if (!desc->action || desc->no_suspend_depth)
> + if (!desc->action)
> return false;
>
> + if (desc->no_suspend_depth) {
> + prepare_no_suspend_irq(desc);
> + return false;
> + }
> +
> if (irqd_is_wakeup_set(&desc->irq_data)) {
> irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED);
> /*
> @@ -135,6 +174,8 @@ static void resume_irq(struct irq_desc *
> if (desc->istate & IRQS_SUSPENDED)
> goto resume;
>
> + restore_no_suspend_irq(desc);
> +
> /* Force resume the interrupt? */
> if (!desc->force_resume_depth)
> return;
>
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
next prev parent reply other threads:[~2015-02-26 8:03 UTC|newest]
Thread overview: 62+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-24 9:55 [RFC PATCH 0/3] genirq: mixing IRQF_NO_SUSPEND and wakeup sources on shared IRQs Boris Brezillon
2015-02-24 9:55 ` Boris Brezillon
2015-02-24 9:56 ` [RFC PATCH 1/3] genirq: prevent system wakeup when dealing with IRQF_NO_SUSPEND IRQs Boris Brezillon
2015-02-24 9:56 ` Boris Brezillon
2015-02-25 22:01 ` Rafael J. Wysocki
2015-02-25 22:01 ` Rafael J. Wysocki
2015-02-26 8:06 ` Boris Brezillon
2015-02-26 8:06 ` Boris Brezillon
2015-02-24 9:56 ` [RFC PATCH 2/3] genirq: add helper functions to deal with wakeup on shared " Boris Brezillon
2015-02-24 9:56 ` Boris Brezillon
2015-02-25 22:03 ` Rafael J. Wysocki
2015-02-25 22:03 ` Rafael J. Wysocki
2015-02-26 8:09 ` Boris Brezillon
2015-02-26 8:09 ` Boris Brezillon
2015-02-24 9:56 ` [RFC PATCH 3/3] rtc: at91sam9: properly act when IRQ handler is called in suspended state Boris Brezillon
2015-02-24 9:56 ` Boris Brezillon
2015-02-25 22:05 ` Rafael J. Wysocki
2015-02-25 22:05 ` Rafael J. Wysocki
2015-02-26 8:12 ` Boris Brezillon
2015-02-26 8:12 ` Boris Brezillon
2015-02-25 21:59 ` [RFC PATCH 0/3] genirq: mixing IRQF_NO_SUSPEND and wakeup sources on shared IRQs Rafael J. Wysocki
2015-02-25 21:59 ` Rafael J. Wysocki
2015-02-26 8:03 ` Boris Brezillon [this message]
2015-02-26 8:03 ` Boris Brezillon
2015-02-26 15:44 ` Rafael J. Wysocki
2015-02-26 15:44 ` Rafael J. Wysocki
2015-02-26 15:47 ` Boris Brezillon
2015-02-26 15:47 ` Boris Brezillon
2015-02-26 18:17 ` Rafael J. Wysocki
2015-02-26 18:17 ` Rafael J. Wysocki
2015-02-26 18:17 ` Boris Brezillon
2015-02-26 18:17 ` Boris Brezillon
2015-02-26 21:55 ` Rafael J. Wysocki
2015-02-26 21:55 ` Rafael J. Wysocki
2015-02-26 23:07 ` [PATCH] genirq / PM: Add flag for shared NO_SUSPEND interrupt lines Rafael J. Wysocki
2015-02-26 23:07 ` Rafael J. Wysocki
2015-02-27 8:38 ` Peter Zijlstra
2015-02-27 8:38 ` Peter Zijlstra
2015-02-27 22:13 ` Rafael J. Wysocki
2015-02-27 22:13 ` Rafael J. Wysocki
2015-02-27 22:11 ` Peter Zijlstra
2015-02-27 22:11 ` Peter Zijlstra
2015-03-04 19:42 ` Mark Rutland
2015-03-04 19:42 ` Mark Rutland
2015-03-04 20:00 ` [PATCH] genirq: describe IRQF_COND_SUSPEND Mark Rutland
2015-03-04 20:00 ` Mark Rutland
2015-03-04 21:55 ` Rafael J. Wysocki
2015-03-04 21:55 ` Rafael J. Wysocki
2015-03-04 22:17 ` Alexandre Belloni
2015-03-04 22:17 ` Alexandre Belloni
2015-03-04 22:27 ` Arnd Bergmann
2015-03-04 22:27 ` Arnd Bergmann
2015-03-05 11:04 ` Mark Rutland
2015-03-05 11:04 ` Mark Rutland
2015-03-05 11:33 ` Alexandre Belloni
2015-03-05 11:33 ` Alexandre Belloni
2015-03-05 12:07 ` Mark Rutland
2015-03-05 12:07 ` Mark Rutland
2015-03-06 0:54 ` Rafael J. Wysocki
2015-03-06 0:54 ` Rafael J. Wysocki
2015-03-04 21:30 ` [PATCH] genirq / PM: Add flag for shared NO_SUSPEND interrupt lines Rafael J. Wysocki
2015-03-04 21:30 ` Rafael J. Wysocki
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150226090347.777c47ec@bbrezillon \
--to=boris.brezillon@free-electrons.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.