msm: smd_pkt: Fix wakelock concurrency issue
In failure conditions, some clients violate the SMD PKT restriction of
single-threaded access resulting in overlapping open requests which
corrupt the wakelock list.
Move the wakelock initialization into the channel mutex to prevent
concurrent access from corrupting the wakelock.
CRs-Fixed: 374644
Change-Id: Idfdfc07fa69258d29154c4fce3fbcf2f000e63d6
Signed-off-by: Eric Holmberg <eholmber@codeaurora.org>
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index f5f76f7..fdbc387 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -767,14 +767,14 @@
}
D_STATUS("Begin %s on smd_pkt_dev id:%d\n", __func__, smd_pkt_devp->i);
- wake_lock_init(&smd_pkt_devp->pa_wake_lock, WAKE_LOCK_SUSPEND,
- smd_pkt_dev_name[smd_pkt_devp->i]);
- INIT_WORK(&smd_pkt_devp->packet_arrival_work, packet_arrival_worker);
-
file->private_data = smd_pkt_devp;
mutex_lock(&smd_pkt_devp->ch_lock);
if (smd_pkt_devp->ch == 0) {
+ wake_lock_init(&smd_pkt_devp->pa_wake_lock, WAKE_LOCK_SUSPEND,
+ smd_pkt_dev_name[smd_pkt_devp->i]);
+ INIT_WORK(&smd_pkt_devp->packet_arrival_work,
+ packet_arrival_worker);
init_completion(&smd_pkt_devp->ch_allocated);
smd_pkt_devp->driver.probe = smd_pkt_dummy_probe;
scnprintf(smd_pkt_devp->pdriver_name, PDRIVER_NAME_MAX_SIZE,
@@ -881,10 +881,11 @@
smd_pkt_devp->driver.probe = NULL;
}
out:
+ if (!smd_pkt_devp->ch)
+ wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
+
mutex_unlock(&smd_pkt_devp->ch_lock);
- if (r < 0)
- wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
return r;
}