From b615b0e3d4661277cfef5e94957dfa62b4d94bb9 Mon Sep 17 00:00:00 2001 From: Abhijeet Dharmapurikar Date: Fri, 21 Oct 2011 19:59:05 -0700 Subject: [PATCH] genirq: chip: set pending only for edge interrupts The IRQS_PENDING flag is meant to record an edge interrupt trigger event when that interrupt is disabled. When an edge triggered interrupt is enabled, check_irq_resend() retriggers that irq and resets the flag to zero if set. Note that check_irq_resend() only does this for edge triggered interrupts. For level triggered interrupts it is expected that the interrupt remains active and doesn't need this PENDING flag assistance from software for re-triggering it. However, handle_fasteoi_irq flow handler sets the PENDING flag even for a disabled level interrupt. This causes an adverse effect if that level interrupt is marked wakeup. The suspend code sees the pending flag on a wakeup interrupt and aborts suspend whereas check_irq_resend does not reset it to 0 (as it is a level interrupt). The end result is that the PENDING flag on this level triggered wakeup interrupt never clears and the system keeps aborting suspend. Fix this by setting IRQS_PENDING flag only for edge interrupts in the handle_fasteoi_irq. CRs-Fixed: 314344 Change-Id: I775d40f434f9309fd9672bae372b0f0fb5b91627 Signed-off-by: Abhijeet Dharmapurikar --- kernel/irq/chip.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index dc154f236a7..45e149c291b 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -396,7 +396,8 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) * then mask it and get out of here: */ if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) { - desc->istate |= IRQS_PENDING; + if (!irq_settings_is_level(desc)) + desc->istate |= IRQS_PENDING; mask_irq(desc); goto out; }