diff options
Diffstat (limited to 'drivers/char/mxser.c')
-rw-r--r-- | drivers/char/mxser.c | 111 |
1 files changed, 35 insertions, 76 deletions
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 5e28d39b9e81..9dac516df006 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -856,9 +856,9 @@ static void mxser_check_modem_status(struct tty_struct *tty, | |||
856 | } | 856 | } |
857 | } | 857 | } |
858 | 858 | ||
859 | static int mxser_startup(struct tty_struct *tty) | 859 | static int mxser_activate(struct tty_port *port, struct tty_struct *tty) |
860 | { | 860 | { |
861 | struct mxser_port *info = tty->driver_data; | 861 | struct mxser_port *info = container_of(port, struct mxser_port, port); |
862 | unsigned long page; | 862 | unsigned long page; |
863 | unsigned long flags; | 863 | unsigned long flags; |
864 | 864 | ||
@@ -868,22 +868,13 @@ static int mxser_startup(struct tty_struct *tty) | |||
868 | 868 | ||
869 | spin_lock_irqsave(&info->slock, flags); | 869 | spin_lock_irqsave(&info->slock, flags); |
870 | 870 | ||
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) { | 871 | if (!info->ioaddr || !info->type) { |
878 | set_bit(TTY_IO_ERROR, &tty->flags); | 872 | set_bit(TTY_IO_ERROR, &tty->flags); |
879 | free_page(page); | 873 | free_page(page); |
880 | spin_unlock_irqrestore(&info->slock, flags); | 874 | spin_unlock_irqrestore(&info->slock, flags); |
881 | return 0; | 875 | return 0; |
882 | } | 876 | } |
883 | if (info->port.xmit_buf) | 877 | info->port.xmit_buf = (unsigned char *) page; |
884 | free_page(page); | ||
885 | else | ||
886 | info->port.xmit_buf = (unsigned char *) page; | ||
887 | 878 | ||
888 | /* | 879 | /* |
889 | * Clear the FIFO buffers and disable them | 880 | * Clear the FIFO buffers and disable them |
@@ -951,24 +942,19 @@ static int mxser_startup(struct tty_struct *tty) | |||
951 | * and set the speed of the serial port | 942 | * and set the speed of the serial port |
952 | */ | 943 | */ |
953 | mxser_change_speed(tty, NULL); | 944 | mxser_change_speed(tty, NULL); |
954 | info->port.flags |= ASYNC_INITIALIZED; | ||
955 | spin_unlock_irqrestore(&info->slock, flags); | 945 | spin_unlock_irqrestore(&info->slock, flags); |
956 | 946 | ||
957 | return 0; | 947 | return 0; |
958 | } | 948 | } |
959 | 949 | ||
960 | /* | 950 | /* |
961 | * This routine will shutdown a serial port; interrupts maybe disabled, and | 951 | * This routine will shutdown a serial port |
962 | * DTR is dropped if the hangup on close termio flag is on. | ||
963 | */ | 952 | */ |
964 | static void mxser_shutdown(struct tty_struct *tty) | 953 | static void mxser_shutdown_port(struct tty_port *port) |
965 | { | 954 | { |
966 | struct mxser_port *info = tty->driver_data; | 955 | struct mxser_port *info = container_of(port, struct mxser_port, port); |
967 | unsigned long flags; | 956 | unsigned long flags; |
968 | 957 | ||
969 | if (!(info->port.flags & ASYNC_INITIALIZED)) | ||
970 | return; | ||
971 | |||
972 | spin_lock_irqsave(&info->slock, flags); | 958 | spin_lock_irqsave(&info->slock, flags); |
973 | 959 | ||
974 | /* | 960 | /* |
@@ -978,7 +964,7 @@ static void mxser_shutdown(struct tty_struct *tty) | |||
978 | wake_up_interruptible(&info->port.delta_msr_wait); | 964 | wake_up_interruptible(&info->port.delta_msr_wait); |
979 | 965 | ||
980 | /* | 966 | /* |
981 | * Free the IRQ, if necessary | 967 | * Free the xmit buffer, if necessary |
982 | */ | 968 | */ |
983 | if (info->port.xmit_buf) { | 969 | if (info->port.xmit_buf) { |
984 | free_page((unsigned long) info->port.xmit_buf); | 970 | free_page((unsigned long) info->port.xmit_buf); |
@@ -988,10 +974,6 @@ static void mxser_shutdown(struct tty_struct *tty) | |||
988 | info->IER = 0; | 974 | info->IER = 0; |
989 | outb(0x00, info->ioaddr + UART_IER); | 975 | outb(0x00, info->ioaddr + UART_IER); |
990 | 976 | ||
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 */ | 977 | /* clear Rx/Tx FIFO's */ |
996 | if (info->board->chip_flag) | 978 | if (info->board->chip_flag) |
997 | outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | | 979 | outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | |
@@ -1004,9 +986,6 @@ static void mxser_shutdown(struct tty_struct *tty) | |||
1004 | /* read data port to reset things */ | 986 | /* read data port to reset things */ |
1005 | (void) inb(info->ioaddr + UART_RX); | 987 | (void) inb(info->ioaddr + UART_RX); |
1006 | 988 | ||
1007 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
1008 | |||
1009 | info->port.flags &= ~ASYNC_INITIALIZED; | ||
1010 | 989 | ||
1011 | if (info->board->chip_flag) | 990 | if (info->board->chip_flag) |
1012 | SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr); | 991 | SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr); |
@@ -1023,8 +1002,7 @@ static void mxser_shutdown(struct tty_struct *tty) | |||
1023 | static int mxser_open(struct tty_struct *tty, struct file *filp) | 1002 | static int mxser_open(struct tty_struct *tty, struct file *filp) |
1024 | { | 1003 | { |
1025 | struct mxser_port *info; | 1004 | struct mxser_port *info; |
1026 | unsigned long flags; | 1005 | int line; |
1027 | int retval, line; | ||
1028 | 1006 | ||
1029 | line = tty->index; | 1007 | line = tty->index; |
1030 | if (line == MXSER_PORTS) | 1008 | if (line == MXSER_PORTS) |
@@ -1035,23 +1013,7 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) | |||
1035 | if (!info->ioaddr) | 1013 | if (!info->ioaddr) |
1036 | return -ENODEV; | 1014 | return -ENODEV; |
1037 | 1015 | ||
1038 | tty->driver_data = info; | 1016 | 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 | } | 1017 | } |
1056 | 1018 | ||
1057 | static void mxser_flush_buffer(struct tty_struct *tty) | 1019 | static void mxser_flush_buffer(struct tty_struct *tty) |
@@ -1075,19 +1037,11 @@ static void mxser_flush_buffer(struct tty_struct *tty) | |||
1075 | } | 1037 | } |
1076 | 1038 | ||
1077 | 1039 | ||
1078 | static void mxser_close_port(struct tty_struct *tty, struct tty_port *port) | 1040 | static void mxser_close_port(struct tty_port *port) |
1079 | { | 1041 | { |
1080 | struct mxser_port *info = container_of(port, struct mxser_port, port); | 1042 | struct mxser_port *info = container_of(port, struct mxser_port, port); |
1081 | unsigned long timeout; | 1043 | unsigned long timeout; |
1082 | /* | 1044 | /* |
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 | 1045 | * At this point we stop accepting input. To do this, we |
1092 | * disable the receive line status interrupts, and tell the | 1046 | * disable the receive line status interrupts, and tell the |
1093 | * interrupt driver to stop checking the data ready bit in the | 1047 | * interrupt driver to stop checking the data ready bit in the |
@@ -1097,22 +1051,18 @@ static void mxser_close_port(struct tty_struct *tty, struct tty_port *port) | |||
1097 | if (info->board->chip_flag) | 1051 | if (info->board->chip_flag) |
1098 | info->IER &= ~MOXA_MUST_RECV_ISR; | 1052 | info->IER &= ~MOXA_MUST_RECV_ISR; |
1099 | 1053 | ||
1100 | if (port->flags & ASYNC_INITIALIZED) { | 1054 | outb(info->IER, info->ioaddr + UART_IER); |
1101 | outb(info->IER, info->ioaddr + UART_IER); | 1055 | /* |
1102 | /* | 1056 | * Before we drop DTR, make sure the UART transmitter |
1103 | * Before we drop DTR, make sure the UART transmitter | 1057 | * has completely drained; this is especially |
1104 | * has completely drained; this is especially | 1058 | * important if there is a transmit FIFO! |
1105 | * important if there is a transmit FIFO! | 1059 | */ |
1106 | */ | 1060 | timeout = jiffies + HZ; |
1107 | timeout = jiffies + HZ; | 1061 | while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) { |
1108 | while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) { | 1062 | schedule_timeout_interruptible(5); |
1109 | schedule_timeout_interruptible(5); | 1063 | if (time_after(jiffies, timeout)) |
1110 | if (time_after(jiffies, timeout)) | 1064 | break; |
1111 | break; | ||
1112 | } | ||
1113 | } | 1065 | } |
1114 | mxser_shutdown(tty); | ||
1115 | |||
1116 | } | 1066 | } |
1117 | 1067 | ||
1118 | /* | 1068 | /* |
@@ -1130,8 +1080,12 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) | |||
1130 | return; | 1080 | return; |
1131 | if (tty_port_close_start(port, tty, filp) == 0) | 1081 | if (tty_port_close_start(port, tty, filp) == 0) |
1132 | return; | 1082 | return; |
1133 | mxser_close_port(tty, port); | 1083 | mutex_lock(&port->mutex); |
1084 | mxser_close_port(port); | ||
1134 | mxser_flush_buffer(tty); | 1085 | mxser_flush_buffer(tty); |
1086 | mxser_shutdown_port(port); | ||
1087 | clear_bit(ASYNCB_INITIALIZED, &port->flags); | ||
1088 | mutex_unlock(&port->mutex); | ||
1135 | /* Right now the tty_port set is done outside of the close_end helper | 1089 | /* Right now the tty_port set is done outside of the close_end helper |
1136 | as we don't yet have everyone using refcounts */ | 1090 | as we don't yet have everyone using refcounts */ |
1137 | tty_port_close_end(port, tty); | 1091 | tty_port_close_end(port, tty); |
@@ -1329,9 +1283,13 @@ static int mxser_set_serial_info(struct tty_struct *tty, | |||
1329 | mxser_change_speed(tty, NULL); | 1283 | mxser_change_speed(tty, NULL); |
1330 | spin_unlock_irqrestore(&info->slock, sl_flags); | 1284 | spin_unlock_irqrestore(&info->slock, sl_flags); |
1331 | } | 1285 | } |
1332 | } else | 1286 | } else { |
1333 | retval = mxser_startup(tty); | 1287 | mutex_lock(&info->port.mutex); |
1334 | 1288 | retval = mxser_activate(&info->port, tty); | |
1289 | if (retval == 0) | ||
1290 | set_bit(ASYNCB_INITIALIZED, &info->port.flags); | ||
1291 | mutex_unlock(&info->port.mutex); | ||
1292 | } | ||
1335 | return retval; | 1293 | return retval; |
1336 | } | 1294 | } |
1337 | 1295 | ||
@@ -2059,7 +2017,6 @@ static void mxser_hangup(struct tty_struct *tty) | |||
2059 | struct mxser_port *info = tty->driver_data; | 2017 | struct mxser_port *info = tty->driver_data; |
2060 | 2018 | ||
2061 | mxser_flush_buffer(tty); | 2019 | mxser_flush_buffer(tty); |
2062 | mxser_shutdown(tty); | ||
2063 | tty_port_hangup(&info->port); | 2020 | tty_port_hangup(&info->port); |
2064 | } | 2021 | } |
2065 | 2022 | ||
@@ -2363,6 +2320,8 @@ static const struct tty_operations mxser_ops = { | |||
2363 | struct tty_port_operations mxser_port_ops = { | 2320 | struct tty_port_operations mxser_port_ops = { |
2364 | .carrier_raised = mxser_carrier_raised, | 2321 | .carrier_raised = mxser_carrier_raised, |
2365 | .dtr_rts = mxser_dtr_rts, | 2322 | .dtr_rts = mxser_dtr_rts, |
2323 | .activate = mxser_activate, | ||
2324 | .shutdown = mxser_shutdown_port, | ||
2366 | }; | 2325 | }; |
2367 | 2326 | ||
2368 | /* | 2327 | /* |