Commit fef062cb authored by Peter Hurley's avatar Peter Hurley Committed by Greg Kroah-Hartman

tty: Remove ASYNC_CLOSING checks in open()/hangup() methods

Since at least before 2.6.30, tty drivers that do not drop the tty lock
while closing cannot observe ASYNC_CLOSING set while holding the
tty lock; this includes the tty driver's open() and hangup() methods,
since the tty core calls these methods holding the tty lock.

For these drivers, waiting for ASYNC_CLOSING to clear while opening
is not required, since this condition cannot occur. Similarly, even
when the open() method drops and reacquires the tty lock after
blocking, ASYNC_CLOSING cannot be set (again, for drivers that
do not drop the tty lock while closing).

Now that tty port drivers no longer drop the tty lock while closing
(since 'tty: Remove tty_wait_until_sent_from_close()'), the same
conditions apply: waiting for ASYNC_CLOSING to clear while opening
is not required, nor is re-checking ASYNC_CLOSING after dropping and
reacquiring the tty lock while blocking (eg., in *_block_til_ready()).

Note: The ASYNC_CLOSING flag state is still maintained since several
bitrotting drivers use it for (dubious) other purposes.
Signed-off-by: default avatarPeter Hurley <peter@hurleysoftware.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 79c1faa4
...@@ -2507,15 +2507,6 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) ...@@ -2507,15 +2507,6 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
printk("%s(%d):mgslpc_open(%s), old ref count = %d\n", printk("%s(%d):mgslpc_open(%s), old ref count = %d\n",
__FILE__, __LINE__, tty->driver->name, port->count); __FILE__, __LINE__, tty->driver->name, port->count);
/* If port is closing, signal caller to try again */
if (port->flags & ASYNC_CLOSING){
wait_event_interruptible_tty(tty, port->close_wait,
!(port->flags & ASYNC_CLOSING));
retval = ((port->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS);
goto cleanup;
}
port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
spin_lock_irqsave(&info->netlock, flags); spin_lock_irqsave(&info->netlock, flags);
......
...@@ -1576,15 +1576,6 @@ static int cy_open(struct tty_struct *tty, struct file *filp) ...@@ -1576,15 +1576,6 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
current->pid, info->port.count); current->pid, info->port.count);
#endif #endif
/*
* If the port is the middle of closing, bail out now
*/
if (info->port.flags & ASYNC_CLOSING) {
wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
}
/* /*
* Start up serial port * Start up serial port
*/ */
......
...@@ -895,14 +895,6 @@ static int rp_open(struct tty_struct *tty, struct file *filp) ...@@ -895,14 +895,6 @@ static int rp_open(struct tty_struct *tty, struct file *filp)
if (!page) if (!page)
return -ENOMEM; return -ENOMEM;
if (port->flags & ASYNC_CLOSING) {
retval = wait_for_completion_interruptible(&info->close_wait);
free_page(page);
if (retval)
return retval;
return ((port->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
}
/* /*
* We must not sleep from here until the port is marked fully in use. * We must not sleep from here until the port is marked fully in use.
*/ */
...@@ -1511,10 +1503,6 @@ static void rp_hangup(struct tty_struct *tty) ...@@ -1511,10 +1503,6 @@ static void rp_hangup(struct tty_struct *tty)
#endif #endif
rp_flush_buffer(tty); rp_flush_buffer(tty);
spin_lock_irqsave(&info->port.lock, flags); spin_lock_irqsave(&info->port.lock, flags);
if (info->port.flags & ASYNC_CLOSING) {
spin_unlock_irqrestore(&info->port.lock, flags);
return;
}
if (info->port.count) if (info->port.count)
atomic_dec(&rp_num_ports_open); atomic_dec(&rp_num_ports_open);
clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
......
...@@ -3758,23 +3758,6 @@ block_til_ready(struct tty_struct *tty, struct file * filp, ...@@ -3758,23 +3758,6 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
int retval; int retval;
int do_clocal = 0; int do_clocal = 0;
/*
* If the device is in the middle of being closed, then block
* until it's done, and then try again.
*/
if (info->port.flags & ASYNC_CLOSING) {
wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
if (info->port.flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
else
return -ERESTARTSYS;
#else
return -EAGAIN;
#endif
}
/* /*
* If non-blocking mode is set, or the port is not enabled, * If non-blocking mode is set, or the port is not enabled,
* then make the check up front and then exit. * then make the check up front and then exit.
...@@ -3825,7 +3808,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, ...@@ -3825,7 +3808,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
#endif #endif
break; break;
} }
if (!(info->port.flags & ASYNC_CLOSING) && do_clocal) if (do_clocal)
/* && (do_clocal || DCD_IS_ASSERTED) */ /* && (do_clocal || DCD_IS_ASSERTED) */
break; break;
if (signal_pending(current)) { if (signal_pending(current)) {
...@@ -3894,20 +3877,6 @@ rs_open(struct tty_struct *tty, struct file * filp) ...@@ -3894,20 +3877,6 @@ rs_open(struct tty_struct *tty, struct file * filp)
info->port.low_latency = !!(info->port.flags & ASYNC_LOW_LATENCY); info->port.low_latency = !!(info->port.flags & ASYNC_LOW_LATENCY);
/*
* If the port is in the middle of closing, bail out now
*/
if (info->port.flags & ASYNC_CLOSING) {
wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
return ((info->port.flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS);
#else
return -EAGAIN;
#endif
}
/* /*
* If DMA is enabled try to allocate the irq's. * If DMA is enabled try to allocate the irq's.
*/ */
......
...@@ -3316,8 +3316,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, ...@@ -3316,8 +3316,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
} }
dcd = tty_port_carrier_raised(&info->port); dcd = tty_port_carrier_raised(&info->port);
if (do_clocal || dcd)
if (!(port->flags & ASYNC_CLOSING) && (do_clocal || dcd))
break; break;
if (signal_pending(current)) { if (signal_pending(current)) {
...@@ -3398,15 +3397,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) ...@@ -3398,15 +3397,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
printk("%s(%d):mgsl_open(%s), old ref count = %d\n", printk("%s(%d):mgsl_open(%s), old ref count = %d\n",
__FILE__,__LINE__,tty->driver->name, info->port.count); __FILE__,__LINE__,tty->driver->name, info->port.count);
/* If port is closing, signal caller to try again */
if (info->port.flags & ASYNC_CLOSING){
wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS);
goto cleanup;
}
info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
spin_lock_irqsave(&info->netlock, flags); spin_lock_irqsave(&info->netlock, flags);
......
...@@ -672,15 +672,6 @@ static int open(struct tty_struct *tty, struct file *filp) ...@@ -672,15 +672,6 @@ static int open(struct tty_struct *tty, struct file *filp)
DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count)); DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count));
/* If port is closing, signal caller to try again */
if (info->port.flags & ASYNC_CLOSING){
wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS);
goto cleanup;
}
mutex_lock(&info->port.mutex); mutex_lock(&info->port.mutex);
info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
...@@ -3320,8 +3311,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -3320,8 +3311,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
} }
cd = tty_port_carrier_raised(port); cd = tty_port_carrier_raised(port);
if (do_clocal || cd)
if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd ))
break; break;
if (signal_pending(current)) { if (signal_pending(current)) {
......
...@@ -752,15 +752,6 @@ static int open(struct tty_struct *tty, struct file *filp) ...@@ -752,15 +752,6 @@ static int open(struct tty_struct *tty, struct file *filp)
printk("%s(%d):%s open(), old ref count = %d\n", printk("%s(%d):%s open(), old ref count = %d\n",
__FILE__,__LINE__,tty->driver->name, info->port.count); __FILE__,__LINE__,tty->driver->name, info->port.count);
/* If port is closing, signal caller to try again */
if (info->port.flags & ASYNC_CLOSING){
wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS);
goto cleanup;
}
info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
spin_lock_irqsave(&info->netlock, flags); spin_lock_irqsave(&info->netlock, flags);
...@@ -3341,8 +3332,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -3341,8 +3332,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
} }
cd = tty_port_carrier_raised(port); cd = tty_port_carrier_raised(port);
if (do_clocal || cd)
if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd))
break; break;
if (signal_pending(current)) { if (signal_pending(current)) {
......
...@@ -363,16 +363,6 @@ int tty_port_block_til_ready(struct tty_port *port, ...@@ -363,16 +363,6 @@ int tty_port_block_til_ready(struct tty_port *port,
unsigned long flags; unsigned long flags;
DEFINE_WAIT(wait); DEFINE_WAIT(wait);
/* block if port is in the process of being closed */
if (port->flags & ASYNC_CLOSING) {
wait_event_interruptible_tty(tty, port->close_wait,
!(port->flags & ASYNC_CLOSING));
if (port->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
else
return -ERESTARTSYS;
}
/* if non-blocking mode is set we can pass directly to open unless /* if non-blocking mode is set we can pass directly to open unless
the port has just hung up or is in another error state */ the port has just hung up or is in another error state */
if (tty->flags & (1 << TTY_IO_ERROR)) { if (tty->flags & (1 << TTY_IO_ERROR)) {
...@@ -423,8 +413,7 @@ int tty_port_block_til_ready(struct tty_port *port, ...@@ -423,8 +413,7 @@ int tty_port_block_til_ready(struct tty_port *port,
* Never ask drivers if CLOCAL is set, this causes troubles * Never ask drivers if CLOCAL is set, this causes troubles
* on some hardware. * on some hardware.
*/ */
if (!(port->flags & ASYNC_CLOSING) && if (do_clocal || tty_port_carrier_raised(port))
(do_clocal || tty_port_carrier_raised(port)))
break; break;
if (signal_pending(current)) { if (signal_pending(current)) {
retval = -ERESTARTSYS; retval = -ERESTARTSYS;
......
...@@ -335,8 +335,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, ...@@ -335,8 +335,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
* specified, we cannot return before the IrCOMM link is * specified, we cannot return before the IrCOMM link is
* ready * ready
*/ */
if (!test_bit(ASYNCB_CLOSING, &port->flags) && if ((do_clocal || tty_port_carrier_raised(port)) &&
(do_clocal || tty_port_carrier_raised(port)) &&
self->state == IRCOMM_TTY_READY) self->state == IRCOMM_TTY_READY)
{ {
break; break;
...@@ -443,34 +442,6 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) ...@@ -443,34 +442,6 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
/* Not really used by us, but lets do it anyway */ /* Not really used by us, but lets do it anyway */
self->port.low_latency = (self->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; self->port.low_latency = (self->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
/*
* If the port is the middle of closing, bail out now
*/
if (test_bit(ASYNCB_CLOSING, &self->port.flags)) {
/* Hm, why are we blocking on ASYNC_CLOSING if we
* do return -EAGAIN/-ERESTARTSYS below anyway?
* IMHO it's either not needed in the first place
* or for some reason we need to make sure the async
* closing has been finished - if so, wouldn't we
* probably better sleep uninterruptible?
*/
if (wait_event_interruptible(self->port.close_wait,
!test_bit(ASYNCB_CLOSING, &self->port.flags))) {
net_warn_ratelimited("%s - got signal while blocking on ASYNC_CLOSING!\n",
__func__);
return -ERESTARTSYS;
}
#ifdef SERIAL_DO_RESTART
return (self->port.flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS;
#else
return -EAGAIN;
#endif
}
/* Check if this is a "normal" ircomm device, or an irlpt device */ /* Check if this is a "normal" ircomm device, or an irlpt device */
if (self->line < 0x10) { if (self->line < 0x10) {
self->service_type = IRCOMM_3_WIRE | IRCOMM_9_WIRE; self->service_type = IRCOMM_3_WIRE | IRCOMM_9_WIRE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment