msm: smd_tty: Check the device is open before scheduling tasklets
When the SMD tty device is closed, tasklets to perform read operation
is killed first and then the underlying SMD channel is closed. There
is a race condition where the tasklet gets rescuduled between these
two operations. So ensure that the device is open before scheduling
tasklets to avoid this race condition.
Change-Id: I80c4e1538a69b5b05c1aadb0f4b0905f96a90001
CRs-Fixed: 318764
Signed-off-by: Karthikeyan Ramasubramanian <kramasub@codeaurora.org>
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index 76a02b0..b9086e3 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -98,7 +98,15 @@
static void buf_req_retry(unsigned long param)
{
struct smd_tty_info *info = (struct smd_tty_info *)param;
- tasklet_hi_schedule(&info->tty_tsklt);
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->reset_lock, flags);
+ if (info->is_open) {
+ spin_unlock_irqrestore(&info->reset_lock, flags);
+ tasklet_hi_schedule(&info->tty_tsklt);
+ return;
+ }
+ spin_unlock_irqrestore(&info->reset_lock, flags);
}
static void smd_tty_read(unsigned long param)
@@ -163,6 +171,12 @@
switch (event) {
case SMD_EVENT_DATA:
+ spin_lock_irqsave(&info->reset_lock, flags);
+ if (!info->is_open) {
+ spin_unlock_irqrestore(&info->reset_lock, flags);
+ break;
+ }
+ spin_unlock_irqrestore(&info->reset_lock, flags);
/* There may be clients (tty framework) that are blocked
* waiting for space to write data, so if a possible read
* interrupt came in wake anyone waiting and disable the
@@ -390,8 +404,15 @@
static void smd_tty_unthrottle(struct tty_struct *tty)
{
struct smd_tty_info *info = tty->driver_data;
- tasklet_hi_schedule(&info->tty_tsklt);
- return;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->reset_lock, flags);
+ if (info->is_open) {
+ spin_unlock_irqrestore(&info->reset_lock, flags);
+ tasklet_hi_schedule(&info->tty_tsklt);
+ return;
+ }
+ spin_unlock_irqrestore(&info->reset_lock, flags);
}
/*