msm: bam_dmux: change write_lock acquire mode
Change writelock() to write_trylock_irqsave(). The irqsave prevents
deadlock when an interrupt is handled while the write_lock is held, and
the irq attempts to grab the read_lock. The trylock prevents deadlock
when ul_timeout() is scheduled while the read_lock is held thus the
write_lock cannot be grabbed and irqsave prevents scheduling.
Change-Id: I19e7c995e645d447e93559a6fbb10ff08ee80815
CRs-Fixed: 319109
Signed-off-by: Jeffrey Hugo <jhugo@codeaurora.org>
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index c70e1b5..8ebac5b 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -877,9 +877,17 @@
static void ul_timeout(struct work_struct *work)
{
+ unsigned long flags;
+ int ret;
+
if (in_global_reset)
return;
- write_lock(&ul_wakeup_lock);
+ ret = write_trylock_irqsave(&ul_wakeup_lock, flags);
+ if (!ret) { /* failed to grab lock, reschedule and bail */
+ schedule_delayed_work(&ul_timeout_work,
+ msecs_to_jiffies(UL_TIMEOUT_DELAY));
+ return;
+ }
if (ul_packet_written) {
ul_packet_written = 0;
schedule_delayed_work(&ul_timeout_work,
@@ -889,7 +897,7 @@
bam_is_connected = 0;
notify_all(BAM_DMUX_UL_DISCONNECTED, (unsigned long)(NULL));
}
- write_unlock(&ul_wakeup_lock);
+ write_unlock_irqrestore(&ul_wakeup_lock, flags);
}
static void ul_wakeup(void)
{