aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/hvc/hvc_iucv.c64
1 files changed, 51 insertions, 13 deletions
diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c
index 9d47f50c2755..fd17a9b804b8 100644
--- a/drivers/tty/hvc/hvc_iucv.c
+++ b/drivers/tty/hvc/hvc_iucv.c
@@ -656,21 +656,64 @@ static void hvc_iucv_notifier_hangup(struct hvc_struct *hp, int id)
656} 656}
657 657
658/** 658/**
659 * hvc_iucv_dtr_rts() - HVC notifier for handling DTR/RTS
660 * @hp: Pointer the HVC device (struct hvc_struct)
661 * @raise: Non-zero to raise or zero to lower DTR/RTS lines
662 *
663 * This routine notifies the HVC back-end to raise or lower DTR/RTS
664 * lines. Raising DTR/RTS is ignored. Lowering DTR/RTS indicates to
665 * drop the IUCV connection (similar to hang up the modem).
666 */
667static void hvc_iucv_dtr_rts(struct hvc_struct *hp, int raise)
668{
669 struct hvc_iucv_private *priv;
670 struct iucv_path *path;
671
672 /* Raising the DTR/RTS is ignored as IUCV connections can be
673 * established at any times.
674 */
675 if (raise)
676 return;
677
678 priv = hvc_iucv_get_private(hp->vtermno);
679 if (!priv)
680 return;
681
682 /* Lowering the DTR/RTS lines disconnects an established IUCV
683 * connection.
684 */
685 flush_sndbuf_sync(priv);
686
687 spin_lock_bh(&priv->lock);
688 path = priv->path; /* save reference to IUCV path */
689 priv->path = NULL;
690 priv->iucv_state = IUCV_DISCONN;
691 spin_unlock_bh(&priv->lock);
692
693 /* Sever IUCV path outside of priv->lock due to lock ordering of:
694 * priv->lock <--> iucv_table_lock */
695 if (path) {
696 iucv_path_sever(path, NULL);
697 iucv_path_free(path);
698 }
699}
700
701/**
659 * hvc_iucv_notifier_del() - HVC notifier for closing a TTY for the last time. 702 * hvc_iucv_notifier_del() - HVC notifier for closing a TTY for the last time.
660 * @hp: Pointer to the HVC device (struct hvc_struct) 703 * @hp: Pointer to the HVC device (struct hvc_struct)
661 * @id: Additional data (originally passed to hvc_alloc): 704 * @id: Additional data (originally passed to hvc_alloc):
662 * the index of an struct hvc_iucv_private instance. 705 * the index of an struct hvc_iucv_private instance.
663 * 706 *
664 * This routine notifies the HVC back-end that the last tty device fd has been 707 * This routine notifies the HVC back-end that the last tty device fd has been
665 * closed. The function calls hvc_iucv_cleanup() to clean up the struct 708 * closed. The function cleans up tty resources. The clean-up of the IUCV
666 * hvc_iucv_private instance. 709 * connection is done in hvc_iucv_dtr_rts() and depends on the HUPCL termios
710 * control setting.
667 * 711 *
668 * Locking: struct hvc_iucv_private->lock 712 * Locking: struct hvc_iucv_private->lock
669 */ 713 */
670static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id) 714static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id)
671{ 715{
672 struct hvc_iucv_private *priv; 716 struct hvc_iucv_private *priv;
673 struct iucv_path *path;
674 717
675 priv = hvc_iucv_get_private(id); 718 priv = hvc_iucv_get_private(id);
676 if (!priv) 719 if (!priv)
@@ -679,17 +722,11 @@ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id)
679 flush_sndbuf_sync(priv); 722 flush_sndbuf_sync(priv);
680 723
681 spin_lock_bh(&priv->lock); 724 spin_lock_bh(&priv->lock);
682 path = priv->path; /* save reference to IUCV path */ 725 destroy_tty_buffer_list(&priv->tty_outqueue);
683 priv->path = NULL; 726 destroy_tty_buffer_list(&priv->tty_inqueue);
684 hvc_iucv_cleanup(priv); 727 priv->tty_state = TTY_CLOSED;
728 priv->sndbuf_len = 0;
685 spin_unlock_bh(&priv->lock); 729 spin_unlock_bh(&priv->lock);
686
687 /* sever IUCV path outside of priv->lock due to lock ordering of:
688 * priv->lock <--> iucv_table_lock */
689 if (path) {
690 iucv_path_sever(path, NULL);
691 iucv_path_free(path);
692 }
693} 730}
694 731
695/** 732/**
@@ -931,6 +968,7 @@ static const struct hv_ops hvc_iucv_ops = {
931 .notifier_add = hvc_iucv_notifier_add, 968 .notifier_add = hvc_iucv_notifier_add,
932 .notifier_del = hvc_iucv_notifier_del, 969 .notifier_del = hvc_iucv_notifier_del,
933 .notifier_hangup = hvc_iucv_notifier_hangup, 970 .notifier_hangup = hvc_iucv_notifier_hangup,
971 .dtr_rts = hvc_iucv_dtr_rts,
934}; 972};
935 973
936/* Suspend / resume device operations */ 974/* Suspend / resume device operations */