summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/mxser.c4
-rw-r--r--drivers/tty/n_gsm.c4
-rw-r--r--drivers/tty/tty_port.c27
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)
mutex_lock(&port->mutex);
mxser_close_port(port);
mxser_flush_buffer(tty);
+ if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
+ if (C_HUPCL(tty))
+ tty_port_lower_dtr_rts(port);
+ }
mxser_shutdown_port(port);
clear_bit(ASYNCB_INITIALIZED, &port->flags);
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)
if (tty_port_close_start(&dlci->port, tty, filp) == 0)
goto out;
gsm_dlci_begin_close(dlci);
+ if (test_bit(ASYNCB_INITIALIZED, &dlci->port.flags)) {
+ if (C_HUPCL(tty))
+ tty_port_lower_dtr_rts(&dlci->port);
+ }
tty_port_close_end(&dlci->port, tty);
tty_port_tty_set(&dlci->port, NULL);
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)
}
EXPORT_SYMBOL(tty_port_tty_set);
-static void tty_port_shutdown(struct tty_port *port)
+static void tty_port_shutdown(struct tty_port *port, struct tty_struct *tty)
{
mutex_lock(&port->mutex);
if (port->console)
goto out;
if (test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) {
+ /*
+ * Drop DTR/RTS if HUPCL is set. This causes any attached
+ * modem to hang up the line.
+ */
+ if (tty && C_HUPCL(tty))
+ tty_port_lower_dtr_rts(port);
+
if (port->ops->shutdown)
port->ops->shutdown(port);
}
@@ -220,18 +227,19 @@ out:
void tty_port_hangup(struct tty_port *port)
{
+ struct tty_struct *tty;
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
port->count = 0;
port->flags &= ~ASYNC_NORMAL_ACTIVE;
- if (port->tty) {
- set_bit(TTY_IO_ERROR, &port->tty->flags);
- tty_kref_put(port->tty);
- }
+ tty = port->tty;
+ if (tty)
+ set_bit(TTY_IO_ERROR, &tty->flags);
port->tty = NULL;
spin_unlock_irqrestore(&port->lock, flags);
- tty_port_shutdown(port);
+ tty_port_shutdown(port, tty);
+ tty_kref_put(tty);
wake_up_interruptible(&port->open_wait);
wake_up_interruptible(&port->delta_msr_wait);
}
@@ -485,11 +493,6 @@ int tty_port_close_start(struct tty_port *port,
/* Flush the ldisc buffering */
tty_ldisc_flush(tty);
- /* Drop DTR/RTS if HUPCL is set. This causes any attached modem to
- hang up the line */
- if (tty->termios.c_cflag & HUPCL)
- tty_port_lower_dtr_rts(port);
-
/* Don't call port->drop for the last reference. Callers will want
to drop the last active reference in ->shutdown() or the tty
shutdown path */
@@ -524,7 +527,7 @@ void tty_port_close(struct tty_port *port, struct tty_struct *tty,
{
if (tty_port_close_start(port, tty, filp) == 0)
return;
- tty_port_shutdown(port);
+ tty_port_shutdown(port, tty);
set_bit(TTY_IO_ERROR, &tty->flags);
tty_port_close_end(port, tty);
tty_port_tty_set(port, NULL);