diff options
Diffstat (limited to 'drivers/char/mxser.c')
-rw-r--r-- | drivers/char/mxser.c | 248 |
1 files changed, 109 insertions, 139 deletions
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 5e28d39b9e81..3d923065d9a2 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
24 | #include <linux/signal.h> | 24 | #include <linux/signal.h> |
25 | #include <linux/sched.h> | 25 | #include <linux/sched.h> |
26 | #include <linux/smp_lock.h> | ||
27 | #include <linux/timer.h> | 26 | #include <linux/timer.h> |
28 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
29 | #include <linux/tty.h> | 28 | #include <linux/tty.h> |
@@ -856,9 +855,9 @@ static void mxser_check_modem_status(struct tty_struct *tty, | |||
856 | } | 855 | } |
857 | } | 856 | } |
858 | 857 | ||
859 | static int mxser_startup(struct tty_struct *tty) | 858 | static int mxser_activate(struct tty_port *port, struct tty_struct *tty) |
860 | { | 859 | { |
861 | struct mxser_port *info = tty->driver_data; | 860 | struct mxser_port *info = container_of(port, struct mxser_port, port); |
862 | unsigned long page; | 861 | unsigned long page; |
863 | unsigned long flags; | 862 | unsigned long flags; |
864 | 863 | ||
@@ -868,22 +867,13 @@ static int mxser_startup(struct tty_struct *tty) | |||
868 | 867 | ||
869 | spin_lock_irqsave(&info->slock, flags); | 868 | spin_lock_irqsave(&info->slock, flags); |
870 | 869 | ||
871 | if (info->port.flags & ASYNC_INITIALIZED) { | ||
872 | free_page(page); | ||
873 | spin_unlock_irqrestore(&info->slock, flags); | ||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | if (!info->ioaddr || !info->type) { | 870 | if (!info->ioaddr || !info->type) { |
878 | set_bit(TTY_IO_ERROR, &tty->flags); | 871 | set_bit(TTY_IO_ERROR, &tty->flags); |
879 | free_page(page); | 872 | free_page(page); |
880 | spin_unlock_irqrestore(&info->slock, flags); | 873 | spin_unlock_irqrestore(&info->slock, flags); |
881 | return 0; | 874 | return 0; |
882 | } | 875 | } |
883 | if (info->port.xmit_buf) | 876 | info->port.xmit_buf = (unsigned char *) page; |
884 | free_page(page); | ||
885 | else | ||
886 | info->port.xmit_buf = (unsigned char *) page; | ||
887 | 877 | ||
888 | /* | 878 | /* |
889 | * Clear the FIFO buffers and disable them | 879 | * Clear the FIFO buffers and disable them |
@@ -951,24 +941,19 @@ static int mxser_startup(struct tty_struct *tty) | |||
951 | * and set the speed of the serial port | 941 | * and set the speed of the serial port |
952 | */ | 942 | */ |
953 | mxser_change_speed(tty, NULL); | 943 | mxser_change_speed(tty, NULL); |
954 | info->port.flags |= ASYNC_INITIALIZED; | ||
955 | spin_unlock_irqrestore(&info->slock, flags); | 944 | spin_unlock_irqrestore(&info->slock, flags); |
956 | 945 | ||
957 | return 0; | 946 | return 0; |
958 | } | 947 | } |
959 | 948 | ||
960 | /* | 949 | /* |
961 | * This routine will shutdown a serial port; interrupts maybe disabled, and | 950 | * This routine will shutdown a serial port |
962 | * DTR is dropped if the hangup on close termio flag is on. | ||
963 | */ | 951 | */ |
964 | static void mxser_shutdown(struct tty_struct *tty) | 952 | static void mxser_shutdown_port(struct tty_port *port) |
965 | { | 953 | { |
966 | struct mxser_port *info = tty->driver_data; | 954 | struct mxser_port *info = container_of(port, struct mxser_port, port); |
967 | unsigned long flags; | 955 | unsigned long flags; |
968 | 956 | ||
969 | if (!(info->port.flags & ASYNC_INITIALIZED)) | ||
970 | return; | ||
971 | |||
972 | spin_lock_irqsave(&info->slock, flags); | 957 | spin_lock_irqsave(&info->slock, flags); |
973 | 958 | ||
974 | /* | 959 | /* |
@@ -978,7 +963,7 @@ static void mxser_shutdown(struct tty_struct *tty) | |||
978 | wake_up_interruptible(&info->port.delta_msr_wait); | 963 | wake_up_interruptible(&info->port.delta_msr_wait); |
979 | 964 | ||
980 | /* | 965 | /* |
981 | * Free the IRQ, if necessary | 966 | * Free the xmit buffer, if necessary |
982 | */ | 967 | */ |
983 | if (info->port.xmit_buf) { | 968 | if (info->port.xmit_buf) { |
984 | free_page((unsigned long) info->port.xmit_buf); | 969 | free_page((unsigned long) info->port.xmit_buf); |
@@ -988,10 +973,6 @@ static void mxser_shutdown(struct tty_struct *tty) | |||
988 | info->IER = 0; | 973 | info->IER = 0; |
989 | outb(0x00, info->ioaddr + UART_IER); | 974 | outb(0x00, info->ioaddr + UART_IER); |
990 | 975 | ||
991 | if (tty->termios->c_cflag & HUPCL) | ||
992 | info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS); | ||
993 | outb(info->MCR, info->ioaddr + UART_MCR); | ||
994 | |||
995 | /* clear Rx/Tx FIFO's */ | 976 | /* clear Rx/Tx FIFO's */ |
996 | if (info->board->chip_flag) | 977 | if (info->board->chip_flag) |
997 | outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | | 978 | outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | |
@@ -1004,9 +985,6 @@ static void mxser_shutdown(struct tty_struct *tty) | |||
1004 | /* read data port to reset things */ | 985 | /* read data port to reset things */ |
1005 | (void) inb(info->ioaddr + UART_RX); | 986 | (void) inb(info->ioaddr + UART_RX); |
1006 | 987 | ||
1007 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
1008 | |||
1009 | info->port.flags &= ~ASYNC_INITIALIZED; | ||
1010 | 988 | ||
1011 | if (info->board->chip_flag) | 989 | if (info->board->chip_flag) |
1012 | SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr); | 990 | SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr); |
@@ -1023,8 +1001,7 @@ static void mxser_shutdown(struct tty_struct *tty) | |||
1023 | static int mxser_open(struct tty_struct *tty, struct file *filp) | 1001 | static int mxser_open(struct tty_struct *tty, struct file *filp) |
1024 | { | 1002 | { |
1025 | struct mxser_port *info; | 1003 | struct mxser_port *info; |
1026 | unsigned long flags; | 1004 | int line; |
1027 | int retval, line; | ||
1028 | 1005 | ||
1029 | line = tty->index; | 1006 | line = tty->index; |
1030 | if (line == MXSER_PORTS) | 1007 | if (line == MXSER_PORTS) |
@@ -1035,23 +1012,7 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) | |||
1035 | if (!info->ioaddr) | 1012 | if (!info->ioaddr) |
1036 | return -ENODEV; | 1013 | return -ENODEV; |
1037 | 1014 | ||
1038 | tty->driver_data = info; | 1015 | return tty_port_open(&info->port, tty, filp); |
1039 | tty_port_tty_set(&info->port, tty); | ||
1040 | /* | ||
1041 | * Start up serial port | ||
1042 | */ | ||
1043 | spin_lock_irqsave(&info->port.lock, flags); | ||
1044 | info->port.count++; | ||
1045 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
1046 | retval = mxser_startup(tty); | ||
1047 | if (retval) | ||
1048 | return retval; | ||
1049 | |||
1050 | retval = tty_port_block_til_ready(&info->port, tty, filp); | ||
1051 | if (retval) | ||
1052 | return retval; | ||
1053 | |||
1054 | return 0; | ||
1055 | } | 1016 | } |
1056 | 1017 | ||
1057 | static void mxser_flush_buffer(struct tty_struct *tty) | 1018 | static void mxser_flush_buffer(struct tty_struct *tty) |
@@ -1075,19 +1036,11 @@ static void mxser_flush_buffer(struct tty_struct *tty) | |||
1075 | } | 1036 | } |
1076 | 1037 | ||
1077 | 1038 | ||
1078 | static void mxser_close_port(struct tty_struct *tty, struct tty_port *port) | 1039 | static void mxser_close_port(struct tty_port *port) |
1079 | { | 1040 | { |
1080 | struct mxser_port *info = container_of(port, struct mxser_port, port); | 1041 | struct mxser_port *info = container_of(port, struct mxser_port, port); |
1081 | unsigned long timeout; | 1042 | unsigned long timeout; |
1082 | /* | 1043 | /* |
1083 | * Save the termios structure, since this port may have | ||
1084 | * separate termios for callout and dialin. | ||
1085 | * | ||
1086 | * FIXME: Can this go ? | ||
1087 | */ | ||
1088 | if (port->flags & ASYNC_NORMAL_ACTIVE) | ||
1089 | info->normal_termios = *tty->termios; | ||
1090 | /* | ||
1091 | * At this point we stop accepting input. To do this, we | 1044 | * At this point we stop accepting input. To do this, we |
1092 | * disable the receive line status interrupts, and tell the | 1045 | * disable the receive line status interrupts, and tell the |
1093 | * interrupt driver to stop checking the data ready bit in the | 1046 | * interrupt driver to stop checking the data ready bit in the |
@@ -1097,22 +1050,18 @@ static void mxser_close_port(struct tty_struct *tty, struct tty_port *port) | |||
1097 | if (info->board->chip_flag) | 1050 | if (info->board->chip_flag) |
1098 | info->IER &= ~MOXA_MUST_RECV_ISR; | 1051 | info->IER &= ~MOXA_MUST_RECV_ISR; |
1099 | 1052 | ||
1100 | if (port->flags & ASYNC_INITIALIZED) { | 1053 | outb(info->IER, info->ioaddr + UART_IER); |
1101 | outb(info->IER, info->ioaddr + UART_IER); | 1054 | /* |
1102 | /* | 1055 | * Before we drop DTR, make sure the UART transmitter |
1103 | * Before we drop DTR, make sure the UART transmitter | 1056 | * has completely drained; this is especially |
1104 | * has completely drained; this is especially | 1057 | * important if there is a transmit FIFO! |
1105 | * important if there is a transmit FIFO! | 1058 | */ |
1106 | */ | 1059 | timeout = jiffies + HZ; |
1107 | timeout = jiffies + HZ; | 1060 | while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) { |
1108 | while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) { | 1061 | schedule_timeout_interruptible(5); |
1109 | schedule_timeout_interruptible(5); | 1062 | if (time_after(jiffies, timeout)) |
1110 | if (time_after(jiffies, timeout)) | 1063 | break; |
1111 | break; | ||
1112 | } | ||
1113 | } | 1064 | } |
1114 | mxser_shutdown(tty); | ||
1115 | |||
1116 | } | 1065 | } |
1117 | 1066 | ||
1118 | /* | 1067 | /* |
@@ -1130,8 +1079,12 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) | |||
1130 | return; | 1079 | return; |
1131 | if (tty_port_close_start(port, tty, filp) == 0) | 1080 | if (tty_port_close_start(port, tty, filp) == 0) |
1132 | return; | 1081 | return; |
1133 | mxser_close_port(tty, port); | 1082 | mutex_lock(&port->mutex); |
1083 | mxser_close_port(port); | ||
1134 | mxser_flush_buffer(tty); | 1084 | mxser_flush_buffer(tty); |
1085 | mxser_shutdown_port(port); | ||
1086 | clear_bit(ASYNCB_INITIALIZED, &port->flags); | ||
1087 | mutex_unlock(&port->mutex); | ||
1135 | /* Right now the tty_port set is done outside of the close_end helper | 1088 | /* Right now the tty_port set is done outside of the close_end helper |
1136 | as we don't yet have everyone using refcounts */ | 1089 | as we don't yet have everyone using refcounts */ |
1137 | tty_port_close_end(port, tty); | 1090 | tty_port_close_end(port, tty); |
@@ -1275,6 +1228,7 @@ static int mxser_set_serial_info(struct tty_struct *tty, | |||
1275 | struct serial_struct __user *new_info) | 1228 | struct serial_struct __user *new_info) |
1276 | { | 1229 | { |
1277 | struct mxser_port *info = tty->driver_data; | 1230 | struct mxser_port *info = tty->driver_data; |
1231 | struct tty_port *port = &info->port; | ||
1278 | struct serial_struct new_serial; | 1232 | struct serial_struct new_serial; |
1279 | speed_t baud; | 1233 | speed_t baud; |
1280 | unsigned long sl_flags; | 1234 | unsigned long sl_flags; |
@@ -1290,7 +1244,7 @@ static int mxser_set_serial_info(struct tty_struct *tty, | |||
1290 | new_serial.port != info->ioaddr) | 1244 | new_serial.port != info->ioaddr) |
1291 | return -EINVAL; | 1245 | return -EINVAL; |
1292 | 1246 | ||
1293 | flags = info->port.flags & ASYNC_SPD_MASK; | 1247 | flags = port->flags & ASYNC_SPD_MASK; |
1294 | 1248 | ||
1295 | if (!capable(CAP_SYS_ADMIN)) { | 1249 | if (!capable(CAP_SYS_ADMIN)) { |
1296 | if ((new_serial.baud_base != info->baud_base) || | 1250 | if ((new_serial.baud_base != info->baud_base) || |
@@ -1304,16 +1258,17 @@ static int mxser_set_serial_info(struct tty_struct *tty, | |||
1304 | * OK, past this point, all the error checking has been done. | 1258 | * OK, past this point, all the error checking has been done. |
1305 | * At this point, we start making changes..... | 1259 | * At this point, we start making changes..... |
1306 | */ | 1260 | */ |
1307 | info->port.flags = ((info->port.flags & ~ASYNC_FLAGS) | | 1261 | port->flags = ((port->flags & ~ASYNC_FLAGS) | |
1308 | (new_serial.flags & ASYNC_FLAGS)); | 1262 | (new_serial.flags & ASYNC_FLAGS)); |
1309 | info->port.close_delay = new_serial.close_delay * HZ / 100; | 1263 | port->close_delay = new_serial.close_delay * HZ / 100; |
1310 | info->port.closing_wait = new_serial.closing_wait * HZ / 100; | 1264 | port->closing_wait = new_serial.closing_wait * HZ / 100; |
1311 | tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) | 1265 | tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
1312 | ? 1 : 0; | 1266 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && |
1313 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && | ||
1314 | (new_serial.baud_base != info->baud_base || | 1267 | (new_serial.baud_base != info->baud_base || |
1315 | new_serial.custom_divisor != | 1268 | new_serial.custom_divisor != |
1316 | info->custom_divisor)) { | 1269 | info->custom_divisor)) { |
1270 | if (new_serial.custom_divisor == 0) | ||
1271 | return -EINVAL; | ||
1317 | baud = new_serial.baud_base / new_serial.custom_divisor; | 1272 | baud = new_serial.baud_base / new_serial.custom_divisor; |
1318 | tty_encode_baud_rate(tty, baud, baud); | 1273 | tty_encode_baud_rate(tty, baud, baud); |
1319 | } | 1274 | } |
@@ -1323,15 +1278,17 @@ static int mxser_set_serial_info(struct tty_struct *tty, | |||
1323 | 1278 | ||
1324 | process_txrx_fifo(info); | 1279 | process_txrx_fifo(info); |
1325 | 1280 | ||
1326 | if (info->port.flags & ASYNC_INITIALIZED) { | 1281 | if (test_bit(ASYNCB_INITIALIZED, &port->flags)) { |
1327 | if (flags != (info->port.flags & ASYNC_SPD_MASK)) { | 1282 | if (flags != (port->flags & ASYNC_SPD_MASK)) { |
1328 | spin_lock_irqsave(&info->slock, sl_flags); | 1283 | spin_lock_irqsave(&info->slock, sl_flags); |
1329 | mxser_change_speed(tty, NULL); | 1284 | mxser_change_speed(tty, NULL); |
1330 | spin_unlock_irqrestore(&info->slock, sl_flags); | 1285 | spin_unlock_irqrestore(&info->slock, sl_flags); |
1331 | } | 1286 | } |
1332 | } else | 1287 | } else { |
1333 | retval = mxser_startup(tty); | 1288 | retval = mxser_activate(port, tty); |
1334 | 1289 | if (retval == 0) | |
1290 | set_bit(ASYNCB_INITIALIZED, &port->flags); | ||
1291 | } | ||
1335 | return retval; | 1292 | return retval; |
1336 | } | 1293 | } |
1337 | 1294 | ||
@@ -1520,7 +1477,8 @@ static int __init mxser_read_register(int port, unsigned short *regs) | |||
1520 | 1477 | ||
1521 | static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | 1478 | static int mxser_ioctl_special(unsigned int cmd, void __user *argp) |
1522 | { | 1479 | { |
1523 | struct mxser_port *port; | 1480 | struct mxser_port *ip; |
1481 | struct tty_port *port; | ||
1524 | struct tty_struct *tty; | 1482 | struct tty_struct *tty; |
1525 | int result, status; | 1483 | int result, status; |
1526 | unsigned int i, j; | 1484 | unsigned int i, j; |
@@ -1536,38 +1494,39 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1536 | 1494 | ||
1537 | case MOXA_CHKPORTENABLE: | 1495 | case MOXA_CHKPORTENABLE: |
1538 | result = 0; | 1496 | result = 0; |
1539 | lock_kernel(); | ||
1540 | for (i = 0; i < MXSER_BOARDS; i++) | 1497 | for (i = 0; i < MXSER_BOARDS; i++) |
1541 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) | 1498 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) |
1542 | if (mxser_boards[i].ports[j].ioaddr) | 1499 | if (mxser_boards[i].ports[j].ioaddr) |
1543 | result |= (1 << i); | 1500 | result |= (1 << i); |
1544 | unlock_kernel(); | ||
1545 | return put_user(result, (unsigned long __user *)argp); | 1501 | return put_user(result, (unsigned long __user *)argp); |
1546 | case MOXA_GETDATACOUNT: | 1502 | case MOXA_GETDATACOUNT: |
1547 | lock_kernel(); | 1503 | /* The receive side is locked by port->slock but it isn't |
1504 | clear that an exact snapshot is worth copying here */ | ||
1548 | if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) | 1505 | if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) |
1549 | ret = -EFAULT; | 1506 | ret = -EFAULT; |
1550 | unlock_kernel(); | ||
1551 | return ret; | 1507 | return ret; |
1552 | case MOXA_GETMSTATUS: { | 1508 | case MOXA_GETMSTATUS: { |
1553 | struct mxser_mstatus ms, __user *msu = argp; | 1509 | struct mxser_mstatus ms, __user *msu = argp; |
1554 | lock_kernel(); | ||
1555 | for (i = 0; i < MXSER_BOARDS; i++) | 1510 | for (i = 0; i < MXSER_BOARDS; i++) |
1556 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { | 1511 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { |
1557 | port = &mxser_boards[i].ports[j]; | 1512 | ip = &mxser_boards[i].ports[j]; |
1513 | port = &ip->port; | ||
1558 | memset(&ms, 0, sizeof(ms)); | 1514 | memset(&ms, 0, sizeof(ms)); |
1559 | 1515 | ||
1560 | if (!port->ioaddr) | 1516 | mutex_lock(&port->mutex); |
1517 | if (!ip->ioaddr) | ||
1561 | goto copy; | 1518 | goto copy; |
1562 | 1519 | ||
1563 | tty = tty_port_tty_get(&port->port); | 1520 | tty = tty_port_tty_get(port); |
1564 | 1521 | ||
1565 | if (!tty || !tty->termios) | 1522 | if (!tty || !tty->termios) |
1566 | ms.cflag = port->normal_termios.c_cflag; | 1523 | ms.cflag = ip->normal_termios.c_cflag; |
1567 | else | 1524 | else |
1568 | ms.cflag = tty->termios->c_cflag; | 1525 | ms.cflag = tty->termios->c_cflag; |
1569 | tty_kref_put(tty); | 1526 | tty_kref_put(tty); |
1570 | status = inb(port->ioaddr + UART_MSR); | 1527 | spin_lock_irq(&ip->slock); |
1528 | status = inb(ip->ioaddr + UART_MSR); | ||
1529 | spin_unlock_irq(&ip->slock); | ||
1571 | if (status & UART_MSR_DCD) | 1530 | if (status & UART_MSR_DCD) |
1572 | ms.dcd = 1; | 1531 | ms.dcd = 1; |
1573 | if (status & UART_MSR_DSR) | 1532 | if (status & UART_MSR_DSR) |
@@ -1575,13 +1534,11 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1575 | if (status & UART_MSR_CTS) | 1534 | if (status & UART_MSR_CTS) |
1576 | ms.cts = 1; | 1535 | ms.cts = 1; |
1577 | copy: | 1536 | copy: |
1578 | if (copy_to_user(msu, &ms, sizeof(ms))) { | 1537 | mutex_unlock(&port->mutex); |
1579 | unlock_kernel(); | 1538 | if (copy_to_user(msu, &ms, sizeof(ms))) |
1580 | return -EFAULT; | 1539 | return -EFAULT; |
1581 | } | ||
1582 | msu++; | 1540 | msu++; |
1583 | } | 1541 | } |
1584 | unlock_kernel(); | ||
1585 | return 0; | 1542 | return 0; |
1586 | } | 1543 | } |
1587 | case MOXA_ASPP_MON_EXT: { | 1544 | case MOXA_ASPP_MON_EXT: { |
@@ -1593,41 +1550,48 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1593 | if (!me) | 1550 | if (!me) |
1594 | return -ENOMEM; | 1551 | return -ENOMEM; |
1595 | 1552 | ||
1596 | lock_kernel(); | ||
1597 | for (i = 0, p = 0; i < MXSER_BOARDS; i++) { | 1553 | for (i = 0, p = 0; i < MXSER_BOARDS; i++) { |
1598 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) { | 1554 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) { |
1599 | if (p >= ARRAY_SIZE(me->rx_cnt)) { | 1555 | if (p >= ARRAY_SIZE(me->rx_cnt)) { |
1600 | i = MXSER_BOARDS; | 1556 | i = MXSER_BOARDS; |
1601 | break; | 1557 | break; |
1602 | } | 1558 | } |
1603 | port = &mxser_boards[i].ports[j]; | 1559 | ip = &mxser_boards[i].ports[j]; |
1604 | if (!port->ioaddr) | 1560 | port = &ip->port; |
1561 | |||
1562 | mutex_lock(&port->mutex); | ||
1563 | if (!ip->ioaddr) { | ||
1564 | mutex_unlock(&port->mutex); | ||
1605 | continue; | 1565 | continue; |
1566 | } | ||
1606 | 1567 | ||
1607 | status = mxser_get_msr(port->ioaddr, 0, p); | 1568 | spin_lock_irq(&ip->slock); |
1569 | status = mxser_get_msr(ip->ioaddr, 0, p); | ||
1608 | 1570 | ||
1609 | if (status & UART_MSR_TERI) | 1571 | if (status & UART_MSR_TERI) |
1610 | port->icount.rng++; | 1572 | ip->icount.rng++; |
1611 | if (status & UART_MSR_DDSR) | 1573 | if (status & UART_MSR_DDSR) |
1612 | port->icount.dsr++; | 1574 | ip->icount.dsr++; |
1613 | if (status & UART_MSR_DDCD) | 1575 | if (status & UART_MSR_DDCD) |
1614 | port->icount.dcd++; | 1576 | ip->icount.dcd++; |
1615 | if (status & UART_MSR_DCTS) | 1577 | if (status & UART_MSR_DCTS) |
1616 | port->icount.cts++; | 1578 | ip->icount.cts++; |
1617 | 1579 | ||
1618 | port->mon_data.modem_status = status; | 1580 | ip->mon_data.modem_status = status; |
1619 | me->rx_cnt[p] = port->mon_data.rxcnt; | 1581 | me->rx_cnt[p] = ip->mon_data.rxcnt; |
1620 | me->tx_cnt[p] = port->mon_data.txcnt; | 1582 | me->tx_cnt[p] = ip->mon_data.txcnt; |
1621 | me->up_rxcnt[p] = port->mon_data.up_rxcnt; | 1583 | me->up_rxcnt[p] = ip->mon_data.up_rxcnt; |
1622 | me->up_txcnt[p] = port->mon_data.up_txcnt; | 1584 | me->up_txcnt[p] = ip->mon_data.up_txcnt; |
1623 | me->modem_status[p] = | 1585 | me->modem_status[p] = |
1624 | port->mon_data.modem_status; | 1586 | ip->mon_data.modem_status; |
1625 | tty = tty_port_tty_get(&port->port); | 1587 | spin_unlock_irq(&ip->slock); |
1588 | |||
1589 | tty = tty_port_tty_get(&ip->port); | ||
1626 | 1590 | ||
1627 | if (!tty || !tty->termios) { | 1591 | if (!tty || !tty->termios) { |
1628 | cflag = port->normal_termios.c_cflag; | 1592 | cflag = ip->normal_termios.c_cflag; |
1629 | iflag = port->normal_termios.c_iflag; | 1593 | iflag = ip->normal_termios.c_iflag; |
1630 | me->baudrate[p] = tty_termios_baud_rate(&port->normal_termios); | 1594 | me->baudrate[p] = tty_termios_baud_rate(&ip->normal_termios); |
1631 | } else { | 1595 | } else { |
1632 | cflag = tty->termios->c_cflag; | 1596 | cflag = tty->termios->c_cflag; |
1633 | iflag = tty->termios->c_iflag; | 1597 | iflag = tty->termios->c_iflag; |
@@ -1646,16 +1610,15 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1646 | if (iflag & (IXON | IXOFF)) | 1610 | if (iflag & (IXON | IXOFF)) |
1647 | me->flowctrl[p] |= 0x0C; | 1611 | me->flowctrl[p] |= 0x0C; |
1648 | 1612 | ||
1649 | if (port->type == PORT_16550A) | 1613 | if (ip->type == PORT_16550A) |
1650 | me->fifo[p] = 1; | 1614 | me->fifo[p] = 1; |
1651 | 1615 | ||
1652 | opmode = inb(port->opmode_ioaddr) >> | 1616 | opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2); |
1653 | ((p % 4) * 2); | ||
1654 | opmode &= OP_MODE_MASK; | 1617 | opmode &= OP_MODE_MASK; |
1655 | me->iftype[p] = opmode; | 1618 | me->iftype[p] = opmode; |
1619 | mutex_unlock(&port->mutex); | ||
1656 | } | 1620 | } |
1657 | } | 1621 | } |
1658 | unlock_kernel(); | ||
1659 | if (copy_to_user(argp, me, sizeof(*me))) | 1622 | if (copy_to_user(argp, me, sizeof(*me))) |
1660 | ret = -EFAULT; | 1623 | ret = -EFAULT; |
1661 | kfree(me); | 1624 | kfree(me); |
@@ -1692,6 +1655,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1692 | unsigned int cmd, unsigned long arg) | 1655 | unsigned int cmd, unsigned long arg) |
1693 | { | 1656 | { |
1694 | struct mxser_port *info = tty->driver_data; | 1657 | struct mxser_port *info = tty->driver_data; |
1658 | struct tty_port *port = &info->port; | ||
1695 | struct async_icount cnow; | 1659 | struct async_icount cnow; |
1696 | unsigned long flags; | 1660 | unsigned long flags; |
1697 | void __user *argp = (void __user *)arg; | 1661 | void __user *argp = (void __user *)arg; |
@@ -1716,20 +1680,20 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1716 | opmode != RS422_MODE && | 1680 | opmode != RS422_MODE && |
1717 | opmode != RS485_4WIRE_MODE) | 1681 | opmode != RS485_4WIRE_MODE) |
1718 | return -EFAULT; | 1682 | return -EFAULT; |
1719 | lock_kernel(); | ||
1720 | mask = ModeMask[p]; | 1683 | mask = ModeMask[p]; |
1721 | shiftbit = p * 2; | 1684 | shiftbit = p * 2; |
1685 | spin_lock_irq(&info->slock); | ||
1722 | val = inb(info->opmode_ioaddr); | 1686 | val = inb(info->opmode_ioaddr); |
1723 | val &= mask; | 1687 | val &= mask; |
1724 | val |= (opmode << shiftbit); | 1688 | val |= (opmode << shiftbit); |
1725 | outb(val, info->opmode_ioaddr); | 1689 | outb(val, info->opmode_ioaddr); |
1726 | unlock_kernel(); | 1690 | spin_unlock_irq(&info->slock); |
1727 | } else { | 1691 | } else { |
1728 | lock_kernel(); | ||
1729 | shiftbit = p * 2; | 1692 | shiftbit = p * 2; |
1693 | spin_lock_irq(&info->slock); | ||
1730 | opmode = inb(info->opmode_ioaddr) >> shiftbit; | 1694 | opmode = inb(info->opmode_ioaddr) >> shiftbit; |
1695 | spin_unlock_irq(&info->slock); | ||
1731 | opmode &= OP_MODE_MASK; | 1696 | opmode &= OP_MODE_MASK; |
1732 | unlock_kernel(); | ||
1733 | if (put_user(opmode, (int __user *)argp)) | 1697 | if (put_user(opmode, (int __user *)argp)) |
1734 | return -EFAULT; | 1698 | return -EFAULT; |
1735 | } | 1699 | } |
@@ -1742,14 +1706,14 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1742 | 1706 | ||
1743 | switch (cmd) { | 1707 | switch (cmd) { |
1744 | case TIOCGSERIAL: | 1708 | case TIOCGSERIAL: |
1745 | lock_kernel(); | 1709 | mutex_lock(&port->mutex); |
1746 | retval = mxser_get_serial_info(tty, argp); | 1710 | retval = mxser_get_serial_info(tty, argp); |
1747 | unlock_kernel(); | 1711 | mutex_unlock(&port->mutex); |
1748 | return retval; | 1712 | return retval; |
1749 | case TIOCSSERIAL: | 1713 | case TIOCSSERIAL: |
1750 | lock_kernel(); | 1714 | mutex_lock(&port->mutex); |
1751 | retval = mxser_set_serial_info(tty, argp); | 1715 | retval = mxser_set_serial_info(tty, argp); |
1752 | unlock_kernel(); | 1716 | mutex_unlock(&port->mutex); |
1753 | return retval; | 1717 | return retval; |
1754 | case TIOCSERGETLSR: /* Get line status register */ | 1718 | case TIOCSERGETLSR: /* Get line status register */ |
1755 | return mxser_get_lsr_info(info, argp); | 1719 | return mxser_get_lsr_info(info, argp); |
@@ -1795,31 +1759,33 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1795 | case MOXA_HighSpeedOn: | 1759 | case MOXA_HighSpeedOn: |
1796 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); | 1760 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); |
1797 | case MOXA_SDS_RSTICOUNTER: | 1761 | case MOXA_SDS_RSTICOUNTER: |
1798 | lock_kernel(); | 1762 | spin_lock_irq(&info->slock); |
1799 | info->mon_data.rxcnt = 0; | 1763 | info->mon_data.rxcnt = 0; |
1800 | info->mon_data.txcnt = 0; | 1764 | info->mon_data.txcnt = 0; |
1801 | unlock_kernel(); | 1765 | spin_unlock_irq(&info->slock); |
1802 | return 0; | 1766 | return 0; |
1803 | 1767 | ||
1804 | case MOXA_ASPP_OQUEUE:{ | 1768 | case MOXA_ASPP_OQUEUE:{ |
1805 | int len, lsr; | 1769 | int len, lsr; |
1806 | 1770 | ||
1807 | lock_kernel(); | ||
1808 | len = mxser_chars_in_buffer(tty); | 1771 | len = mxser_chars_in_buffer(tty); |
1772 | spin_lock(&info->slock); | ||
1809 | lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE; | 1773 | lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE; |
1774 | spin_unlock_irq(&info->slock); | ||
1810 | len += (lsr ? 0 : 1); | 1775 | len += (lsr ? 0 : 1); |
1811 | unlock_kernel(); | ||
1812 | 1776 | ||
1813 | return put_user(len, (int __user *)argp); | 1777 | return put_user(len, (int __user *)argp); |
1814 | } | 1778 | } |
1815 | case MOXA_ASPP_MON: { | 1779 | case MOXA_ASPP_MON: { |
1816 | int mcr, status; | 1780 | int mcr, status; |
1817 | 1781 | ||
1818 | lock_kernel(); | 1782 | spin_lock(&info->slock); |
1819 | status = mxser_get_msr(info->ioaddr, 1, tty->index); | 1783 | status = mxser_get_msr(info->ioaddr, 1, tty->index); |
1820 | mxser_check_modem_status(tty, info, status); | 1784 | mxser_check_modem_status(tty, info, status); |
1821 | 1785 | ||
1822 | mcr = inb(info->ioaddr + UART_MCR); | 1786 | mcr = inb(info->ioaddr + UART_MCR); |
1787 | spin_unlock(&info->slock); | ||
1788 | |||
1823 | if (mcr & MOXA_MUST_MCR_XON_FLAG) | 1789 | if (mcr & MOXA_MUST_MCR_XON_FLAG) |
1824 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; | 1790 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; |
1825 | else | 1791 | else |
@@ -1834,7 +1800,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1834 | info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; | 1800 | info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; |
1835 | else | 1801 | else |
1836 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; | 1802 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; |
1837 | unlock_kernel(); | 1803 | |
1838 | if (copy_to_user(argp, &info->mon_data, | 1804 | if (copy_to_user(argp, &info->mon_data, |
1839 | sizeof(struct mxser_mon))) | 1805 | sizeof(struct mxser_mon))) |
1840 | return -EFAULT; | 1806 | return -EFAULT; |
@@ -1993,6 +1959,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1993 | { | 1959 | { |
1994 | struct mxser_port *info = tty->driver_data; | 1960 | struct mxser_port *info = tty->driver_data; |
1995 | unsigned long orig_jiffies, char_time; | 1961 | unsigned long orig_jiffies, char_time; |
1962 | unsigned long flags; | ||
1996 | int lsr; | 1963 | int lsr; |
1997 | 1964 | ||
1998 | if (info->type == PORT_UNKNOWN) | 1965 | if (info->type == PORT_UNKNOWN) |
@@ -2032,19 +1999,21 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) | |||
2032 | timeout, char_time); | 1999 | timeout, char_time); |
2033 | printk("jiff=%lu...", jiffies); | 2000 | printk("jiff=%lu...", jiffies); |
2034 | #endif | 2001 | #endif |
2035 | lock_kernel(); | 2002 | spin_lock_irqsave(&info->slock, flags); |
2036 | while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { | 2003 | while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { |
2037 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 2004 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT |
2038 | printk("lsr = %d (jiff=%lu)...", lsr, jiffies); | 2005 | printk("lsr = %d (jiff=%lu)...", lsr, jiffies); |
2039 | #endif | 2006 | #endif |
2007 | spin_unlock_irqrestore(&info->slock, flags); | ||
2040 | schedule_timeout_interruptible(char_time); | 2008 | schedule_timeout_interruptible(char_time); |
2009 | spin_lock_irqsave(&info->slock, flags); | ||
2041 | if (signal_pending(current)) | 2010 | if (signal_pending(current)) |
2042 | break; | 2011 | break; |
2043 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) | 2012 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) |
2044 | break; | 2013 | break; |
2045 | } | 2014 | } |
2015 | spin_unlock_irqrestore(&info->slock, flags); | ||
2046 | set_current_state(TASK_RUNNING); | 2016 | set_current_state(TASK_RUNNING); |
2047 | unlock_kernel(); | ||
2048 | 2017 | ||
2049 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 2018 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT |
2050 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); | 2019 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); |
@@ -2059,7 +2028,6 @@ static void mxser_hangup(struct tty_struct *tty) | |||
2059 | struct mxser_port *info = tty->driver_data; | 2028 | struct mxser_port *info = tty->driver_data; |
2060 | 2029 | ||
2061 | mxser_flush_buffer(tty); | 2030 | mxser_flush_buffer(tty); |
2062 | mxser_shutdown(tty); | ||
2063 | tty_port_hangup(&info->port); | 2031 | tty_port_hangup(&info->port); |
2064 | } | 2032 | } |
2065 | 2033 | ||
@@ -2363,6 +2331,8 @@ static const struct tty_operations mxser_ops = { | |||
2363 | struct tty_port_operations mxser_port_ops = { | 2331 | struct tty_port_operations mxser_port_ops = { |
2364 | .carrier_raised = mxser_carrier_raised, | 2332 | .carrier_raised = mxser_carrier_raised, |
2365 | .dtr_rts = mxser_dtr_rts, | 2333 | .dtr_rts = mxser_dtr_rts, |
2334 | .activate = mxser_activate, | ||
2335 | .shutdown = mxser_shutdown_port, | ||
2366 | }; | 2336 | }; |
2367 | 2337 | ||
2368 | /* | 2338 | /* |