spmi: qpnp-int: use edge flow handler for edge interrupts
The driver uses level flow handler for both edge and level trigger types.
This creates a window where an edge triggered interrupt can be missed.
The following explanation applies for kernel prior to commit
d4dc0f90d243fb54cfbca6601c9a7c5a758e437f ("genirq: Allow
check_wakeup_irqs to notice level-triggered interrupts").
The edge flow handler sets the IRQS_PENDING flag if that interrupt was
disabled (IRQD_DISABLED flag set) and the genirq framework uses this
flag to:
1. Resend edge triggered interrupts
2. Abort suspend if it were a wakeup interrupt
The level flow handler does not set this flag as it is expected that a
level triggered interrupt will be active unless handled.
If the level flow handler is used for edge triggered interrupts, then we
miss the opportunity to set IRQS_PENDING flag and so we could miss
resending the interrupt or aborting suspend if the edge triggered
interrupt fires while it is disabled.
Change in commit d4dc0f90d243fb54cfbca6601c9a7c5a758e437f ("genirq:
Allow check_wakeup_irqs to notice level-triggered interrupts")
makes level flow handler set the IRQS_PENDING flag and solves this issue.
However, the qpnp-int driver is intended to be run on kernels without this
change.
Hence update the code to use edge flow handler for edge triggered
interrupts.
Change-Id: I9a99ecd1366a614fc372743f150e5a6d508db786
CRs-Fixed: 630034
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
diff --git a/drivers/spmi/qpnp-int.c b/drivers/spmi/qpnp-int.c
index 1b99c1a..c225f94 100644
--- a/drivers/spmi/qpnp-int.c
+++ b/drivers/spmi/qpnp-int.c
@@ -318,6 +318,11 @@
return rc;
}
+ if (flow_type & IRQ_TYPE_EDGE_BOTH)
+ __irq_set_handler_locked(d->irq, handle_edge_irq);
+ else
+ __irq_set_handler_locked(d->irq, handle_level_irq);
+
return 0;
}