diff mbox

PM / sleep / irq: Do not suspend wakeup interrupts

Message ID 4679574.kGUnqAuNl9@vostro.rjw.lan (mailing list archive)
State Accepted, archived
Headers show

Commit Message

Rafael J. Wysocki July 10, 2014, 9:37 p.m. UTC
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

If an IRQ has been configured for wakeup via enable_irq_wake(), the
driver who has done that must be prepared for receiving interrupts
after suspend_device_irqs() has returned, so there is no need to
"suspend" such IRQs.  Moreover, if drivers using enable_irq_wake()
actually want to receive interrupts after suspend_device_irqs() has
returned, they need to add IRQF_NO_SUSPEND to the IRQ flags while
requesting the IRQs, which shouldn't be necessary (it also goes a bit
too far, as IRQF_NO_SUSPEND causes the IRQ to be ignored by
suspend_device_irqs() all the time regardless of whether or not it
has been configured for signaling wakeup).

For the above reasons, make __disable_irq() ignore IRQ descriptors
with IRQD_WAKEUP_STATE set when its suspend argument is true which
effectively causes them to behave like IRQs with IRQF_NO_SUSPEND
set.

This also allows IRQs configured for wakeup via enable_irq_wake()
to work as wakeup interrupts for the "freeze" (suspend-to-idle)
sleep mode automatically just like for any other sleep states.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 kernel/irq/manage.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)


--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Alexander Stein July 15, 2014, 12:22 p.m. UTC | #1
On Thursday 10 July 2014 23:37:54, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> If an IRQ has been configured for wakeup via enable_irq_wake(), the
> driver who has done that must be prepared for receiving interrupts
> after suspend_device_irqs() has returned, so there is no need to
> "suspend" such IRQs.  Moreover, if drivers using enable_irq_wake()
> actually want to receive interrupts after suspend_device_irqs() has
> returned, they need to add IRQF_NO_SUSPEND to the IRQ flags while
> requesting the IRQs, which shouldn't be necessary (it also goes a bit
> too far, as IRQF_NO_SUSPEND causes the IRQ to be ignored by
> suspend_device_irqs() all the time regardless of whether or not it
> has been configured for signaling wakeup).
> 
> For the above reasons, make __disable_irq() ignore IRQ descriptors
> with IRQD_WAKEUP_STATE set when its suspend argument is true which
> effectively causes them to behave like IRQs with IRQF_NO_SUSPEND
> set.
> 
> This also allows IRQs configured for wakeup via enable_irq_wake()
> to work as wakeup interrupts for the "freeze" (suspend-to-idle)
> sleep mode automatically just like for any other sleep states.
> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  kernel/irq/manage.c |    3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> Index: linux-pm/kernel/irq/manage.c
> ===================================================================
> --- linux-pm.orig/kernel/irq/manage.c
> +++ linux-pm/kernel/irq/manage.c
> @@ -385,7 +385,8 @@ setup_affinity(unsigned int irq, struct
>  void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
>  {
>  	if (suspend) {
> -		if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
> +		if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND)
> +		    || irqd_has_set(&desc->irq_data, IRQD_WAKEUP_STATE))
>  			return;
>  		desc->istate |= IRQS_SUSPENDED;
>  	}

Nice, this fixes my wakeup problem from freeze using gpio-keys. Unfortunately my SPI-attached touchscreen controller cannot be used for wakeup from freeze. Using it to wakeup from mem does work instead. Any ideas what might be wrong in this case?

Best regards,
Alexander

