]> git.karo-electronics.de Git - linux-beck.git/commitdiff
tty: synclink: avoid sleep_on race
authorArnd Bergmann <arnd@arndb.de>
Thu, 2 Jan 2014 12:07:40 +0000 (13:07 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 8 Jan 2014 01:05:21 +0000 (17:05 -0800)
The four variants of the synclink driver use the same code in their
open() callback to wait for a port in process of being closed,
using interruptible_sleep_on, which is racy and going away soon.

Making things worse, these functions hold the BTM while doing so,
which means that if we ever enter this code path, we cannot actually
continue since the other thread that is in process of closing the
port can no longer get the BTM.

This addresses both issues by using wait_event_interruptible_tty()
instead.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/char/pcmcia/synclink_cs.c
drivers/tty/synclink.c
drivers/tty/synclink_gt.c
drivers/tty/synclinkmp.c

index d39cca659a3f4839233475d32a6d63c16553209d..8320abd1ef1473ddfda6820c8a6bcaa689f73824 100644 (file)
@@ -2511,8 +2511,8 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
 
        /* If port is closing, signal caller to try again */
        if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING){
-               if (port->flags & ASYNC_CLOSING)
-                       interruptible_sleep_on(&port->close_wait);
+               wait_event_interruptible_tty(tty, port->close_wait,
+                                            !(port->flags & ASYNC_CLOSING));
                retval = ((port->flags & ASYNC_HUP_NOTIFY) ?
                        -EAGAIN : -ERESTARTSYS);
                goto cleanup;
index e1ce141bad5e2995afb98ee3fd9719c1558f03f8..5ae14b46cce0709aab95904ca0082ac3a29f7d7a 100644 (file)
@@ -3404,8 +3404,8 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
 
        /* If port is closing, signal caller to try again */
        if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
-               if (info->port.flags & ASYNC_CLOSING)
-                       interruptible_sleep_on(&info->port.close_wait);
+               wait_event_interruptible_tty(tty, info->port.close_wait,
+                                    !(info->port.flags & ASYNC_CLOSING));
                retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
                        -EAGAIN : -ERESTARTSYS);
                goto cleanup;
index 1abf946463f664522d1721a1537a4fdba9d45c25..c359a91f7346071396e7ba0ec9d3f4bb4a381772 100644 (file)
@@ -674,8 +674,8 @@ static int open(struct tty_struct *tty, struct file *filp)
 
        /* If port is closing, signal caller to try again */
        if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
-               if (info->port.flags & ASYNC_CLOSING)
-                       interruptible_sleep_on(&info->port.close_wait);
+               wait_event_interruptible_tty(tty, info->port.close_wait,
+                                            !(info->port.flags & ASYNC_CLOSING));
                retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
                        -EAGAIN : -ERESTARTSYS);
                goto cleanup;
index dc6e96996ead4796eace1ba3bb4b61232f132302..144202eef6fe3a3a9bda7e5dc4527a71201bd6f5 100644 (file)
@@ -754,8 +754,8 @@ static int open(struct tty_struct *tty, struct file *filp)
 
        /* If port is closing, signal caller to try again */
        if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
-               if (info->port.flags & ASYNC_CLOSING)
-                       interruptible_sleep_on(&info->port.close_wait);
+               wait_event_interruptible_tty(tty, info->port.close_wait,
+                                            !(info->port.flags & ASYNC_CLOSING));
                retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
                        -EAGAIN : -ERESTARTSYS);
                goto cleanup;