All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Rafael J. Wysocki" <rjw@rjwysocki.net>
To: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>,
	linux-kernel@vger.kernel.org,
	Linux PM list <linux-pm@vger.kernel.org>,
	Dmitry Torokhov <dtor@google.com>
Subject: Re: [PATCH 0/5] irq / PM: Shared IRQs vs IRQF_NO_SUSPEND and suspend-to-idle wakeup
Date: Fri, 08 Aug 2014 04:09 +0200	[thread overview]
Message-ID: <4089915.QH7xXfFoFW@vostro.rjw.lan> (raw)
In-Reply-To: <3321219.itH23ZEDt4@vostro.rjw.lan>

On Tuesday, August 05, 2014 05:22:57 PM Rafael J. Wysocki wrote:
> On Friday, August 01, 2014 04:29:40 PM Rafael J. Wysocki wrote:
> > On Friday, August 01, 2014 03:43:21 PM Thomas Gleixner wrote:
> > > On Fri, 1 Aug 2014, Rafael J. Wysocki wrote:
> > > > OK, I guess "IRQ_HANDLED from a wakeup interrupt" may be interpreted as
> > > > IRQ_HANDLED_PMWAKE.  On the other hand, if that's going to be handled in
> > > > handle_irq_event_percpu(), then using a special return code would save us
> > > > a brach for IRQ_HANDLED interrupts.  We could convert it to IRQ_HANDLED
> > > > immediately then.
> > > 
> > > We can handle it at the end of the function by calling
> > > note_interrupt() unconditionally do the following there:
> > > 
> > >       if (suspended) {
> > >       	 if (ret == IRQ_NONE) {
> > > 	    if (shared)
> > > 	       yell_and_abort_or_resume();
> > >          } else {
> > > 	    abort_or_resume();
> > >          }
> > >       }
> > >       if (noirqdebug)
> > >       	 return;
> > 
> > I see.
> > 
> > > > OK, I'll take a stab at the IRQF_SHARED thing if you don't mind.
> > > 
> > > Definitely not :)
> > > 
> > > > Here's my current understanding of what can be done for IRQF_NO_SUSPEND.
> > > > 
> > > > In suspend_device_irqs():
> > > > 
> > > > (1) If all actions in the list have the same setting (eg. IRQF_NO_SUSPEND unset),
> > > >     keep the current behavior.
> > > > (2) If the actions have different settings:
> > > >     - Actions with IRQF_NO_SUSPEND set are not modified.
> > > >     - Actions with IRQF_NO_SUSPEND unset are switched over to a stub handler.
> > > >     - IRQS_SUSPEND_MODE (new flag) is set for the IRQ.
> > > 
> > > Can we please do that in setup_irq() and let the shared ones always
> > > run through the stub? That keeps suspend/resume_device_irqs() simple.
> > 
> > OK
> 
> Here's a patch series based on what we talked about.
> 
> [1/5] Mechanism to wake up the system or abort suspend in progress automatically.
> [2/5] Fix for shared IRQs vs IRQF_NO_SUSPEND (with wakeup in mind).
> [3/5] Wakeup interrupts support for suspend-to-idle.
> [4/5] Set IRQCHIP_SKIP_SET_WAKE for x86 IOAPIC IRQ chips.
> [5/5] Make PCIe PME wake up from suspend to idle.
> 
> All tested on MSI Wind that has a couple of issues being addressed.

Below is the doc patch I promised.

I'm not signing it off yet, as I'm sending it for comments mostly rather than
as something actually done.

