aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/mxser.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/mxser.c')
-rw-r--r--drivers/char/mxser.c111
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
859static int mxser_startup(struct tty_struct *tty) 859static 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 */
964static void mxser_shutdown(struct tty_struct *tty) 953static 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)
1023static int mxser_open(struct tty_struct *tty, struct file *filp) 1002static 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
1057static void mxser_flush_buffer(struct tty_struct *tty) 1019static 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
1078static void mxser_close_port(struct tty_struct *tty, struct tty_port *port) 1040static 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 = {
2363struct tty_port_operations mxser_port_ops = { 2320struct 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/*