From: "Rafael J. Wysocki" <rjw@rjwysocki.net>
To: Peter Zijlstra <peterz@infradead.org>,
Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org,
Dmitry Torokhov <dmitry.torokhov@gmail.com>,
Linux PM list <linux-pm@vger.kernel.org>,
Dmitry Torokhov <dtor@google.com>
Subject: Re: [RFC][PATCH] irq: Rework IRQF_NO_SUSPENDED
Date: Fri, 25 Jul 2014 01:10:36 +0200 [thread overview]
Message-ID: <13290270.IfKaUSRMLR@vostro.rjw.lan> (raw)
In-Reply-To: <20140724212620.GO3935@laptop>
On Thursday, July 24, 2014 11:26:20 PM Peter Zijlstra wrote:
> Subject: irq: Rework IRQF_NO_SUSPENDED
> From: Peter Zijlstra <peterz@infradead.org>
> Date: Thu Jul 24 22:34:50 CEST 2014
>
> Typically when devices are suspended they're quiesced such that they
> will not generate any further interrupts.
>
> However some devices should still generate interrupts, even when
> suspended, typically used to wake the machine back up.
>
> Such logic should ideally be contained inside each driver, if it can
> generate interrupts when suspended, it knows about this and the
> interrupt handler can deal with it.
>
> Except of course for shared interrupts, when such a wakeup device is
> sharing an interrupt line with a device that does not expect
> interrupts while suspended things can go funny.
>
> This is where IRQF_NO_SUSPEND comes in, the idea is that drivers that
> have the capability to wake the machine set IRQF_NO_SUSPEND and their
> handler will still be called, even when the IRQ subsystem is formally
> suspended. Handlers without IRQF_NO_SUSPEND will not be called.
>
> This replaced the prior implementation of IRQF_NO_SUSPEND which had
> a number of fatal issues in that it didn't actually work for the
> shared case, exactly the case it should be helping.
>
> There is still enable_irq_wake()/IRQD_WAKEUP_STATE that tries to serve
> a similar purpose but is equially wrecked for shared interrupts,
> ideally this would be removed.
Let me comment about this particular thing.
I had a discussion with Dmitry about that and his argument was that
enable_irq_wake() should imply IRQF_NO_SUSPEND, because drivers that
set up interrupts for system wakeup should expect those interrupts to
trigger at any time, including system suspend. Hence the patch that
added the IRQD_WAKEUP_STATE check to __disable_irq().
However, in the face of the problem that is being addressed here I'm
not really sure that this argument is valid, because if the driver
calling enable_irq_wake() is sharing the IRQ with another one, the
other driver may not actually know that the IRQ will be a wakeup one
and still may not expect interrupts to come to it during system
suspend/resume.
Yes, drivers using enable_irq_wake() will likely want IRQF_NO_SUSPEND to
be set for their irqactions, but that should not imply "no suspend" for
all irqactions sharing the same desc. So I guess it may be better to go
forth and use a global "interrupts suspended" state variable instead of the
IRQS_SUSPENDED flag for each desc and throw away the IRQD_WAKEUP_STATE
check from suspend_device_irqs() entirely.
Peter, it looks like you'd prefer that?
Rafael
> Cc: rjw@rjwysocki.net
> Signed-off-by: Peter Zijlstra <peterz@infradead.org>
> ---
> kernel/irq/chip.c | 4 +---
> kernel/irq/handle.c | 24 +++++++++++++++++++++---
> kernel/irq/internals.h | 6 ++++--
> kernel/irq/manage.c | 31 ++++++-------------------------
> kernel/irq/pm.c | 17 +++++++++--------
> 5 files changed, 41 insertions(+), 41 deletions(-)
>
> --- a/kernel/irq/chip.c
> +++ b/kernel/irq/chip.c
> @@ -677,9 +677,7 @@ void handle_percpu_devid_irq(unsigned in
> if (chip->irq_ack)
> chip->irq_ack(&desc->irq_data);
>
> - trace_irq_handler_entry(irq, action);
> - res = action->handler(irq, dev_id);
> - trace_irq_handler_exit(irq, action, res);
> + res = do_irqaction(desc, action, irq, dev_id);
>
> if (chip->irq_eoi)
> chip->irq_eoi(&desc->irq_data);
> --- a/kernel/irq/handle.c
> +++ b/kernel/irq/handle.c
> @@ -131,6 +131,23 @@ void __irq_wake_thread(struct irq_desc *
> }
>
> irqreturn_t
> +do_irqaction(struct irq_desc *desc, struct irqaction *action,
> + unsigned int irq, void *dev_id)
> +{
> + irqreturn_t ret;
> +
> + if (unlikely((desc->istate & IRQS_SUSPENDED) &&
> + !(action->flags & IRQF_NO_SUSPEND)))
> + return IRQ_NONE;
> +
> + trace_irq_handler_entry(irq, action);
> + ret = action->handler(irq, dev_id);
> + trace_irq_handler_exit(irq, action, ret);
> +
> + return ret;
> +}
> +
> +irqreturn_t
> handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
> {
> irqreturn_t retval = IRQ_NONE;
> @@ -139,9 +156,7 @@ handle_irq_event_percpu(struct irq_desc
> do {
> irqreturn_t res;
>
> - trace_irq_handler_entry(irq, action);
> - res = action->handler(irq, action->dev_id);
> - trace_irq_handler_exit(irq, action, res);
> + res = do_irqaction(desc, action, irq, action->dev_id);
>
> if (WARN_ONCE(!irqs_disabled(),"irq %u handler %pF enabled interrupts\n",
> irq, action->handler))
> @@ -175,6 +190,9 @@ handle_irq_event_percpu(struct irq_desc
>
> add_interrupt_randomness(irq, flags);
>
> + if (unlikely(desc->istate & IRQS_SUSPENDED) && retval == IRQ_NONE)
> + retval = IRQ_HANDLED;
> +
> if (!noirqdebug)
> note_interrupt(irq, desc, retval);
> return retval;
> --- a/kernel/irq/internals.h
> +++ b/kernel/irq/internals.h
> @@ -63,8 +63,10 @@ enum {
>
> extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
> unsigned long flags);
> -extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp);
> -extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume);
> +
> +extern irqreturn_t
> +do_irqaction(struct irq_desc *desc, struct irqaction *action,
> + unsigned int irq, void *dev_id);
>
> extern int irq_startup(struct irq_desc *desc, bool resend);
> extern void irq_shutdown(struct irq_desc *desc);
> --- a/kernel/irq/manage.c
> +++ b/kernel/irq/manage.c
> @@ -382,15 +382,8 @@ setup_affinity(unsigned int irq, struct
> }
> #endif
>
> -void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
> +void __disable_irq(struct irq_desc *desc, unsigned int irq)
> {
> - if (suspend) {
> - if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND) ||
> - irqd_has_set(&desc->irq_data, IRQD_WAKEUP_STATE))
> - return;
> - desc->istate |= IRQS_SUSPENDED;
> - }
> -
> if (!desc->depth++)
> irq_disable(desc);
> }
> @@ -402,7 +395,7 @@ static int __disable_irq_nosync(unsigned
>
> if (!desc)
> return -EINVAL;
> - __disable_irq(desc, irq, false);
> + __disable_irq(desc, irq);
> irq_put_desc_busunlock(desc, flags);
> return 0;
> }
> @@ -443,20 +436,8 @@ void disable_irq(unsigned int irq)
> }
> EXPORT_SYMBOL(disable_irq);
>
> -void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume)
> +void __enable_irq(struct irq_desc *desc, unsigned int irq)
> {
> - if (resume) {
> - if (!(desc->istate & IRQS_SUSPENDED)) {
> - if (!desc->action)
> - return;
> - if (!(desc->action->flags & IRQF_FORCE_RESUME))
> - return;
> - /* Pretend that it got disabled ! */
> - desc->depth++;
> - }
> - desc->istate &= ~IRQS_SUSPENDED;
> - }
> -
> switch (desc->depth) {
> case 0:
> err_out:
> @@ -498,7 +479,7 @@ void enable_irq(unsigned int irq)
> KERN_ERR "enable_irq before setup/request_irq: irq %u\n", irq))
> goto out;
>
> - __enable_irq(desc, irq, false);
> + __enable_irq(desc, irq);
> out:
> irq_put_desc_busunlock(desc, flags);
> }
> @@ -1079,7 +1060,7 @@ __setup_irq(unsigned int irq, struct irq
> */
>
> #define IRQF_MISMATCH \
> - (IRQF_TRIGGER_MASK | IRQF_ONESHOT | IRQF_NO_SUSPEND)
> + (IRQF_TRIGGER_MASK | IRQF_ONESHOT)
>
> if (!((old->flags & new->flags) & IRQF_SHARED) ||
> ((old->flags ^ new->flags) & IRQF_MISMATCH))
> @@ -1232,7 +1213,7 @@ __setup_irq(unsigned int irq, struct irq
> */
> if (shared && (desc->istate & IRQS_SPURIOUS_DISABLED)) {
> desc->istate &= ~IRQS_SPURIOUS_DISABLED;
> - __enable_irq(desc, irq, false);
> + __enable_irq(desc, irq);
> }
>
> raw_spin_unlock_irqrestore(&desc->lock, flags);
> --- a/kernel/irq/pm.c
> +++ b/kernel/irq/pm.c
> @@ -29,14 +29,20 @@ void suspend_device_irqs(void)
> for_each_irq_desc(irq, desc) {
> unsigned long flags;
>
> + /*
> + * Ideally this would be a global state, but we cannot
> + * for the trainwreck that is IRQD_WAKEUP_STATE.
> + */
> raw_spin_lock_irqsave(&desc->lock, flags);
> - __disable_irq(desc, irq, true);
> + if (!irqd_has_set(&desc->irq_data, IRQD_WAKEUP_STATE))
> + desc->istate |= IRQS_SUSPENDED;
> raw_spin_unlock_irqrestore(&desc->lock, flags);
> }
>
> - for_each_irq_desc(irq, desc)
> + for_each_irq_desc(irq, desc) {
> if (desc->istate & IRQS_SUSPENDED)
> synchronize_irq(irq);
> + }
> }
> EXPORT_SYMBOL_GPL(suspend_device_irqs);
>
> @@ -47,14 +53,9 @@ static void resume_irqs(bool want_early)
>
> for_each_irq_desc(irq, desc) {
> unsigned long flags;
> - bool is_early = desc->action &&
> - desc->action->flags & IRQF_EARLY_RESUME;
> -
> - if (!is_early && want_early)
> - continue;
>
> raw_spin_lock_irqsave(&desc->lock, flags);
> - __enable_irq(desc, irq, true);
> + desc->istate &= ~IRQS_SUSPENDED;
> raw_spin_unlock_irqrestore(&desc->lock, flags);
> }
> }
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
next prev parent reply other threads:[~2014-07-24 22:52 UTC|newest]
Thread overview: 73+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-24 21:26 [RFC][PATCH] irq: Rework IRQF_NO_SUSPENDED Peter Zijlstra
2014-07-24 22:02 ` Rafael J. Wysocki
2014-07-24 23:10 ` Rafael J. Wysocki [this message]
2014-07-25 5:58 ` Peter Zijlstra
2014-07-29 19:20 ` Brian Norris
2014-07-29 19:28 ` Peter Zijlstra
2014-07-29 20:41 ` Brian Norris
2014-07-25 9:27 ` Thomas Gleixner
2014-07-25 12:49 ` Rafael J. Wysocki
2014-07-25 13:55 ` Thomas Gleixner
2014-07-25 9:40 ` Thomas Gleixner
2014-07-25 12:40 ` Peter Zijlstra
2014-07-25 13:25 ` Peter Zijlstra
2014-07-25 17:03 ` Rafael J. Wysocki
2014-07-25 16:58 ` Peter Zijlstra
2014-07-25 21:00 ` Thomas Gleixner
2014-07-25 22:25 ` Rafael J. Wysocki
2014-07-25 23:07 ` Rafael J. Wysocki
2014-07-26 11:49 ` Rafael J. Wysocki
2014-07-26 11:53 ` Rafael J. Wysocki
2014-07-28 6:49 ` Peter Zijlstra
2014-07-28 12:33 ` Thomas Gleixner
2014-07-28 13:04 ` Peter Zijlstra
2014-07-28 21:53 ` Rafael J. Wysocki
2014-07-28 23:01 ` Rafael J. Wysocki
2014-07-29 12:46 ` Thomas Gleixner
2014-07-29 13:33 ` Rafael J. Wysocki
2014-07-30 21:46 ` [PATCH 0/3] irq / PM: wakeup interrupt interface for drivers (was: Re: [RFC][PATCH] irq: Rework IRQF_NO_SUSPENDED) Rafael J. Wysocki
2014-07-30 21:51 ` [PATCH 1/3] irq / PM: New driver interface for wakeup interrupts Rafael J. Wysocki
2014-07-30 22:56 ` Thomas Gleixner
2014-07-31 0:12 ` Thomas Gleixner
2014-07-31 2:14 ` Rafael J. Wysocki
2014-07-31 10:44 ` Thomas Gleixner
2014-07-31 18:36 ` Rafael J. Wysocki
2014-07-31 20:12 ` Alan Stern
2014-07-31 21:04 ` Rafael J. Wysocki
2014-07-31 23:41 ` Thomas Gleixner
2014-08-01 0:51 ` Rafael J. Wysocki
2014-08-01 14:41 ` Alan Stern
2014-07-31 22:16 ` Thomas Gleixner
2014-08-01 0:08 ` Rafael J. Wysocki
2014-08-01 1:24 ` Rafael J. Wysocki
2014-08-01 9:40 ` [PATCH 1/3] irq / PM: New driver interface for wakeup interruptsn Thomas Gleixner
2014-08-01 13:45 ` Rafael J. Wysocki
2014-08-01 13:43 ` Thomas Gleixner
2014-08-01 14:29 ` Rafael J. Wysocki
2014-08-02 1:31 ` Rafael J. Wysocki
2014-08-03 13:42 ` Rafael J. Wysocki
2014-08-04 3:38 ` Rafael J. Wysocki
2014-08-05 15:22 ` [PATCH 0/5] irq / PM: Shared IRQs vs IRQF_NO_SUSPEND and suspend-to-idle wakeup Rafael J. Wysocki
2014-08-05 15:24 ` [PATCH 1/5] PM / sleep: Mechanism for aborting system suspends unconditionally Rafael J. Wysocki
2014-08-05 23:29 ` [Update][PATCH " Rafael J. Wysocki
2014-08-05 15:25 ` [PATCH 2/5] irq / PM: Fix IRQF_NO_SUSPEND problem with shared interrupts Rafael J. Wysocki
2014-08-05 15:26 ` [PATCH 3/5] irq / PM: Make wakeup interrupts wake up from suspend-to-idle Rafael J. Wysocki
2014-08-08 1:58 ` [Update][PATCH " Rafael J. Wysocki
2014-08-09 0:28 ` Rafael J. Wysocki
2014-08-05 15:27 ` [PATCH 4/5] x86 / PM: Set IRQCHIP_SKIP_SET_WAKE for IOAPIC IRQ chip objects Rafael J. Wysocki
2014-08-05 15:28 ` [PATCH 5/5] PCI / PM: Make PCIe PME interrupts wake up from suspend-to-idle Rafael J. Wysocki
2014-08-05 16:12 ` [PATCH 0/5] irq / PM: Shared IRQs vs IRQF_NO_SUSPEND and suspend-to-idle wakeup Peter Zijlstra
2014-08-08 2:09 ` Rafael J. Wysocki
2014-07-31 22:54 ` [PATCH 1/3] irq / PM: New driver interface for wakeup interrupts Thomas Gleixner
2014-07-30 21:51 ` [PATCH 2/3] PCI / PM: Make PCIe PME interrupts wake up from "freeze" sleep state Rafael J. Wysocki
2014-07-30 21:52 ` [PATCH 3/3] gpio-keys / PM: use enable/disable_device_irq_wake() Rafael J. Wysocki
2014-07-28 21:27 ` [RFC][PATCH] irq: Rework IRQF_NO_SUSPENDED Rafael J. Wysocki
2014-07-27 15:53 ` Rafael J. Wysocki
2014-07-27 22:00 ` [PATCH, v2] Rafael J. Wysocki
2014-07-28 12:11 ` Thomas Gleixner
2014-07-28 21:17 ` [PATCH, v3] irq / PM: Fix IRQF_NO_SUSPEND problem with shared interrupts (was: Re: [PATCH, v2]) Rafael J. Wysocki
2014-07-29 7:28 ` [PATCH, v4] irq / PM: Fix IRQF_NO_SUSPEND problem with shared interrupts Rafael J. Wysocki
2014-07-29 13:46 ` [PATCH, v5] " Rafael J. Wysocki
2014-07-30 0:54 ` [PATCH, v6] " Rafael J. Wysocki
2014-07-25 12:47 ` [RFC][PATCH] irq: Rework IRQF_NO_SUSPENDED Rafael J. Wysocki
2014-07-25 13:22 ` Peter Zijlstra
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=13290270.IfKaUSRMLR@vostro.rjw.lan \
--to=rjw@rjwysocki.net \
--cc=dmitry.torokhov@gmail.com \
--cc=dtor@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox