diff options
author | Alan Cox <alan@linux.intel.com> | 2010-06-01 22:52:50 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 13:47:41 -0700 |
commit | a360fae67bc173942f620d44d1b23cfb5ccaaf96 (patch) | |
tree | be45781b50fb44586694e265d9ec113e481809f5 /drivers/char | |
parent | 4287341d4dba27ef8048f589e3c0bc683c9f2017 (diff) | |
download | op-kernel-dev-a360fae67bc173942f620d44d1b23cfb5ccaaf96.zip op-kernel-dev-a360fae67bc173942f620d44d1b23cfb5ccaaf96.tar.gz |
synclink: reworking locking a bit
Use the port mutex and port lock to fix the various races. The locking
still isn't totally consistent but its better than before. Wants switching
to the port helpers.
Signed-off-by: Alan Cox <alan@linux.intel.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/synclink_gt.c | 12 | ||||
-rw-r--r-- | drivers/char/synclinkmp.c | 9 |
2 files changed, 19 insertions, 2 deletions
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 3c7ac6a..5a602eb 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -675,12 +675,14 @@ static int open(struct tty_struct *tty, struct file *filp) goto cleanup; } + mutex_lock(&info->port.mutex); info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; spin_lock_irqsave(&info->netlock, flags); if (info->netcount) { retval = -EBUSY; spin_unlock_irqrestore(&info->netlock, flags); + mutex_unlock(&info->port.mutex); goto cleanup; } info->port.count++; @@ -692,7 +694,7 @@ static int open(struct tty_struct *tty, struct file *filp) if (retval < 0) goto cleanup; } - + mutex_unlock(&info->port.mutex); retval = block_til_ready(tty, filp, info); if (retval) { DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval)); @@ -724,12 +726,14 @@ static void close(struct tty_struct *tty, struct file *filp) if (tty_port_close_start(&info->port, tty, filp) == 0) goto cleanup; + mutex_lock(&info->port.mutex); if (info->port.flags & ASYNC_INITIALIZED) wait_until_sent(tty, info->timeout); flush_buffer(tty); tty_ldisc_flush(tty); shutdown(info); + mutex_unlock(&info->port.mutex); tty_port_close_end(&info->port, tty); info->port.tty = NULL; @@ -740,17 +744,23 @@ cleanup: static void hangup(struct tty_struct *tty) { struct slgt_info *info = tty->driver_data; + unsigned long flags; if (sanity_check(info, tty->name, "hangup")) return; DBGINFO(("%s hangup\n", info->device_name)); flush_buffer(tty); + + mutex_lock(&info->port.mutex); shutdown(info); + spin_lock_irqsave(&info->port.lock, flags); info->port.count = 0; info->port.flags &= ~ASYNC_NORMAL_ACTIVE; info->port.tty = NULL; + spin_unlock_irqrestore(&info->port.lock, flags); + mutex_unlock(&info->port.mutex); wake_up_interruptible(&info->port.open_wait); } diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 8da976b..ac447c7 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -812,13 +812,15 @@ static void close(struct tty_struct *tty, struct file *filp) if (tty_port_close_start(&info->port, tty, filp) == 0) goto cleanup; - + + mutex_lock(&info->port.mutex); if (info->port.flags & ASYNC_INITIALIZED) wait_until_sent(tty, info->timeout); flush_buffer(tty); tty_ldisc_flush(tty); shutdown(info); + mutex_unlock(&info->port.mutex); tty_port_close_end(&info->port, tty); info->port.tty = NULL; @@ -834,6 +836,7 @@ cleanup: static void hangup(struct tty_struct *tty) { SLMP_INFO *info = tty->driver_data; + unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):%s hangup()\n", @@ -842,12 +845,16 @@ static void hangup(struct tty_struct *tty) if (sanity_check(info, tty->name, "hangup")) return; + mutex_lock(&info->port.mutex); flush_buffer(tty); shutdown(info); + spin_lock_irqsave(&info->port.lock, flags); info->port.count = 0; info->port.flags &= ~ASYNC_NORMAL_ACTIVE; info->port.tty = NULL; + spin_unlock_irqrestore(&info->port.lock, flags); + mutex_unlock(&info->port.mutex); wake_up_interruptible(&info->port.open_wait); } |