--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alexander Stein July 15, 2014, 12:36 p.m. UTC | #2
On Tuesday 15 July 2014 14:50:28, Rafael J. Wysocki wrote:
> On Tuesday, July 15, 2014 02:22:25 PM Alexander Stein wrote:
> > On Thursday 10 July 2014 23:37:54, Rafael J. Wysocki wrote:
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > 
> > > If an IRQ has been configured for wakeup via enable_irq_wake(), the
> > > driver who has done that must be prepared for receiving interrupts
> > > after suspend_device_irqs() has returned, so there is no need to
> > > "suspend" such IRQs.  Moreover, if drivers using enable_irq_wake()
> > > actually want to receive interrupts after suspend_device_irqs() has
> > > returned, they need to add IRQF_NO_SUSPEND to the IRQ flags while
> > > requesting the IRQs, which shouldn't be necessary (it also goes a bit
> > > too far, as IRQF_NO_SUSPEND causes the IRQ to be ignored by
> > > suspend_device_irqs() all the time regardless of whether or not it
> > > has been configured for signaling wakeup).
> > > 
> > > For the above reasons, make __disable_irq() ignore IRQ descriptors
> > > with IRQD_WAKEUP_STATE set when its suspend argument is true which
> > > effectively causes them to behave like IRQs with IRQF_NO_SUSPEND
> > > set.
> > > 
> > > This also allows IRQs configured for wakeup via enable_irq_wake()
> > > to work as wakeup interrupts for the "freeze" (suspend-to-idle)
> > > sleep mode automatically just like for any other sleep states.
> > > 
> > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > ---
> > >  kernel/irq/manage.c |    3 ++-
> > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > > 
> > > Index: linux-pm/kernel/irq/manage.c
> > > ===================================================================
> > > --- linux-pm.orig/kernel/irq/manage.c
> > > +++ linux-pm/kernel/irq/manage.c
> > > @@ -385,7 +385,8 @@ setup_affinity(unsigned int irq, struct
> > >  void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
> > >  {
> > >  	if (suspend) {
> > > -		if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
> > > +		if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND)
> > > +		    || irqd_has_set(&desc->irq_data, IRQD_WAKEUP_STATE))
> > >  			return;
> > >  		desc->istate |= IRQS_SUSPENDED;
> > >  	}
> > 
> > Nice, this fixes my wakeup problem from freeze using gpio-keys. Unfortunately my SPI-attached touchscreen controller cannot be used for wakeup from freeze. Using it to wakeup from mem does work instead. Any ideas what might be wrong in this case?
> 
> Not without looking at the code in question.
> 
> One guess would be a missing call to enable_irq_wake().

No, ads7846.c does call 'enable_irq_wake(ts->spi->irq)'. So is this a platform or driver specific problem?

Regards,
Alexander

--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael J. Wysocki July 15, 2014, 12:50 p.m. UTC | #3
On Tuesday, July 15, 2014 02:22:25 PM Alexander Stein wrote:
> On Thursday 10 July 2014 23:37:54, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > 
> > If an IRQ has been configured for wakeup via enable_irq_wake(), the
> > driver who has done that must be prepared for receiving interrupts
> > after suspend_device_irqs() has returned, so there is no need to
> > "suspend" such IRQs.  Moreover, if drivers using enable_irq_wake()
> > actually want to receive interrupts after suspend_device_irqs() has
> > returned, they need to add IRQF_NO_SUSPEND to the IRQ flags while
> > requesting the IRQs, which shouldn't be necessary (it also goes a bit
> > too far, as IRQF_NO_SUSPEND causes the IRQ to be ignored by
> > suspend_device_irqs() all the time regardless of whether or not it
> > has been configured for signaling wakeup).
> > 
> > For the above reasons, make __disable_irq() ignore IRQ descriptors
> > with IRQD_WAKEUP_STATE set when its suspend argument is true which
> > effectively causes them to behave like IRQs with IRQF_NO_SUSPEND
> > set.
> > 
> > This also allows IRQs configured for wakeup via enable_irq_wake()
> > to work as wakeup interrupts for the "freeze" (suspend-to-idle)
> > sleep mode automatically just like for any other sleep states.
> > 
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> >  kernel/irq/manage.c |    3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> > 
> > Index: linux-pm/kernel/irq/manage.c
> > ===================================================================
> > --- linux-pm.orig/kernel/irq/manage.c
> > +++ linux-pm/kernel/irq/manage.c
> > @@ -385,7 +385,8 @@ setup_affinity(unsigned int irq, struct
> >  void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
> >  {
> >  	if (suspend) {
> > -		if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
> > +		if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND)
> > +		    || irqd_has_set(&desc->irq_data, IRQD_WAKEUP_STATE))
> >  			return;
> >  		desc->istate |= IRQS_SUSPENDED;
> >  	}
> 
> Nice, this fixes my wakeup problem from freeze using gpio-keys. Unfortunately my SPI-attached touchscreen controller cannot be used for wakeup from freeze. Using it to wakeup from mem does work instead. Any ideas what might be wrong in this case?

