diff options
-rw-r--r-- | drivers/tty/mxser.c | 4 | ||||
-rw-r--r-- | drivers/tty/n_gsm.c | 4 | ||||
-rw-r--r-- | drivers/tty/tty_port.c | 27 |
3 files changed, 23 insertions, 12 deletions
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 484b6a3c9b03..d996038eacfd 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c | |||
@@ -1084,6 +1084,10 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) | |||
1084 | mutex_lock(&port->mutex); | 1084 | mutex_lock(&port->mutex); |
1085 | mxser_close_port(port); | 1085 | mxser_close_port(port); |
1086 | mxser_flush_buffer(tty); | 1086 | mxser_flush_buffer(tty); |
1087 | if (test_bit(ASYNCB_INITIALIZED, &port->flags)) { | ||
1088 | if (C_HUPCL(tty)) | ||
1089 | tty_port_lower_dtr_rts(port); | ||
1090 | } | ||
1087 | mxser_shutdown_port(port); | 1091 | mxser_shutdown_port(port); |
1088 | clear_bit(ASYNCB_INITIALIZED, &port->flags); | 1092 | clear_bit(ASYNCB_INITIALIZED, &port->flags); |
1089 | mutex_unlock(&port->mutex); | 1093 | mutex_unlock(&port->mutex); |
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 74d9a0258d7c..642239015b46 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c | |||
@@ -2964,6 +2964,10 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp) | |||
2964 | if (tty_port_close_start(&dlci->port, tty, filp) == 0) | 2964 | if (tty_port_close_start(&dlci->port, tty, filp) == 0) |
2965 | goto out; | 2965 | goto out; |
2966 | gsm_dlci_begin_close(dlci); | 2966 | gsm_dlci_begin_close(dlci); |
2967 | if (test_bit(ASYNCB_INITIALIZED, &dlci->port.flags)) { | ||
2968 | if (C_HUPCL(tty)) | ||
2969 | tty_port_lower_dtr_rts(&dlci->port); | ||
2970 | } | ||
2967 | tty_port_close_end(&dlci->port, tty); | 2971 | tty_port_close_end(&dlci->port, tty); |
2968 | tty_port_tty_set(&dlci->port, NULL); | 2972 | tty_port_tty_set(&dlci->port, NULL); |
2969 | out: | 2973 | out: |
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 7e3eaf4eb9fe..0af8d9aa5b02 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c | |||
@@ -196,13 +196,20 @@ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty) | |||
196 | } | 196 | } |
197 | EXPORT_SYMBOL(tty_port_tty_set); | 197 | EXPORT_SYMBOL(tty_port_tty_set); |
198 | 198 | ||
199 | static void tty_port_shutdown(struct tty_port *port) | 199 | static void tty_port_shutdown(struct tty_port *port, struct tty_struct *tty) |
200 | { | 200 | { |
201 | mutex_lock(&port->mutex); | 201 | mutex_lock(&port->mutex); |
202 | if (port->console) | 202 | if (port->console) |
203 | goto out; | 203 | goto out; |
204 | 204 | ||
205 | if (test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) { | 205 | if (test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) { |
206 | /* | ||
207 | * Drop DTR/RTS if HUPCL is set. This causes any attached | ||
208 | * modem to hang up the line. | ||
209 | */ | ||
210 | if (tty && C_HUPCL(tty)) | ||
211 | tty_port_lower_dtr_rts(port); | ||
212 | |||
206 | if (port->ops->shutdown) | 213 | if (port->ops->shutdown) |
207 | port->ops->shutdown(port); | 214 | port->ops->shutdown(port); |
208 | } | 215 | } |
@@ -220,18 +227,19 @@ out: | |||
220 | 227 | ||
221 | void tty_port_hangup(struct tty_port *port) | 228 | void tty_port_hangup(struct tty_port *port) |
222 | { | 229 | { |
230 | struct tty_struct *tty; | ||
223 | unsigned long flags; | 231 | unsigned long flags; |
224 | 232 | ||
225 | spin_lock_irqsave(&port->lock, flags); | 233 | spin_lock_irqsave(&port->lock, flags); |
226 | port->count = 0; | 234 | port->count = 0; |
227 | port->flags &= ~ASYNC_NORMAL_ACTIVE; | 235 | port->flags &= ~ASYNC_NORMAL_ACTIVE; |
228 | if (port->tty) { | 236 | tty = port->tty; |
229 | set_bit(TTY_IO_ERROR, &port->tty->flags); | 237 | if (tty) |
230 | tty_kref_put(port->tty); | 238 | set_bit(TTY_IO_ERROR, &tty->flags); |
231 | } | ||
232 | port->tty = NULL; | 239 | port->tty = NULL; |
233 | spin_unlock_irqrestore(&port->lock, flags); | 240 | spin_unlock_irqrestore(&port->lock, flags); |
234 | tty_port_shutdown(port); | 241 | tty_port_shutdown(port, tty); |
242 | tty_kref_put(tty); | ||
235 | wake_up_interruptible(&port->open_wait); | 243 | wake_up_interruptible(&port->open_wait); |
236 | wake_up_interruptible(&port->delta_msr_wait); | 244 | wake_up_interruptible(&port->delta_msr_wait); |
237 | } | 245 | } |
@@ -485,11 +493,6 @@ int tty_port_close_start(struct tty_port *port, | |||
485 | /* Flush the ldisc buffering */ | 493 | /* Flush the ldisc buffering */ |
486 | tty_ldisc_flush(tty); | 494 | tty_ldisc_flush(tty); |
487 | 495 | ||
488 | /* Drop DTR/RTS if HUPCL is set. This causes any attached modem to | ||
489 | hang up the line */ | ||
490 | if (tty->termios.c_cflag & HUPCL) | ||
491 | tty_port_lower_dtr_rts(port); | ||
492 | |||
493 | /* Don't call port->drop for the last reference. Callers will want | 496 | /* Don't call port->drop for the last reference. Callers will want |
494 | to drop the last active reference in ->shutdown() or the tty | 497 | to drop the last active reference in ->shutdown() or the tty |
495 | shutdown path */ | 498 | shutdown path */ |
@@ -524,7 +527,7 @@ void tty_port_close(struct tty_port *port, struct tty_struct *tty, | |||
524 | { | 527 | { |
525 | if (tty_port_close_start(port, tty, filp) == 0) | 528 | if (tty_port_close_start(port, tty, filp) == 0) |
526 | return; | 529 | return; |
527 | tty_port_shutdown(port); | 530 | tty_port_shutdown(port, tty); |
528 | set_bit(TTY_IO_ERROR, &tty->flags); | 531 | set_bit(TTY_IO_ERROR, &tty->flags); |
529 | tty_port_close_end(port, tty); | 532 | tty_port_close_end(port, tty); |
530 | tty_port_tty_set(port, NULL); | 533 | tty_port_tty_set(port, NULL); |