Re: [PATCH 2/3] IRQ: allow check_wakeup_irqs to notice level-triggered interrupts.
On Fri, 4 May 2012 18:01:22 +0200 (CEST) Thomas Gleixner t...@linutronix.de wrote: Neil, On Fri, 4 May 2012, NeilBrown wrote: On Wed, 25 Apr 2012 14:54:54 +0200 (CEST) Thomas Gleixner t...@linutronix.de wrote: Why not simply managing the pending bit for level irqs ? Hi Thomas, thanks again for the patch. I finally made time to test it and it works as expected. I've included it below with a change-log entry and tested-by: in case that helps. thanks for testing. The changelog is great. You know how to make the live of lazy buggers easier :) Just buttering you up so any future patches slip past easily :-) I think I'll need to ask for IRQS_PENDING to be set for nested interrupts too but I'll be a little while before I an look at that issue properly and propose a patch. Thanks for your help, NeilBrown for_each_irq_desc(irq, desc) { - if (irqd_is_wakeup_set(desc-irq_data)) { + if (desc-depth == 1 + irqd_is_wakeup_set(desc-irq_data)) { if (desc-istate IRQS_PENDING) return -EBUSY; continue; I split that part into a separate patch, as it's really a different issue. Thanks, tglx signature.asc Description: PGP signature
Re: [PATCH 2/3] IRQ: allow check_wakeup_irqs to notice level-triggered interrupts.
Neil, On Fri, 4 May 2012, NeilBrown wrote: On Wed, 25 Apr 2012 14:54:54 +0200 (CEST) Thomas Gleixner t...@linutronix.de wrote: Why not simply managing the pending bit for level irqs ? Hi Thomas, thanks again for the patch. I finally made time to test it and it works as expected. I've included it below with a change-log entry and tested-by: in case that helps. thanks for testing. The changelog is great. You know how to make the live of lazy buggers easier :) for_each_irq_desc(irq, desc) { - if (irqd_is_wakeup_set(desc-irq_data)) { + if (desc-depth == 1 + irqd_is_wakeup_set(desc-irq_data)) { if (desc-istate IRQS_PENDING) return -EBUSY; continue; I split that part into a separate patch, as it's really a different issue. Thanks, tglx -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/3] IRQ: allow check_wakeup_irqs to notice level-triggered interrupts.
On Wed, 25 Apr 2012 14:54:54 +0200 (CEST) Thomas Gleixner t...@linutronix.de wrote: Why not simply managing the pending bit for level irqs ? Hi Thomas, thanks again for the patch. I finally made time to test it and it works as expected. I've included it below with a change-log entry and tested-by: in case that helps. Thanks, NeilBrown From: Thomas Gleixner t...@linutronix.de Date: Wed, 25 Apr 2012 12:54:54 +0200 Subject: [PATCH] IRQ: allow check_wakeup_irqs to notice level-triggered interrupts. Level triggered interrupts do not cause IRQS_PENDING to be set when they fire-while-disabled as the 'pending' state is always present in the level - they automatically refire where re-enabled. However the IRQS_PENDING flag is also used to abort a suspend cycle - if any 'is_wakeup_set' interrupt is PENDING, check_wakeup_irqs() will cause suspend to abort. Without IRQS_PENDING, suspend won't abort. Consequently, level-triggered interrupts that fire during the 'noirq' phase of suspend do not currently abort suspend. So set IRQS_PENDING even for level triggered interrupts, and make sure to clear the flag in check_irq_resend. Also: in check_wakeup_irqs, ignore 'is_wakeup' interrupts that were already disabled before suspend_device_irqs() disabled them further. Tested-by: NeilBrown ne...@suse.de diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 6080f6b..741f836 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -379,8 +379,10 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) * If its disabled or no action available * keep it masked and get out of here */ - if (unlikely(!desc-action || irqd_irq_disabled(desc-irq_data))) + if (unlikely(!desc-action || irqd_irq_disabled(desc-irq_data))) { + desc-istate |= IRQS_PENDING; goto out_unlock; + } handle_irq_event(desc); diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c index 15e53b1..b858ce3 100644 --- a/kernel/irq/pm.c +++ b/kernel/irq/pm.c @@ -103,7 +103,8 @@ int check_wakeup_irqs(void) int irq; for_each_irq_desc(irq, desc) { - if (irqd_is_wakeup_set(desc-irq_data)) { + if (desc-depth == 1 + irqd_is_wakeup_set(desc-irq_data)) { if (desc-istate IRQS_PENDING) return -EBUSY; continue; diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c index 14dd576..6454db7 100644 --- a/kernel/irq/resend.c +++ b/kernel/irq/resend.c @@ -58,10 +58,13 @@ void check_irq_resend(struct irq_desc *desc, unsigned int irq) /* * We do not resend level type interrupts. Level type * interrupts are resent by hardware when they are still -* active. +* active. Clear the pending bit so suspend/resume does not +* get confused. */ - if (irq_settings_is_level(desc)) + if (irq_settings_is_level(desc)) { + desc-istate = ~IRQS_PENDING; return; + } if (desc-istate IRQS_REPLAY) return; if (desc-istate IRQS_PENDING) { signature.asc Description: PGP signature
Re: [PATCH 2/3] IRQ: allow check_wakeup_irqs to notice level-triggered interrupts.
On Wed, 25 Apr 2012, NeilBrown wrote: Level triggered interrupts do not cause IRQS_PENDING to be set, so check_wakeup_irqs ignores them. They don't need to set IRQS_PENDING as the level stays high which shows that they must be pending. However if such an interrupt fired during late suspend, it will have been masked so the fact that it is still asserted will not cause the suspend to abort. So if any wakeup interrupt is masked, unmask it when checking wakeup irqs. If the interrupt is asserted, suspend will abort. Signed-off-by: NeilBrown ne...@suse.de --- kernel/irq/pm.c |6 ++ 1 file changed, 6 insertions(+) diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c index 15e53b1..0d26206 100644 --- a/kernel/irq/pm.c +++ b/kernel/irq/pm.c @@ -106,6 +106,12 @@ int check_wakeup_irqs(void) if (irqd_is_wakeup_set(desc-irq_data)) { if (desc-istate IRQS_PENDING) return -EBUSY; + if (irqd_irq_masked(desc-irq_data)) + /* Probably a level interrupt + * which fired recently and was + * masked + */ + unmask_irq(desc); Oh no. We don't unmask unconditionally. What about an interrupt which is disabled, has no handler . ? That needs more thought. Thanks, tglx -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/3] IRQ: allow check_wakeup_irqs to notice level-triggered interrupts.
On Wed, 25 Apr 2012 10:50:15 +0200 (CEST) Thomas Gleixner t...@linutronix.de wrote: On Wed, 25 Apr 2012, NeilBrown wrote: Level triggered interrupts do not cause IRQS_PENDING to be set, so check_wakeup_irqs ignores them. They don't need to set IRQS_PENDING as the level stays high which shows that they must be pending. However if such an interrupt fired during late suspend, it will have been masked so the fact that it is still asserted will not cause the suspend to abort. So if any wakeup interrupt is masked, unmask it when checking wakeup irqs. If the interrupt is asserted, suspend will abort. Signed-off-by: NeilBrown ne...@suse.de --- kernel/irq/pm.c |6 ++ 1 file changed, 6 insertions(+) diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c index 15e53b1..0d26206 100644 --- a/kernel/irq/pm.c +++ b/kernel/irq/pm.c @@ -106,6 +106,12 @@ int check_wakeup_irqs(void) if (irqd_is_wakeup_set(desc-irq_data)) { if (desc-istate IRQS_PENDING) return -EBUSY; + if (irqd_irq_masked(desc-irq_data)) + /* Probably a level interrupt +* which fired recently and was +* masked +*/ + unmask_irq(desc); Oh no. We don't unmask unconditionally. What about an interrupt which is disabled, has no handler . ? That needs more thought. If there is no handler, then irqd_is_wakeup_set() should fail should it not? For disabled: would it be OK to check desc-depth? Something like: if (desc-depth == 1 (desc-state IRQS_SUSPENDED) irqd_irq_masked(desc-irq_data)) unmask_irq(desc); ?? Thanks, NeilBrown signature.asc Description: PGP signature
Re: [PATCH 2/3] IRQ: allow check_wakeup_irqs to notice level-triggered interrupts.
On Wed, 25 Apr 2012, NeilBrown wrote: On Wed, 25 Apr 2012 10:50:15 +0200 (CEST) Thomas Gleixner t...@linutronix.de wrote: On Wed, 25 Apr 2012, NeilBrown wrote: Level triggered interrupts do not cause IRQS_PENDING to be set, so check_wakeup_irqs ignores them. They don't need to set IRQS_PENDING as the level stays high which shows that they must be pending. However if such an interrupt fired during late suspend, it will have been masked so the fact that it is still asserted will not cause the suspend to abort. So if any wakeup interrupt is masked, unmask it when checking wakeup irqs. If the interrupt is asserted, suspend will abort. Signed-off-by: NeilBrown ne...@suse.de --- kernel/irq/pm.c |6 ++ 1 file changed, 6 insertions(+) diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c index 15e53b1..0d26206 100644 --- a/kernel/irq/pm.c +++ b/kernel/irq/pm.c @@ -106,6 +106,12 @@ int check_wakeup_irqs(void) if (irqd_is_wakeup_set(desc-irq_data)) { if (desc-istate IRQS_PENDING) return -EBUSY; + if (irqd_irq_masked(desc-irq_data)) + /* Probably a level interrupt + * which fired recently and was + * masked + */ + unmask_irq(desc); Oh no. We don't unmask unconditionally. What about an interrupt which is disabled, has no handler . ? That needs more thought. If there is no handler, then irqd_is_wakeup_set() should fail should it not? Well, it does not. The wakeup state is a permanent flag on the irq line. Though we don't have IRQS_SUSPENDED on that descriptor. For disabled: would it be OK to check desc-depth? Something like: if (desc-depth == 1 (desc-state IRQS_SUSPENDED) irqd_irq_masked(desc-irq_data)) unmask_irq(desc); Why not simply managing the pending bit for level irqs ? Index: tip/kernel/irq/chip.c === --- tip.orig/kernel/irq/chip.c +++ tip/kernel/irq/chip.c @@ -379,8 +379,10 @@ handle_level_irq(unsigned int irq, struc * If its disabled or no action available * keep it masked and get out of here */ - if (unlikely(!desc-action || irqd_irq_disabled(desc-irq_data))) + if (unlikely(!desc-action || irqd_irq_disabled(desc-irq_data))) { + desc-istate |= IRQS_PENDING; goto out_unlock; + } handle_irq_event(desc); Index: tip/kernel/irq/resend.c === --- tip.orig/kernel/irq/resend.c +++ tip/kernel/irq/resend.c @@ -58,10 +58,13 @@ void check_irq_resend(struct irq_desc *d /* * We do not resend level type interrupts. Level type * interrupts are resent by hardware when they are still -* active. +* active. Clear the pending bit so suspend/resume does not +* get confused. */ - if (irq_settings_is_level(desc)) + if (irq_settings_is_level(desc)) { + desc-istate = ~IRQS_PENDING; return; + } if (desc-istate IRQS_REPLAY) return; if (desc-istate IRQS_PENDING) { And to handle interrupts which have been disabled before suspend add: Index: tip/kernel/irq/pm.c === --- tip.orig/kernel/irq/pm.c +++ tip/kernel/irq/pm.c @@ -103,7 +103,8 @@ int check_wakeup_irqs(void) int irq; for_each_irq_desc(irq, desc) { - if (irqd_is_wakeup_set(desc-irq_data)) { + if (desc-depth == 1 + irqd_is_wakeup_set(desc-irq_data)) { if (desc-istate IRQS_PENDING) return -EBUSY; continue; -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/3] IRQ: allow check_wakeup_irqs to notice level-triggered interrupts.
On Wed, 25 Apr 2012 14:54:54 +0200 (CEST) Thomas Gleixner t...@linutronix.de wrote: On Wed, 25 Apr 2012, NeilBrown wrote: On Wed, 25 Apr 2012 10:50:15 +0200 (CEST) Thomas Gleixner t...@linutronix.de wrote: On Wed, 25 Apr 2012, NeilBrown wrote: Level triggered interrupts do not cause IRQS_PENDING to be set, so check_wakeup_irqs ignores them. They don't need to set IRQS_PENDING as the level stays high which shows that they must be pending. However if such an interrupt fired during late suspend, it will have been masked so the fact that it is still asserted will not cause the suspend to abort. So if any wakeup interrupt is masked, unmask it when checking wakeup irqs. If the interrupt is asserted, suspend will abort. Signed-off-by: NeilBrown ne...@suse.de --- kernel/irq/pm.c |6 ++ 1 file changed, 6 insertions(+) diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c index 15e53b1..0d26206 100644 --- a/kernel/irq/pm.c +++ b/kernel/irq/pm.c @@ -106,6 +106,12 @@ int check_wakeup_irqs(void) if (irqd_is_wakeup_set(desc-irq_data)) { if (desc-istate IRQS_PENDING) return -EBUSY; + if (irqd_irq_masked(desc-irq_data)) + /* Probably a level interrupt +* which fired recently and was +* masked +*/ + unmask_irq(desc); Oh no. We don't unmask unconditionally. What about an interrupt which is disabled, has no handler . ? That needs more thought. If there is no handler, then irqd_is_wakeup_set() should fail should it not? Well, it does not. The wakeup state is a permanent flag on the irq line. Though we don't have IRQS_SUSPENDED on that descriptor. For disabled: would it be OK to check desc-depth? Something like: if (desc-depth == 1 (desc-state IRQS_SUSPENDED) irqd_irq_masked(desc-irq_data)) unmask_irq(desc); Why not simply managing the pending bit for level irqs ? Primarily because I was aiming for the simplest patch that would have the desired effect. Also because 'pending' is implicit in the level so it seems superfluous to store the bit separately. And understanding all the consequences of that change is not something I felt up to. However: thanks for the patch. I'll try to explore it tomorrow and see if seems to be behaving correctly. Thanks, NeilBrown Index: tip/kernel/irq/chip.c === --- tip.orig/kernel/irq/chip.c +++ tip/kernel/irq/chip.c @@ -379,8 +379,10 @@ handle_level_irq(unsigned int irq, struc * If its disabled or no action available * keep it masked and get out of here */ - if (unlikely(!desc-action || irqd_irq_disabled(desc-irq_data))) + if (unlikely(!desc-action || irqd_irq_disabled(desc-irq_data))) { + desc-istate |= IRQS_PENDING; goto out_unlock; + } handle_irq_event(desc); Index: tip/kernel/irq/resend.c === --- tip.orig/kernel/irq/resend.c +++ tip/kernel/irq/resend.c @@ -58,10 +58,13 @@ void check_irq_resend(struct irq_desc *d /* * We do not resend level type interrupts. Level type * interrupts are resent by hardware when they are still - * active. + * active. Clear the pending bit so suspend/resume does not + * get confused. */ - if (irq_settings_is_level(desc)) + if (irq_settings_is_level(desc)) { + desc-istate = ~IRQS_PENDING; return; + } if (desc-istate IRQS_REPLAY) return; if (desc-istate IRQS_PENDING) { And to handle interrupts which have been disabled before suspend add: Index: tip/kernel/irq/pm.c === --- tip.orig/kernel/irq/pm.c +++ tip/kernel/irq/pm.c @@ -103,7 +103,8 @@ int check_wakeup_irqs(void) int irq; for_each_irq_desc(irq, desc) { - if (irqd_is_wakeup_set(desc-irq_data)) { + if (desc-depth == 1 + irqd_is_wakeup_set(desc-irq_data)) { if (desc-istate IRQS_PENDING) return -EBUSY; continue; signature.asc Description: PGP signature
[PATCH 2/3] IRQ: allow check_wakeup_irqs to notice level-triggered interrupts.
Level triggered interrupts do not cause IRQS_PENDING to be set, so check_wakeup_irqs ignores them. They don't need to set IRQS_PENDING as the level stays high which shows that they must be pending. However if such an interrupt fired during late suspend, it will have been masked so the fact that it is still asserted will not cause the suspend to abort. So if any wakeup interrupt is masked, unmask it when checking wakeup irqs. If the interrupt is asserted, suspend will abort. Signed-off-by: NeilBrown ne...@suse.de --- kernel/irq/pm.c |6 ++ 1 file changed, 6 insertions(+) diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c index 15e53b1..0d26206 100644 --- a/kernel/irq/pm.c +++ b/kernel/irq/pm.c @@ -106,6 +106,12 @@ int check_wakeup_irqs(void) if (irqd_is_wakeup_set(desc-irq_data)) { if (desc-istate IRQS_PENDING) return -EBUSY; + if (irqd_irq_masked(desc-irq_data)) + /* Probably a level interrupt +* which fired recently and was +* masked +*/ + unmask_irq(desc); continue; } /* -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html