Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Peter Hurley and committed by
Greg Kroah-Hartman
fef062cb 79c1faa4

+11 -142
-9
drivers/tty/cyclades.c
··· 1577 1577 #endif 1578 1578 1579 1579 /* 1580 - * If the port is the middle of closing, bail out now 1581 - */ 1582 - if (info->port.flags & ASYNC_CLOSING) { 1583 - wait_event_interruptible_tty(tty, info->port.close_wait, 1584 - !(info->port.flags & ASYNC_CLOSING)); 1585 - return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; 1586 - } 1587 - 1588 - /* 1589 1580 * Start up serial port 1590 1581 */ 1591 1582 retval = cy_startup(info, tty);
-12
drivers/tty/rocket.c
··· 895 895 if (!page) 896 896 return -ENOMEM; 897 897 898 - if (port->flags & ASYNC_CLOSING) { 899 - retval = wait_for_completion_interruptible(&info->close_wait); 900 - free_page(page); 901 - if (retval) 902 - return retval; 903 - return ((port->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); 904 - } 905 - 906 898 /* 907 899 * We must not sleep from here until the port is marked fully in use. 908 900 */ ··· 1503 1511 #endif 1504 1512 rp_flush_buffer(tty); 1505 1513 spin_lock_irqsave(&info->port.lock, flags); 1506 - if (info->port.flags & ASYNC_CLOSING) { 1507 - spin_unlock_irqrestore(&info->port.lock, flags); 1508 - return; 1509 - } 1510 1514 if (info->port.count) 1511 1515 atomic_dec(&rp_num_ports_open); 1512 1516 clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
+1 -32
drivers/tty/serial/crisv10.c
··· 3759 3759 int do_clocal = 0; 3760 3760 3761 3761 /* 3762 - * If the device is in the middle of being closed, then block 3763 - * until it's done, and then try again. 3764 - */ 3765 - if (info->port.flags & ASYNC_CLOSING) { 3766 - wait_event_interruptible_tty(tty, info->port.close_wait, 3767 - !(info->port.flags & ASYNC_CLOSING)); 3768 - #ifdef SERIAL_DO_RESTART 3769 - if (info->port.flags & ASYNC_HUP_NOTIFY) 3770 - return -EAGAIN; 3771 - else 3772 - return -ERESTARTSYS; 3773 - #else 3774 - return -EAGAIN; 3775 - #endif 3776 - } 3777 - 3778 - /* 3779 3762 * If non-blocking mode is set, or the port is not enabled, 3780 3763 * then make the check up front and then exit. 3781 3764 */ ··· 3808 3825 #endif 3809 3826 break; 3810 3827 } 3811 - if (!(info->port.flags & ASYNC_CLOSING) && do_clocal) 3828 + if (do_clocal) 3812 3829 /* && (do_clocal || DCD_IS_ASSERTED) */ 3813 3830 break; 3814 3831 if (signal_pending(current)) { ··· 3876 3893 info->port.tty = tty; 3877 3894 3878 3895 info->port.low_latency = !!(info->port.flags & ASYNC_LOW_LATENCY); 3879 - 3880 - /* 3881 - * If the port is in the middle of closing, bail out now 3882 - */ 3883 - if (info->port.flags & ASYNC_CLOSING) { 3884 - wait_event_interruptible_tty(tty, info->port.close_wait, 3885 - !(info->port.flags & ASYNC_CLOSING)); 3886 - #ifdef SERIAL_DO_RESTART 3887 - return ((info->port.flags & ASYNC_HUP_NOTIFY) ? 3888 - -EAGAIN : -ERESTARTSYS); 3889 - #else 3890 - return -EAGAIN; 3891 - #endif 3892 - } 3893 3896 3894 3897 /* 3895 3898 * If DMA is enabled try to allocate the irq's.
+4 -14
drivers/tty/synclink.c
··· 3314 3314 -EAGAIN : -ERESTARTSYS; 3315 3315 break; 3316 3316 } 3317 - 3317 + 3318 3318 dcd = tty_port_carrier_raised(&info->port); 3319 - 3320 - if (!(port->flags & ASYNC_CLOSING) && (do_clocal || dcd)) 3321 - break; 3322 - 3319 + if (do_clocal || dcd) 3320 + break; 3321 + 3323 3322 if (signal_pending(current)) { 3324 3323 retval = -ERESTARTSYS; 3325 3324 break; ··· 3397 3398 printk("%s(%d):mgsl_open(%s), old ref count = %d\n", 3398 3399 __FILE__,__LINE__,tty->driver->name, info->port.count); 3399 3400 3400 - /* If port is closing, signal caller to try again */ 3401 - if (info->port.flags & ASYNC_CLOSING){ 3402 - wait_event_interruptible_tty(tty, info->port.close_wait, 3403 - !(info->port.flags & ASYNC_CLOSING)); 3404 - retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? 3405 - -EAGAIN : -ERESTARTSYS); 3406 - goto cleanup; 3407 - } 3408 - 3409 3401 info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; 3410 3402 3411 3403 spin_lock_irqsave(&info->netlock, flags);
+2 -12
drivers/tty/synclinkmp.c
··· 752 752 printk("%s(%d):%s open(), old ref count = %d\n", 753 753 __FILE__,__LINE__,tty->driver->name, info->port.count); 754 754 755 - /* If port is closing, signal caller to try again */ 756 - if (info->port.flags & ASYNC_CLOSING){ 757 - wait_event_interruptible_tty(tty, info->port.close_wait, 758 - !(info->port.flags & ASYNC_CLOSING)); 759 - retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? 760 - -EAGAIN : -ERESTARTSYS); 761 - goto cleanup; 762 - } 763 - 764 755 info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; 765 756 766 757 spin_lock_irqsave(&info->netlock, flags); ··· 3332 3341 } 3333 3342 3334 3343 cd = tty_port_carrier_raised(port); 3335 - 3336 - if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd)) 3337 - break; 3344 + if (do_clocal || cd) 3345 + break; 3338 3346 3339 3347 if (signal_pending(current)) { 3340 3348 retval = -ERESTARTSYS;
+1 -12
drivers/tty/tty_port.c
··· 363 363 unsigned long flags; 364 364 DEFINE_WAIT(wait); 365 365 366 - /* block if port is in the process of being closed */ 367 - if (port->flags & ASYNC_CLOSING) { 368 - wait_event_interruptible_tty(tty, port->close_wait, 369 - !(port->flags & ASYNC_CLOSING)); 370 - if (port->flags & ASYNC_HUP_NOTIFY) 371 - return -EAGAIN; 372 - else 373 - return -ERESTARTSYS; 374 - } 375 - 376 366 /* if non-blocking mode is set we can pass directly to open unless 377 367 the port has just hung up or is in another error state */ 378 368 if (tty->flags & (1 << TTY_IO_ERROR)) { ··· 413 423 * Never ask drivers if CLOCAL is set, this causes troubles 414 424 * on some hardware. 415 425 */ 416 - if (!(port->flags & ASYNC_CLOSING) && 417 - (do_clocal || tty_port_carrier_raised(port))) 426 + if (do_clocal || tty_port_carrier_raised(port)) 418 427 break; 419 428 if (signal_pending(current)) { 420 429 retval = -ERESTARTSYS;
+1 -30
net/irda/ircomm/ircomm_tty.c
··· 335 335 * specified, we cannot return before the IrCOMM link is 336 336 * ready 337 337 */ 338 - if (!test_bit(ASYNCB_CLOSING, &port->flags) && 339 - (do_clocal || tty_port_carrier_raised(port)) && 338 + if ((do_clocal || tty_port_carrier_raised(port)) && 340 339 self->state == IRCOMM_TTY_READY) 341 340 { 342 341 break; ··· 441 442 442 443 /* Not really used by us, but lets do it anyway */ 443 444 self->port.low_latency = (self->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; 444 - 445 - /* 446 - * If the port is the middle of closing, bail out now 447 - */ 448 - if (test_bit(ASYNCB_CLOSING, &self->port.flags)) { 449 - 450 - /* Hm, why are we blocking on ASYNC_CLOSING if we 451 - * do return -EAGAIN/-ERESTARTSYS below anyway? 452 - * IMHO it's either not needed in the first place 453 - * or for some reason we need to make sure the async 454 - * closing has been finished - if so, wouldn't we 455 - * probably better sleep uninterruptible? 456 - */ 457 - 458 - if (wait_event_interruptible(self->port.close_wait, 459 - !test_bit(ASYNCB_CLOSING, &self->port.flags))) { 460 - net_warn_ratelimited("%s - got signal while blocking on ASYNC_CLOSING!\n", 461 - __func__); 462 - return -ERESTARTSYS; 463 - } 464 - 465 - #ifdef SERIAL_DO_RESTART 466 - return (self->port.flags & ASYNC_HUP_NOTIFY) ? 467 - -EAGAIN : -ERESTARTSYS; 468 - #else 469 - return -EAGAIN; 470 - #endif 471 - } 472 445 473 446 /* Check if this is a "normal" ircomm device, or an irlpt device */ 474 447 if (self->line < 0x10) {