Not without looking at the code in question.

One guess would be a missing call to enable_irq_wake().

Rafael

--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael J. Wysocki July 16, 2014, 12:45 a.m. UTC | #4
On Tuesday, July 15, 2014 02:36:46 PM Alexander Stein wrote:
> On Tuesday 15 July 2014 14:50:28, Rafael J. Wysocki wrote:
> > On Tuesday, July 15, 2014 02:22:25 PM Alexander Stein wrote:
> > > On Thursday 10 July 2014 23:37:54, Rafael J. Wysocki wrote:
> > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > 
> > > > If an IRQ has been configured for wakeup via enable_irq_wake(), the
> > > > driver who has done that must be prepared for receiving interrupts
> > > > after suspend_device_irqs() has returned, so there is no need to
> > > > "suspend" such IRQs.  Moreover, if drivers using enable_irq_wake()
> > > > actually want to receive interrupts after suspend_device_irqs() has
> > > > returned, they need to add IRQF_NO_SUSPEND to the IRQ flags while
> > > > requesting the IRQs, which shouldn't be necessary (it also goes a bit
> > > > too far, as IRQF_NO_SUSPEND causes the IRQ to be ignored by
> > > > suspend_device_irqs() all the time regardless of whether or not it
> > > > has been configured for signaling wakeup).
> > > > 
> > > > For the above reasons, make __disable_irq() ignore IRQ descriptors
> > > > with IRQD_WAKEUP_STATE set when its suspend argument is true which
> > > > effectively causes them to behave like IRQs with IRQF_NO_SUSPEND
> > > > set.
> > > > 
> > > > This also allows IRQs configured for wakeup via enable_irq_wake()
> > > > to work as wakeup interrupts for the "freeze" (suspend-to-idle)
> > > > sleep mode automatically just like for any other sleep states.
> > > > 
> > > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > ---
> > > >  kernel/irq/manage.c |    3 ++-
> > > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > > > 
> > > > Index: linux-pm/kernel/irq/manage.c
> > > > ===================================================================
> > > > --- linux-pm.orig/kernel/irq/manage.c
> > > > +++ linux-pm/kernel/irq/manage.c
> > > > @@ -385,7 +385,8 @@ setup_affinity(unsigned int irq, struct
> > > >  void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
> > > >  {
> > > >  	if (suspend) {
> > > > -		if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
> > > > +		if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND)
> > > > +		    || irqd_has_set(&desc->irq_data, IRQD_WAKEUP_STATE))
> > > >  			return;
> > > >  		desc->istate |= IRQS_SUSPENDED;
> > > >  	}
> > > 
> > > Nice, this fixes my wakeup problem from freeze using gpio-keys. Unfortunately my SPI-attached touchscreen controller cannot be used for wakeup from freeze. Using it to wakeup from mem does work instead. Any ideas what might be wrong in this case?
> > 
> > Not without looking at the code in question.
> > 
> > One guess would be a missing call to enable_irq_wake().
> 
> No, ads7846.c does call 'enable_irq_wake(ts->spi->irq)'. So is this a platform or driver specific problem?

Well, both code paths are identical from the driver's perspective, so I'd bet
on the platform, but that's only a guess at this point.

Rafael

--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

Index: linux-pm/kernel/irq/manage.c
===================================================================
--- linux-pm.orig/kernel/irq/manage.c
+++ linux-pm/kernel/irq/manage.c
@@ -385,7 +385,8 @@  setup_affinity(unsigned int irq, struct
 void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
 {
 	if (suspend) {
-		if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
+		if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND)
+		    || irqd_has_set(&desc->irq_data, IRQD_WAKEUP_STATE))
 			return;
 		desc->istate |= IRQS_SUSPENDED;
 	}