aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/tty_port.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c
index 9769b1149f76..549bd0fa8bb6 100644
--- a/drivers/char/tty_port.c
+++ b/drivers/char/tty_port.c
@@ -96,6 +96,14 @@ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
96} 96}
97EXPORT_SYMBOL(tty_port_tty_set); 97EXPORT_SYMBOL(tty_port_tty_set);
98 98
99static void tty_port_shutdown(struct tty_port *port)
100{
101 if (port->ops->shutdown &&
102 test_and_clear_bit(ASYNC_INITIALIZED, &port->flags))
103 port->ops->shutdown(port);
104
105}
106
99/** 107/**
100 * tty_port_hangup - hangup helper 108 * tty_port_hangup - hangup helper
101 * @port: tty port 109 * @port: tty port
@@ -116,6 +124,7 @@ void tty_port_hangup(struct tty_port *port)
116 port->tty = NULL; 124 port->tty = NULL;
117 spin_unlock_irqrestore(&port->lock, flags); 125 spin_unlock_irqrestore(&port->lock, flags);
118 wake_up_interruptible(&port->open_wait); 126 wake_up_interruptible(&port->open_wait);
127 tty_port_shutdown(port);
119} 128}
120EXPORT_SYMBOL(tty_port_hangup); 129EXPORT_SYMBOL(tty_port_hangup);
121 130
@@ -296,15 +305,17 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f
296 305
297 if (port->count) { 306 if (port->count) {
298 spin_unlock_irqrestore(&port->lock, flags); 307 spin_unlock_irqrestore(&port->lock, flags);
308 if (port->ops->drop)
309 port->ops->drop(port);
299 return 0; 310 return 0;
300 } 311 }
301 port->flags |= ASYNC_CLOSING; 312 set_bit(ASYNC_CLOSING, &port->flags);
302 tty->closing = 1; 313 tty->closing = 1;
303 spin_unlock_irqrestore(&port->lock, flags); 314 spin_unlock_irqrestore(&port->lock, flags);
304 /* Don't block on a stalled port, just pull the chain */ 315 /* Don't block on a stalled port, just pull the chain */
305 if (tty->flow_stopped) 316 if (tty->flow_stopped)
306 tty_driver_flush_buffer(tty); 317 tty_driver_flush_buffer(tty);
307 if (port->flags & ASYNC_INITIALIZED && 318 if (test_bit(ASYNCB_INITIALIZED, &port->flags) &&
308 port->closing_wait != ASYNC_CLOSING_WAIT_NONE) 319 port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
309 tty_wait_until_sent(tty, port->closing_wait); 320 tty_wait_until_sent(tty, port->closing_wait);
310 if (port->drain_delay) { 321 if (port->drain_delay) {
@@ -318,6 +329,9 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f
318 timeout = 2 * HZ; 329 timeout = 2 * HZ;
319 schedule_timeout_interruptible(timeout); 330 schedule_timeout_interruptible(timeout);
320 } 331 }
332 /* Don't call port->drop for the last reference. Callers will want
333 to drop the last active reference in ->shutdown() or the tty
334 shutdown path */
321 return 1; 335 return 1;
322} 336}
323EXPORT_SYMBOL(tty_port_close_start); 337EXPORT_SYMBOL(tty_port_close_start);
@@ -348,3 +362,14 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
348 spin_unlock_irqrestore(&port->lock, flags); 362 spin_unlock_irqrestore(&port->lock, flags);
349} 363}
350EXPORT_SYMBOL(tty_port_close_end); 364EXPORT_SYMBOL(tty_port_close_end);
365
366void tty_port_close(struct tty_port *port, struct tty_struct *tty,
367 struct file *filp)
368{
369 if (tty_port_close_start(port, tty, filp) == 0)
370 return;
371 tty_port_shutdown(port);
372 tty_port_close_end(port, tty);
373 tty_port_tty_set(port, NULL);
374}
375EXPORT_SYMBOL(tty_port_close);