diff options
-rw-r--r-- | drivers/char/rocket.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 0e29a23ec4c5..79c3bc69165a 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
@@ -73,7 +73,6 @@ | |||
73 | #include <linux/tty_driver.h> | 73 | #include <linux/tty_driver.h> |
74 | #include <linux/tty_flip.h> | 74 | #include <linux/tty_flip.h> |
75 | #include <linux/serial.h> | 75 | #include <linux/serial.h> |
76 | #include <linux/smp_lock.h> | ||
77 | #include <linux/string.h> | 76 | #include <linux/string.h> |
78 | #include <linux/fcntl.h> | 77 | #include <linux/fcntl.h> |
79 | #include <linux/ptrace.h> | 78 | #include <linux/ptrace.h> |
@@ -1017,6 +1016,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1017 | if (tty_port_close_start(port, tty, filp) == 0) | 1016 | if (tty_port_close_start(port, tty, filp) == 0) |
1018 | return; | 1017 | return; |
1019 | 1018 | ||
1019 | mutex_lock(&port->mutex); | ||
1020 | cp = &info->channel; | 1020 | cp = &info->channel; |
1021 | /* | 1021 | /* |
1022 | * Before we drop DTR, make sure the UART transmitter | 1022 | * Before we drop DTR, make sure the UART transmitter |
@@ -1060,9 +1060,13 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1060 | info->xmit_buf = NULL; | 1060 | info->xmit_buf = NULL; |
1061 | } | 1061 | } |
1062 | } | 1062 | } |
1063 | spin_lock_irq(&port->lock); | ||
1063 | info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE); | 1064 | info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE); |
1064 | tty->closing = 0; | 1065 | tty->closing = 0; |
1066 | spin_unlock_irq(&port->lock); | ||
1067 | mutex_unlock(&port->mutex); | ||
1065 | tty_port_tty_set(port, NULL); | 1068 | tty_port_tty_set(port, NULL); |
1069 | |||
1066 | wake_up_interruptible(&port->close_wait); | 1070 | wake_up_interruptible(&port->close_wait); |
1067 | complete_all(&info->close_wait); | 1071 | complete_all(&info->close_wait); |
1068 | atomic_dec(&rp_num_ports_open); | 1072 | atomic_dec(&rp_num_ports_open); |
@@ -1210,11 +1214,13 @@ static int get_config(struct r_port *info, struct rocket_config __user *retinfo) | |||
1210 | if (!retinfo) | 1214 | if (!retinfo) |
1211 | return -EFAULT; | 1215 | return -EFAULT; |
1212 | memset(&tmp, 0, sizeof (tmp)); | 1216 | memset(&tmp, 0, sizeof (tmp)); |
1217 | mutex_lock(&info->port.mutex); | ||
1213 | tmp.line = info->line; | 1218 | tmp.line = info->line; |
1214 | tmp.flags = info->flags; | 1219 | tmp.flags = info->flags; |
1215 | tmp.close_delay = info->port.close_delay; | 1220 | tmp.close_delay = info->port.close_delay; |
1216 | tmp.closing_wait = info->port.closing_wait; | 1221 | tmp.closing_wait = info->port.closing_wait; |
1217 | tmp.port = rcktpt_io_addr[(info->line >> 5) & 3]; | 1222 | tmp.port = rcktpt_io_addr[(info->line >> 5) & 3]; |
1223 | mutex_unlock(&info->port.mutex); | ||
1218 | 1224 | ||
1219 | if (copy_to_user(retinfo, &tmp, sizeof (*retinfo))) | 1225 | if (copy_to_user(retinfo, &tmp, sizeof (*retinfo))) |
1220 | return -EFAULT; | 1226 | return -EFAULT; |
@@ -1229,10 +1235,13 @@ static int set_config(struct tty_struct *tty, struct r_port *info, | |||
1229 | if (copy_from_user(&new_serial, new_info, sizeof (new_serial))) | 1235 | if (copy_from_user(&new_serial, new_info, sizeof (new_serial))) |
1230 | return -EFAULT; | 1236 | return -EFAULT; |
1231 | 1237 | ||
1238 | mutex_lock(&info->port.mutex); | ||
1232 | if (!capable(CAP_SYS_ADMIN)) | 1239 | if (!capable(CAP_SYS_ADMIN)) |
1233 | { | 1240 | { |
1234 | if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) | 1241 | if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) { |
1242 | mutex_unlock(&info->port.mutex); | ||
1235 | return -EPERM; | 1243 | return -EPERM; |
1244 | } | ||
1236 | info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK)); | 1245 | info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK)); |
1237 | configure_r_port(tty, info, NULL); | 1246 | configure_r_port(tty, info, NULL); |
1238 | return 0; | 1247 | return 0; |
@@ -1250,6 +1259,7 @@ static int set_config(struct tty_struct *tty, struct r_port *info, | |||
1250 | tty->alt_speed = 230400; | 1259 | tty->alt_speed = 230400; |
1251 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) | 1260 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) |
1252 | tty->alt_speed = 460800; | 1261 | tty->alt_speed = 460800; |
1262 | mutex_unlock(&info->port.mutex); | ||
1253 | 1263 | ||
1254 | configure_r_port(tty, info, NULL); | 1264 | configure_r_port(tty, info, NULL); |
1255 | return 0; | 1265 | return 0; |
@@ -1325,8 +1335,6 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file, | |||
1325 | if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl")) | 1335 | if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl")) |
1326 | return -ENXIO; | 1336 | return -ENXIO; |
1327 | 1337 | ||
1328 | lock_kernel(); | ||
1329 | |||
1330 | switch (cmd) { | 1338 | switch (cmd) { |
1331 | case RCKP_GET_STRUCT: | 1339 | case RCKP_GET_STRUCT: |
1332 | if (copy_to_user(argp, info, sizeof (struct r_port))) | 1340 | if (copy_to_user(argp, info, sizeof (struct r_port))) |
@@ -1350,7 +1358,6 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file, | |||
1350 | default: | 1358 | default: |
1351 | ret = -ENOIOCTLCMD; | 1359 | ret = -ENOIOCTLCMD; |
1352 | } | 1360 | } |
1353 | unlock_kernel(); | ||
1354 | return ret; | 1361 | return ret; |
1355 | } | 1362 | } |
1356 | 1363 | ||
@@ -1471,7 +1478,6 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1471 | jiffies); | 1478 | jiffies); |
1472 | printk(KERN_INFO "cps=%d...\n", info->cps); | 1479 | printk(KERN_INFO "cps=%d...\n", info->cps); |
1473 | #endif | 1480 | #endif |
1474 | lock_kernel(); | ||
1475 | while (1) { | 1481 | while (1) { |
1476 | txcnt = sGetTxCnt(cp); | 1482 | txcnt = sGetTxCnt(cp); |
1477 | if (!txcnt) { | 1483 | if (!txcnt) { |
@@ -1499,7 +1505,6 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1499 | break; | 1505 | break; |
1500 | } | 1506 | } |
1501 | __set_current_state(TASK_RUNNING); | 1507 | __set_current_state(TASK_RUNNING); |
1502 | unlock_kernel(); | ||
1503 | #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT | 1508 | #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT |
1504 | printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies); | 1509 | printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies); |
1505 | #endif | 1510 | #endif |
@@ -1512,6 +1517,7 @@ static void rp_hangup(struct tty_struct *tty) | |||
1512 | { | 1517 | { |
1513 | CHANNEL_t *cp; | 1518 | CHANNEL_t *cp; |
1514 | struct r_port *info = tty->driver_data; | 1519 | struct r_port *info = tty->driver_data; |
1520 | unsigned long flags; | ||
1515 | 1521 | ||
1516 | if (rocket_paranoia_check(info, "rp_hangup")) | 1522 | if (rocket_paranoia_check(info, "rp_hangup")) |
1517 | return; | 1523 | return; |
@@ -1520,11 +1526,15 @@ static void rp_hangup(struct tty_struct *tty) | |||
1520 | printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line); | 1526 | printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line); |
1521 | #endif | 1527 | #endif |
1522 | rp_flush_buffer(tty); | 1528 | rp_flush_buffer(tty); |
1523 | if (info->port.flags & ASYNC_CLOSING) | 1529 | spin_lock_irqsave(&info->port.lock, flags); |
1530 | if (info->port.flags & ASYNC_CLOSING) { | ||
1531 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
1524 | return; | 1532 | return; |
1533 | } | ||
1525 | if (info->port.count) | 1534 | if (info->port.count) |
1526 | atomic_dec(&rp_num_ports_open); | 1535 | atomic_dec(&rp_num_ports_open); |
1527 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); | 1536 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); |
1537 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
1528 | 1538 | ||
1529 | tty_port_hangup(&info->port); | 1539 | tty_port_hangup(&info->port); |
1530 | 1540 | ||
@@ -1535,7 +1545,7 @@ static void rp_hangup(struct tty_struct *tty) | |||
1535 | sDisCTSFlowCtl(cp); | 1545 | sDisCTSFlowCtl(cp); |
1536 | sDisTxSoftFlowCtl(cp); | 1546 | sDisTxSoftFlowCtl(cp); |
1537 | sClrTxXOFF(cp); | 1547 | sClrTxXOFF(cp); |
1538 | info->port.flags &= ~ASYNC_INITIALIZED; | 1548 | clear_bit(ASYNCB_INITIALIZED, &info->port.flags); |
1539 | 1549 | ||
1540 | wake_up_interruptible(&info->port.open_wait); | 1550 | wake_up_interruptible(&info->port.open_wait); |
1541 | } | 1551 | } |