diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2015-11-08 09:29:38 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-12-13 22:59:48 -0500 |
commit | 63d8cb3f19dabb409a09b4f2b8827934ab9365a3 (patch) | |
tree | e6e253f2730c9cb0c1c152e8fb057ff95d5e139a /drivers/tty | |
parent | 5841fc4b136b8dbab551749d2b12d71628f34635 (diff) |
tty: Simplify tty_set_ldisc() exit handling
Perform common exit for both successful and error exit handling
in tty_set_ldisc(). Fixes unlikely possibility of failing to restart
input kworker when switching to the same line discipline (noop case).
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/tty_ldisc.c | 42 |
1 files changed, 13 insertions, 29 deletions
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 7d43ff12f6e2..9ec125046343 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c | |||
@@ -529,34 +529,21 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
529 | 529 | ||
530 | tty_lock(tty); | 530 | tty_lock(tty); |
531 | retval = tty_ldisc_lock(tty, 5 * HZ); | 531 | retval = tty_ldisc_lock(tty, 5 * HZ); |
532 | if (retval) { | 532 | if (retval) |
533 | tty_ldisc_put(new_ldisc); | 533 | goto err; |
534 | tty_unlock(tty); | ||
535 | return retval; | ||
536 | } | ||
537 | 534 | ||
538 | /* | 535 | /* Check the no-op case */ |
539 | * Check the no-op case | 536 | if (tty->ldisc->ops->num == ldisc) |
540 | */ | 537 | goto out; |
541 | 538 | ||
542 | if (tty->ldisc->ops->num == ldisc) { | 539 | if (test_bit(TTY_HUPPED, &tty->flags)) { |
543 | tty_ldisc_unlock(tty); | 540 | /* We were raced by hangup */ |
544 | tty_ldisc_put(new_ldisc); | 541 | retval = -EIO; |
545 | tty_unlock(tty); | 542 | goto out; |
546 | return 0; | ||
547 | } | 543 | } |
548 | 544 | ||
549 | old_ldisc = tty->ldisc; | 545 | old_ldisc = tty->ldisc; |
550 | 546 | ||
551 | if (test_bit(TTY_HUPPED, &tty->flags)) { | ||
552 | /* We were raced by the hangup method. It will have stomped | ||
553 | the ldisc data and closed the ldisc down */ | ||
554 | tty_ldisc_unlock(tty); | ||
555 | tty_ldisc_put(new_ldisc); | ||
556 | tty_unlock(tty); | ||
557 | return -EIO; | ||
558 | } | ||
559 | |||
560 | /* Shutdown the old discipline. */ | 547 | /* Shutdown the old discipline. */ |
561 | tty_ldisc_close(tty, old_ldisc); | 548 | tty_ldisc_close(tty, old_ldisc); |
562 | 549 | ||
@@ -582,18 +569,15 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
582 | the old ldisc (if it was restored as part of error cleanup | 569 | the old ldisc (if it was restored as part of error cleanup |
583 | above). In either case, releasing a single reference from | 570 | above). In either case, releasing a single reference from |
584 | the old ldisc is correct. */ | 571 | the old ldisc is correct. */ |
585 | 572 | new_ldisc = old_ldisc; | |
586 | tty_ldisc_put(old_ldisc); | 573 | out: |
587 | |||
588 | /* | ||
589 | * Allow ldisc referencing to occur again | ||
590 | */ | ||
591 | tty_ldisc_unlock(tty); | 574 | tty_ldisc_unlock(tty); |
592 | 575 | ||
593 | /* Restart the work queue in case no characters kick it off. Safe if | 576 | /* Restart the work queue in case no characters kick it off. Safe if |
594 | already running */ | 577 | already running */ |
595 | tty_buffer_restart_work(tty->port); | 578 | tty_buffer_restart_work(tty->port); |
596 | 579 | err: | |
580 | tty_ldisc_put(new_ldisc); /* drop the extra reference */ | ||
597 | tty_unlock(tty); | 581 | tty_unlock(tty); |
598 | return retval; | 582 | return retval; |
599 | } | 583 | } |