aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/hvc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/hvc')
-rw-r--r--drivers/tty/hvc/hvc_console.c11
-rw-r--r--drivers/tty/hvc/hvc_console.h3
-rw-r--r--drivers/tty/hvc/hvc_iucv.c64
-rw-r--r--drivers/tty/hvc/hvc_xen.c6
4 files changed, 67 insertions, 17 deletions
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index eb255e807c06..9eba119bcdd3 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -361,7 +361,12 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
361 tty->driver_data = NULL; 361 tty->driver_data = NULL;
362 tty_port_put(&hp->port); 362 tty_port_put(&hp->port);
363 printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc); 363 printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
364 } 364 } else
365 /* We are ready... raise DTR/RTS */
366 if (C_BAUD(tty))
367 if (hp->ops->dtr_rts)
368 hp->ops->dtr_rts(hp, 1);
369
365 /* Force wakeup of the polling thread */ 370 /* Force wakeup of the polling thread */
366 hvc_kick(); 371 hvc_kick();
367 372
@@ -393,6 +398,10 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
393 /* We are done with the tty pointer now. */ 398 /* We are done with the tty pointer now. */
394 tty_port_tty_set(&hp->port, NULL); 399 tty_port_tty_set(&hp->port, NULL);
395 400
401 if (C_HUPCL(tty))
402 if (hp->ops->dtr_rts)
403 hp->ops->dtr_rts(hp, 0);
404
396 if (hp->ops->notifier_del) 405 if (hp->ops->notifier_del)
397 hp->ops->notifier_del(hp, hp->data); 406 hp->ops->notifier_del(hp, hp->data);
398 407
diff --git a/drivers/tty/hvc/hvc_console.h b/drivers/tty/hvc/hvc_console.h
index 674d23cb919a..913101980827 100644
--- a/drivers/tty/hvc/hvc_console.h
+++ b/drivers/tty/hvc/hvc_console.h
@@ -75,6 +75,9 @@ struct hv_ops {
75 /* tiocmget/set implementation */ 75 /* tiocmget/set implementation */
76 int (*tiocmget)(struct hvc_struct *hp); 76 int (*tiocmget)(struct hvc_struct *hp);
77 int (*tiocmset)(struct hvc_struct *hp, unsigned int set, unsigned int clear); 77 int (*tiocmset)(struct hvc_struct *hp, unsigned int set, unsigned int clear);
78
79 /* Callbacks to handle tty ports */
80 void (*dtr_rts)(struct hvc_struct *hp, int raise);
78}; 81};
79 82
80/* Register a vterm and a slot index for use as a console (console_init) */ 83/* Register a vterm and a slot index for use as a console (console_init) */
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 */
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
index 682210d778bd..e61c36cbb866 100644
--- a/drivers/tty/hvc/hvc_xen.c
+++ b/drivers/tty/hvc/hvc_xen.c
@@ -208,7 +208,7 @@ static int xen_hvm_console_init(void)
208 208
209 info = vtermno_to_xencons(HVC_COOKIE); 209 info = vtermno_to_xencons(HVC_COOKIE);
210 if (!info) { 210 if (!info) {
211 info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL | __GFP_ZERO); 211 info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
212 if (!info) 212 if (!info)
213 return -ENOMEM; 213 return -ENOMEM;
214 } else if (info->intf != NULL) { 214 } else if (info->intf != NULL) {
@@ -257,7 +257,7 @@ static int xen_pv_console_init(void)
257 257
258 info = vtermno_to_xencons(HVC_COOKIE); 258 info = vtermno_to_xencons(HVC_COOKIE);
259 if (!info) { 259 if (!info) {
260 info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL | __GFP_ZERO); 260 info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
261 if (!info) 261 if (!info)
262 return -ENOMEM; 262 return -ENOMEM;
263 } else if (info->intf != NULL) { 263 } else if (info->intf != NULL) {
@@ -284,7 +284,7 @@ static int xen_initial_domain_console_init(void)
284 284
285 info = vtermno_to_xencons(HVC_COOKIE); 285 info = vtermno_to_xencons(HVC_COOKIE);
286 if (!info) { 286 if (!info) {
287 info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL | __GFP_ZERO); 287 info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
288 if (!info) 288 if (!info)
289 return -ENOMEM; 289 return -ENOMEM;
290 } 290 }