Of course, it documents the situation after the series of [1-5/5] (with the
updated [3/5] I've just sent), especially as far as the suspend-to-idle goes.

Rafael


---
 Documentation/power/suspend-and-interrupts.txt |  136 +++++++++++++++++++++++++
 1 file changed, 136 insertions(+)

Index: linux-pm/Documentation/power/suspend-and-interrupts.txt
===================================================================
--- /dev/null
+++ linux-pm/Documentation/power/suspend-and-interrupts.txt
@@ -0,0 +1,136 @@
+System Suspend and Device Interrupts
+
+Copyright (C) 2014 Intel Corp.
+Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+
+Suspending and Resuming Device IRQs
+-----------------------------------
+
+Device interrupt request lines (IRQs) are generally disabled during system
+suspend after the "late" phase of suspending devices (that is, after all of the
+->prepare, ->suspend and ->suspend_late callbacks have been executed for all
+devices).  That is done by the suspend_device_irqs() function.
+
+The rationale for doing so is that after the "late" phase of device suspend
+there is no legitimate reason why any interrupts from suspended devices should
+trigger and if any devices have not been suspended properly yet, it is better to
+block interrupts from them anyway.  Also in the past we had problems with
+interrupt handlers of devices that shared IRQs with other devices and were not
+prepared for interrupts triggering after their devices had been suspended.
+In those cases they would attempt to access, for example, memory address spaces
+of suspended devices and cause unpredictable behavior to ensue as a result.
+Unfortunately, such problems are very difficult to debug and the introduction
+of suspend_device_irqs(), along with the "noirq" phase of device suspend, was
+the only practical way to prevent them from happening.
+
+Device IRQs are re-enabled during system resume, right before the "early" phase
+of resuming devices (that is, before starting to execute ->resume_early
+callbacks for devices).  The function doing that is resume_device_irqs().
+
+
+The IRQF_NO_SUSPEND Flag
+------------------------
+
+There are interrupts that can legitimately trigger during the entire system
+suspend-resume cycle, including the "noirq" phases of suspending and resuming
+devices as well as during the time when nonboot CPUs are taken offline and
+brought back online.  That applies to timer interrupts in the first place,
+but also to IPIs and to some other special-purpose interrupts, such as the ACPI
+SCI that isn't associated with any specific device and is used for signaling
+many different types of events.
+
+The IRQF_NO_SUSPEND flag is used to indicate that to the IRQ subsystem when
+requesting a special-purpose interrupt.  It causes suspend_device_irqs() to
+leave the corresponding IRQ enabled so as to allow the interrupt to work all
+the time as expected.
+
+If that IRQ is shared, it will still be left enabled by suspend_device_irqs(),
+but the interrupt handlers that were installed for it without IRQF_NO_SUSPEND
+set will not be executed after suspend_device_irqs() has returned.  Then, the
+IRQ subsystem will only execute interrupt handlers for which IRQF_NO_SUSPEND is
+set.  In that case, if the final result of handing an interrupt is IRQ_NONE, the
+IRQ subsystem will assume that the interrupt came from one of the apparently
+suspended devices that share the IRQ with an IRQF_NO_SUSPEND interrupt source
+(or more of them).  As a result, the IRQ will be disabled and marked as
+"suspended" to prevent spurious interrupts from triggering going forward.
+Next
+(1) if a system suspend is in progress, it will be aborted or
+(2) if the system is in the "freeze" sleep state (suspend-to-idle), it will be
+    woken up,
+to allow the system to recover from that error condition gracefully.
+
+The IRQF_NO_SUSPEND flag should not be used when requesting system wakeup
+interrupts (that is, interrupts that are supposed to wake up the system from
+sleep states), unless there are other (that is, unrelated to system wakeup)
+reasons why those interrupts can legitimately trigger after suspend_device_irqs()
+has returned and before resume_device_irqs() is called during the subsequent
+system resume.
+
+
+System Wakeup Interrupts, enable_irq_wake() and disable_irq_wake()
+------------------------------------------------------------------
+
+System wakeup interrupts generally need to be configured to wake up the system
+from sleep states, especially if they are used for different purposes (e.g. as
+I/O interrupts) in the working state.
+
+That may involve turning on a special signal handling logic within the platform
+(such as an SoC) so that signals from a given line are routed in a different way
+during system sleep so as to trigger a system wakeup when needed.  For example,
+the platform may include a dedicated interrupt controller used specifically for
+handling system wakeup events.  Then, if a given interrupt line is supposed to
+wake up the system from sleep sates, the corresponding input of that interrupt
+controller needs to be enabled to handle signals from the line in question.
+After wakeup, it generally is better to disable that input to prevent the
+dedicated controller from triggering interrupts unnecessarily.
+
+The IRQ subsystem provides two helper functions to be used by device drivers for
+those purposes.  Namely, enable_irq_wake() turns on the platform's logic for
+handling the given IRQ as a system wakeup interrupt line and disable_irq_wake()
+turns that logic off.
+
+Calling enable_irq_wake() doesn't prevent the working-state logic for handling
+the given IRQ from being disabled by suspend_device_irqs(), so after the "late"
+phase of suspending devices the IRQ can only be expected to work as a system
+wakeup interrupt line.  The IRQ subsystem checks if there are any pending
+interrupts on those lines by calling check_wakeup_irqs() at the last (syscore)
+stage of full system suspend.  If there are any, it aborts the system suspend
+by returning -EBUSY from that function.
+
+
+System Wakeup Interrupts and Suspend-to-Idle
+--------------------------------------------
+
+Suspend-to-idle (also known as the "freeze" sleep state) is a relatively new
+system sleep state that works by idling all of the processors and waiting for
+interrupts right after the "noirq" phase of suspending devices.
+
+Of course, this means that all of the interrupts with IRQF_NO_SUSPEND set will
+bring CPUs out of idle while in that state, but they will not cause the IRQ
+subsystem to trigger a system wakeup, unless the final result of handling an
+interrupt is IRQ_NONE.
+
+System wakeup interrupts, in turn, are generally expected to trigger wakeup from
+system sleep states, including suspend-to-idle.  For this reason, all of the
+IRQs configured for system wakeup with enable_irq_wake(), previously disabled
+by suspend_device_irqs(), are re-enabled right before starting the final "go to
+an idle state and wait for an interrupt" loop of suspend-to-idle.  However, they
+are also reconfigured so that the original handlers associated with them will
+not be invoked at that time.  Those interrupt handlers are all temporarily
+replaced with stub handlers that always return IRQ_NONE.  That tells the IRQ
+subsystem to trigger wakeup from suspend-to-idle upon receiving one of those
+interrupts, which is analogous to how system wakeup from full suspend works
+(that is, system wakeup is triggered when there's a signal on one of the wakeup
+lines).
+
+The rationale for doing so is that, even if the original handlers for the
+wakeup interrupts were invoked (which is not the case for wakeup from full
+system suspend anyway), they wouldn't be able to access devices (presumably
+suspended at that point) and they would only be able to tell "wakeup!" to the
+IRQ core.  However, the core doesn't really need to ask them about that, as it
+can figure that out by itself well enough.
+
+When wakeup from suspend-to-idle is triggered, the wakeup IRQs are disabled
+again and their original behavior is restored.  They are subsequently re-enabled
+by resume_device_irqs(), as usual.


  parent reply	other threads:[~2014-08-08  1:50 UTC|newest]

Thread overview: 75+ 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
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 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-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 [this message]
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=4089915.QH7xXfFoFW@vostro.rjw.lan \
    --to=rjw@rjwysocki.net \
    --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 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.