Commit c2ba38cd76df770a253f0cab4b6abe514c265a85
Committed by
Linus Torvalds
1 parent
a129909ca9
Exists in
master
and in
4 other branches
tty: relock riscom8 using port locks
Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 20 additions and 10 deletions Side-by-side Diff
drivers/char/riscom8.c
... | ... | @@ -919,14 +919,12 @@ |
919 | 919 | retval = 0; |
920 | 920 | add_wait_queue(&port->open_wait, &wait); |
921 | 921 | |
922 | - spin_lock_irqsave(&riscom_lock, flags); | |
923 | - | |
922 | + spin_lock_irqsave(&port->lock, flags); | |
924 | 923 | if (!tty_hung_up_p(filp)) |
925 | 924 | port->count--; |
926 | - | |
927 | - spin_unlock_irqrestore(&riscom_lock, flags); | |
928 | - | |
929 | 925 | port->blocked_open++; |
926 | + spin_unlock_irqrestore(&port->lock, flags); | |
927 | + | |
930 | 928 | while (1) { |
931 | 929 | |
932 | 930 | CD = tty_port_carrier_raised(port); |
933 | 931 | |
... | ... | @@ -950,13 +948,13 @@ |
950 | 948 | } |
951 | 949 | __set_current_state(TASK_RUNNING); |
952 | 950 | remove_wait_queue(&port->open_wait, &wait); |
951 | + spin_lock_irqsave(&port->lock, flags); | |
953 | 952 | if (!tty_hung_up_p(filp)) |
954 | 953 | port->count++; |
955 | 954 | port->blocked_open--; |
956 | - if (retval) | |
957 | - return retval; | |
958 | - | |
959 | - port->flags |= ASYNC_NORMAL_ACTIVE; | |
955 | + if (retval == 0) | |
956 | + port->flags |= ASYNC_NORMAL_ACTIVE; | |
957 | + spin_unlock_irqrestore(&port->lock, flags); | |
960 | 958 | return 0; |
961 | 959 | } |
962 | 960 | |
... | ... | @@ -1015,7 +1013,7 @@ |
1015 | 1013 | if (!port || rc_paranoia_check(port, tty->name, "close")) |
1016 | 1014 | return; |
1017 | 1015 | |
1018 | - spin_lock_irqsave(&riscom_lock, flags); | |
1016 | + spin_lock_irqsave(&port->port.lock, flags); | |
1019 | 1017 | |
1020 | 1018 | if (tty_hung_up_p(filp)) |
1021 | 1019 | goto out; |
... | ... | @@ -1041,6 +1039,7 @@ |
1041 | 1039 | * the line discipline to only process XON/XOFF characters. |
1042 | 1040 | */ |
1043 | 1041 | tty->closing = 1; |
1042 | + spin_unlock_irqrestore(&port->port.lock, flags); | |
1044 | 1043 | if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) |
1045 | 1044 | tty_wait_until_sent(tty, port->port.closing_wait); |
1046 | 1045 | /* |
... | ... | @@ -1049,6 +1048,8 @@ |
1049 | 1048 | * interrupt driver to stop checking the data ready bit in the |
1050 | 1049 | * line status register. |
1051 | 1050 | */ |
1051 | + | |
1052 | + spin_lock_irqsave(&riscom_lock, flags); | |
1052 | 1053 | port->IER &= ~IER_RXD; |
1053 | 1054 | if (port->port.flags & ASYNC_INITIALIZED) { |
1054 | 1055 | port->IER &= ~IER_TXRDY; |
1055 | 1056 | |
1056 | 1057 | |
1057 | 1058 | |
1058 | 1059 | |
1059 | 1060 | |
... | ... | @@ -1062,21 +1063,27 @@ |
1062 | 1063 | */ |
1063 | 1064 | timeout = jiffies + HZ; |
1064 | 1065 | while (port->IER & IER_TXEMPTY) { |
1066 | + spin_unlock_irqrestore(&riscom_lock, flags); | |
1065 | 1067 | msleep_interruptible(jiffies_to_msecs(port->timeout)); |
1068 | + spin_lock_irqsave(&riscom_lock, flags); | |
1066 | 1069 | if (time_after(jiffies, timeout)) |
1067 | 1070 | break; |
1068 | 1071 | } |
1069 | 1072 | } |
1070 | 1073 | rc_shutdown_port(tty, bp, port); |
1071 | 1074 | rc_flush_buffer(tty); |
1075 | + spin_unlock_irqrestore(&riscom_lock, flags); | |
1072 | 1076 | tty_ldisc_flush(tty); |
1073 | 1077 | |
1078 | + spin_lock_irqsave(&port->port.lock, flags); | |
1074 | 1079 | tty->closing = 0; |
1075 | 1080 | port->port.tty = NULL; |
1076 | 1081 | if (port->port.blocked_open) { |
1082 | + spin_unlock_irqrestore(&port->port.lock, flags); | |
1077 | 1083 | if (port->port.close_delay) |
1078 | 1084 | msleep_interruptible(jiffies_to_msecs(port->port.close_delay)); |
1079 | 1085 | wake_up_interruptible(&port->port.open_wait); |
1086 | + spin_lock_irqsave(&port->port.lock, flags); | |
1080 | 1087 | } |
1081 | 1088 | port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); |
1082 | 1089 | wake_up_interruptible(&port->port.close_wait); |
... | ... | @@ -1465,6 +1472,7 @@ |
1465 | 1472 | { |
1466 | 1473 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; |
1467 | 1474 | struct riscom_board *bp; |
1475 | + unsigned long flags; | |
1468 | 1476 | |
1469 | 1477 | if (rc_paranoia_check(port, tty->name, "rc_hangup")) |
1470 | 1478 | return; |
1471 | 1479 | |
... | ... | @@ -1472,10 +1480,12 @@ |
1472 | 1480 | bp = port_Board(port); |
1473 | 1481 | |
1474 | 1482 | rc_shutdown_port(tty, bp, port); |
1483 | + spin_lock_irqsave(&port->port.lock, flags); | |
1475 | 1484 | port->port.count = 0; |
1476 | 1485 | port->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
1477 | 1486 | port->port.tty = NULL; |
1478 | 1487 | wake_up_interruptible(&port->port.open_wait); |
1488 | + spin_unlock_irqrestore(&port->port.lock, flags); | |
1479 | 1489 | } |
1480 | 1490 | |
1481 | 1491 | static void rc_set_termios(struct tty_struct *tty, |