diff options
-rw-r--r-- | MAINTAINERS | 3 | ||||
-rw-r--r-- | drivers/char/pty.c | 57 | ||||
-rw-r--r-- | drivers/char/tty_io.c | 2 | ||||
-rw-r--r-- | drivers/char/tty_ioctl.c | 5 | ||||
-rw-r--r-- | drivers/char/tty_ldisc.c | 3 | ||||
-rw-r--r-- | drivers/serial/atmel_serial.c | 8 | ||||
-rw-r--r-- | drivers/serial/imx.c | 12 |
7 files changed, 64 insertions, 26 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 2cb7566904b1..09f6b3e5708a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -157,9 +157,10 @@ S: Maintained | |||
157 | F: drivers/net/r8169.c | 157 | F: drivers/net/r8169.c |
158 | 158 | ||
159 | 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER | 159 | 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER |
160 | P: Alan Cox | ||
161 | M: alan@lxorguk.ukuu.org.uk | ||
160 | L: linux-serial@vger.kernel.org | 162 | L: linux-serial@vger.kernel.org |
161 | W: http://serial.sourceforge.net | 163 | W: http://serial.sourceforge.net |
162 | M: alan@lxorguk.ukuu.org.uk | ||
163 | S: Odd Fixes | 164 | S: Odd Fixes |
164 | F: drivers/serial/8250* | 165 | F: drivers/serial/8250* |
165 | F: include/linux/serial_8250.h | 166 | F: include/linux/serial_8250.h |
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 3910ce112a95..daebe1ba43d4 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
@@ -95,23 +95,34 @@ static void pty_unthrottle(struct tty_struct *tty) | |||
95 | * a count. | 95 | * a count. |
96 | * | 96 | * |
97 | * FIXME: Our pty_write method is called with our ldisc lock held but | 97 | * FIXME: Our pty_write method is called with our ldisc lock held but |
98 | * not our partners. We can't just take the other one blindly without | 98 | * not our partners. We can't just wait on the other one blindly without |
99 | * risking deadlocks. | 99 | * risking deadlocks. At some point when everything has settled down we need |
100 | * to look into making pty_write at least able to sleep over an ldisc change. | ||
101 | * | ||
102 | * The return on no ldisc is a bit counter intuitive but the logic works | ||
103 | * like this. During an ldisc change the other end will flush its buffers. We | ||
104 | * thus return the full length which is identical to the case where we had | ||
105 | * proper locking and happened to queue the bytes just before the flush during | ||
106 | * the ldisc change. | ||
100 | */ | 107 | */ |
101 | static int pty_write(struct tty_struct *tty, const unsigned char *buf, | 108 | static int pty_write(struct tty_struct *tty, const unsigned char *buf, |
102 | int count) | 109 | int count) |
103 | { | 110 | { |
104 | struct tty_struct *to = tty->link; | 111 | struct tty_struct *to = tty->link; |
105 | int c; | 112 | struct tty_ldisc *ld; |
113 | int c = count; | ||
106 | 114 | ||
107 | if (!to || !to->ldisc || tty->stopped) | 115 | if (!to || tty->stopped) |
108 | return 0; | 116 | return 0; |
109 | 117 | ld = tty_ldisc_ref(to); | |
110 | c = to->receive_room; | 118 | |
111 | if (c > count) | 119 | if (ld) { |
112 | c = count; | 120 | c = to->receive_room; |
113 | to->ldisc->ops->receive_buf(to, buf, NULL, c); | 121 | if (c > count) |
114 | 122 | c = count; | |
123 | ld->ops->receive_buf(to, buf, NULL, c); | ||
124 | tty_ldisc_deref(ld); | ||
125 | } | ||
115 | return c; | 126 | return c; |
116 | } | 127 | } |
117 | 128 | ||
@@ -145,14 +156,23 @@ static int pty_write_room(struct tty_struct *tty) | |||
145 | static int pty_chars_in_buffer(struct tty_struct *tty) | 156 | static int pty_chars_in_buffer(struct tty_struct *tty) |
146 | { | 157 | { |
147 | struct tty_struct *to = tty->link; | 158 | struct tty_struct *to = tty->link; |
148 | int count; | 159 | struct tty_ldisc *ld; |
160 | int count = 0; | ||
149 | 161 | ||
150 | /* We should get the line discipline lock for "tty->link" */ | 162 | /* We should get the line discipline lock for "tty->link" */ |
151 | if (!to || !to->ldisc || !to->ldisc->ops->chars_in_buffer) | 163 | if (!to) |
164 | return 0; | ||
165 | /* We cannot take a sleeping reference here without deadlocking with | ||
166 | an ldisc change - but it doesn't really matter */ | ||
167 | ld = tty_ldisc_ref(to); | ||
168 | if (ld == NULL) | ||
152 | return 0; | 169 | return 0; |
153 | 170 | ||
154 | /* The ldisc must report 0 if no characters available to be read */ | 171 | /* The ldisc must report 0 if no characters available to be read */ |
155 | count = to->ldisc->ops->chars_in_buffer(to); | 172 | if (ld->ops->chars_in_buffer) |
173 | count = ld->ops->chars_in_buffer(to); | ||
174 | |||
175 | tty_ldisc_deref(ld); | ||
156 | 176 | ||
157 | if (tty->driver->subtype == PTY_TYPE_SLAVE) | 177 | if (tty->driver->subtype == PTY_TYPE_SLAVE) |
158 | return count; | 178 | return count; |
@@ -182,12 +202,19 @@ static void pty_flush_buffer(struct tty_struct *tty) | |||
182 | { | 202 | { |
183 | struct tty_struct *to = tty->link; | 203 | struct tty_struct *to = tty->link; |
184 | unsigned long flags; | 204 | unsigned long flags; |
205 | struct tty_ldisc *ld; | ||
206 | |||
207 | if (!to) | ||
208 | return; | ||
209 | ld = tty_ldisc_ref(to); | ||
185 | 210 | ||
186 | if (!to || !to->ldisc) | 211 | /* The other end is changing discipline */ |
212 | if (!ld) | ||
187 | return; | 213 | return; |
188 | 214 | ||
189 | if (to->ldisc->ops->flush_buffer) | 215 | if (ld->ops->flush_buffer) |
190 | to->ldisc->ops->flush_buffer(to); | 216 | to->ldisc->ops->flush_buffer(to); |
217 | tty_ldisc_deref(ld); | ||
191 | 218 | ||
192 | if (to->packet) { | 219 | if (to->packet) { |
193 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 220 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 939e198d7670..a3afa0c387cd 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -1263,7 +1263,9 @@ static int tty_reopen(struct tty_struct *tty) | |||
1263 | tty->count++; | 1263 | tty->count++; |
1264 | tty->driver = driver; /* N.B. why do this every time?? */ | 1264 | tty->driver = driver; /* N.B. why do this every time?? */ |
1265 | 1265 | ||
1266 | mutex_lock(&tty->ldisc_mutex); | ||
1266 | WARN_ON(!test_bit(TTY_LDISC, &tty->flags)); | 1267 | WARN_ON(!test_bit(TTY_LDISC, &tty->flags)); |
1268 | mutex_unlock(&tty->ldisc_mutex); | ||
1267 | 1269 | ||
1268 | return 0; | 1270 | return 0; |
1269 | } | 1271 | } |
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 8116bb1c8f80..b24f6c6a1ea3 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
@@ -947,7 +947,6 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
947 | void __user *p = (void __user *)arg; | 947 | void __user *p = (void __user *)arg; |
948 | int ret = 0; | 948 | int ret = 0; |
949 | struct ktermios kterm; | 949 | struct ktermios kterm; |
950 | struct termiox ktermx; | ||
951 | 950 | ||
952 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 951 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
953 | tty->driver->subtype == PTY_TYPE_MASTER) | 952 | tty->driver->subtype == PTY_TYPE_MASTER) |
@@ -1049,7 +1048,8 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
1049 | return ret; | 1048 | return ret; |
1050 | #endif | 1049 | #endif |
1051 | #ifdef TCGETX | 1050 | #ifdef TCGETX |
1052 | case TCGETX: | 1051 | case TCGETX: { |
1052 | struct termiox ktermx; | ||
1053 | if (real_tty->termiox == NULL) | 1053 | if (real_tty->termiox == NULL) |
1054 | return -EINVAL; | 1054 | return -EINVAL; |
1055 | mutex_lock(&real_tty->termios_mutex); | 1055 | mutex_lock(&real_tty->termios_mutex); |
@@ -1058,6 +1058,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
1058 | if (copy_to_user(p, &ktermx, sizeof(struct termiox))) | 1058 | if (copy_to_user(p, &ktermx, sizeof(struct termiox))) |
1059 | ret = -EFAULT; | 1059 | ret = -EFAULT; |
1060 | return ret; | 1060 | return ret; |
1061 | } | ||
1061 | case TCSETX: | 1062 | case TCSETX: |
1062 | return set_termiox(real_tty, p, 0); | 1063 | return set_termiox(real_tty, p, 0); |
1063 | case TCSETXW: | 1064 | case TCSETXW: |
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index 94b3e06d73ec..a19e935847b0 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c | |||
@@ -207,6 +207,7 @@ static void tty_ldisc_put(struct tty_ldisc *ld) | |||
207 | ldo->refcount--; | 207 | ldo->refcount--; |
208 | module_put(ldo->owner); | 208 | module_put(ldo->owner); |
209 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 209 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
210 | WARN_ON(ld->refcount); | ||
210 | kfree(ld); | 211 | kfree(ld); |
211 | } | 212 | } |
212 | 213 | ||
@@ -793,6 +794,8 @@ void tty_ldisc_hangup(struct tty_struct *tty) | |||
793 | /* Avoid racing set_ldisc */ | 794 | /* Avoid racing set_ldisc */ |
794 | mutex_lock(&tty->ldisc_mutex); | 795 | mutex_lock(&tty->ldisc_mutex); |
795 | /* Switch back to N_TTY */ | 796 | /* Switch back to N_TTY */ |
797 | tty_ldisc_halt(tty); | ||
798 | tty_ldisc_wait_idle(tty); | ||
796 | tty_ldisc_reinit(tty); | 799 | tty_ldisc_reinit(tty); |
797 | /* At this point we have a closed ldisc and we want to | 800 | /* At this point we have a closed ldisc and we want to |
798 | reopen it. We could defer this to the next open but | 801 | reopen it. We could defer this to the next open but |
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index b3497d7e5354..338b15c0a548 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c | |||
@@ -1104,11 +1104,13 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1104 | /* update the per-port timeout */ | 1104 | /* update the per-port timeout */ |
1105 | uart_update_timeout(port, termios->c_cflag, baud); | 1105 | uart_update_timeout(port, termios->c_cflag, baud); |
1106 | 1106 | ||
1107 | /* save/disable interrupts and drain transmitter */ | 1107 | /* |
1108 | * save/disable interrupts. The tty layer will ensure that the | ||
1109 | * transmitter is empty if requested by the caller, so there's | ||
1110 | * no need to wait for it here. | ||
1111 | */ | ||
1108 | imr = UART_GET_IMR(port); | 1112 | imr = UART_GET_IMR(port); |
1109 | UART_PUT_IDR(port, -1); | 1113 | UART_PUT_IDR(port, -1); |
1110 | while (!(UART_GET_CSR(port) & ATMEL_US_TXEMPTY)) | ||
1111 | cpu_relax(); | ||
1112 | 1114 | ||
1113 | /* disable receiver and transmitter */ | 1115 | /* disable receiver and transmitter */ |
1114 | UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS); | 1116 | UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS); |
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 285b414f3054..5d7b58f1fe42 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
@@ -924,11 +924,13 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, | |||
924 | rational_best_approximation(16 * div * baud, sport->port.uartclk, | 924 | rational_best_approximation(16 * div * baud, sport->port.uartclk, |
925 | 1 << 16, 1 << 16, &num, &denom); | 925 | 1 << 16, 1 << 16, &num, &denom); |
926 | 926 | ||
927 | tdiv64 = sport->port.uartclk; | 927 | if (port->info && port->info->port.tty) { |
928 | tdiv64 *= num; | 928 | tdiv64 = sport->port.uartclk; |
929 | do_div(tdiv64, denom * 16 * div); | 929 | tdiv64 *= num; |
930 | tty_encode_baud_rate(sport->port.info->port.tty, | 930 | do_div(tdiv64, denom * 16 * div); |
931 | (speed_t)tdiv64, (speed_t)tdiv64); | 931 | tty_encode_baud_rate(sport->port.info->port.tty, |
932 | (speed_t)tdiv64, (speed_t)tdiv64); | ||
933 | } | ||
932 | 934 | ||
933 | num -= 1; | 935 | num -= 1; |
934 | denom -= 1; | 936 | denom -= 1; |