aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2015-11-08 09:29:38 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-12-13 22:59:48 -0500
commit63d8cb3f19dabb409a09b4f2b8827934ab9365a3 (patch)
treee6e253f2730c9cb0c1c152e8fb057ff95d5e139a /drivers/tty
parent5841fc4b136b8dbab551749d2b12d71628f34635 (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.c42
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); 573out:
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 579err:
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}