aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/hvc_iucv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/hvc_iucv.c')
-rw-r--r--drivers/char/hvc_iucv.c40
1 files changed, 28 insertions, 12 deletions
diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c
index 7b627368caac..a53496828b76 100644
--- a/drivers/char/hvc_iucv.c
+++ b/drivers/char/hvc_iucv.c
@@ -60,6 +60,7 @@ enum tty_state_t {
60struct hvc_iucv_private { 60struct hvc_iucv_private {
61 struct hvc_struct *hvc; /* HVC struct reference */ 61 struct hvc_struct *hvc; /* HVC struct reference */
62 u8 srv_name[8]; /* IUCV service name (ebcdic) */ 62 u8 srv_name[8]; /* IUCV service name (ebcdic) */
63 unsigned char is_console; /* Linux console usage flag */
63 enum iucv_state_t iucv_state; /* IUCV connection status */ 64 enum iucv_state_t iucv_state; /* IUCV connection status */
64 enum tty_state_t tty_state; /* TTY status */ 65 enum tty_state_t tty_state; /* TTY status */
65 struct iucv_path *path; /* IUCV path pointer */ 66 struct iucv_path *path; /* IUCV path pointer */
@@ -93,6 +94,7 @@ static unsigned long hvc_iucv_devices = 1;
93 94
94/* Array of allocated hvc iucv tty lines... */ 95/* Array of allocated hvc iucv tty lines... */
95static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES]; 96static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES];
97#define IUCV_HVC_CON_IDX (0)
96 98
97/* Kmem cache and mempool for iucv_tty_buffer elements */ 99/* Kmem cache and mempool for iucv_tty_buffer elements */
98static struct kmem_cache *hvc_iucv_buffer_cache; 100static struct kmem_cache *hvc_iucv_buffer_cache;
@@ -139,7 +141,7 @@ static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags)
139 bufp = mempool_alloc(hvc_iucv_mempool, flags); 141 bufp = mempool_alloc(hvc_iucv_mempool, flags);
140 if (!bufp) 142 if (!bufp)
141 return NULL; 143 return NULL;
142 memset(bufp, 0, sizeof(struct iucv_tty_buffer)); 144 memset(bufp, 0, sizeof(*bufp));
143 145
144 if (size > 0) { 146 if (size > 0) {
145 bufp->msg.length = MSG_SIZE(size); 147 bufp->msg.length = MSG_SIZE(size);
@@ -463,7 +465,7 @@ static int hvc_iucv_put_chars(uint32_t vtermno, const char *buf, int count)
463 * @id: Additional data (originally passed to hvc_alloc): the index of an struct 465 * @id: Additional data (originally passed to hvc_alloc): the index of an struct
464 * hvc_iucv_private instance. 466 * hvc_iucv_private instance.
465 * 467 *
466 * The function sets the tty state to TTY_OPEN for the struct hvc_iucv_private 468 * The function sets the tty state to TTY_OPENED for the struct hvc_iucv_private
467 * instance that is derived from @id. Always returns 0. 469 * instance that is derived from @id. Always returns 0.
468 * 470 *
469 * Locking: struct hvc_iucv_private->lock, spin_lock_bh 471 * Locking: struct hvc_iucv_private->lock, spin_lock_bh
@@ -707,6 +709,9 @@ static void hvc_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
707 709
708 /* If the tty has not yet been opened, clean up the hvc_iucv_private 710 /* If the tty has not yet been opened, clean up the hvc_iucv_private
709 * structure to allow re-connects. 711 * structure to allow re-connects.
712 * This is also done for our console device because console hangups
713 * are handled specially and no notifier is called by HVC.
714 * The tty session is active (TTY_OPEN) and ready for re-connects...
710 * 715 *
711 * If it has been opened, let get_chars() return -EPIPE to signal the 716 * If it has been opened, let get_chars() return -EPIPE to signal the
712 * HVC layer to hang up the tty. 717 * HVC layer to hang up the tty.
@@ -716,7 +721,11 @@ static void hvc_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
716 if (priv->tty_state == TTY_CLOSED) 721 if (priv->tty_state == TTY_CLOSED)
717 hvc_iucv_cleanup(priv); 722 hvc_iucv_cleanup(priv);
718 else 723 else
719 hvc_kick(); 724 if (priv->is_console) {
725 hvc_iucv_cleanup(priv);
726 priv->tty_state = TTY_OPENED;
727 } else
728 hvc_kick();
720 spin_unlock(&priv->lock); 729 spin_unlock(&priv->lock);
721 730
722 /* finally sever path (outside of priv->lock due to lock ordering) */ 731 /* finally sever path (outside of priv->lock due to lock ordering) */
@@ -747,7 +756,6 @@ static void hvc_iucv_msg_pending(struct iucv_path *path,
747 return; 756 return;
748 } 757 }
749 758
750
751 spin_lock(&priv->lock); 759 spin_lock(&priv->lock);
752 760
753 /* reject messages if tty has not yet been opened */ 761 /* reject messages if tty has not yet been opened */
@@ -814,13 +822,14 @@ static struct hv_ops hvc_iucv_ops = {
814 822
815/** 823/**
816 * hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance 824 * hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance
817 * @id: hvc_iucv_table index 825 * @id: hvc_iucv_table index
826 * @is_console: Flag if the instance is used as Linux console
818 * 827 *
819 * This function allocates a new hvc_iucv_private structure and stores 828 * This function allocates a new hvc_iucv_private structure and stores
820 * the instance in hvc_iucv_table at index @id. 829 * the instance in hvc_iucv_table at index @id.
821 * Returns 0 on success; otherwise non-zero. 830 * Returns 0 on success; otherwise non-zero.
822 */ 831 */
823static int __init hvc_iucv_alloc(int id) 832static int __init hvc_iucv_alloc(int id, unsigned int is_console)
824{ 833{
825 struct hvc_iucv_private *priv; 834 struct hvc_iucv_private *priv;
826 char name[9]; 835 char name[9];
@@ -842,6 +851,9 @@ static int __init hvc_iucv_alloc(int id)
842 return -ENOMEM; 851 return -ENOMEM;
843 } 852 }
844 853
854 /* set console flag */
855 priv->is_console = is_console;
856
845 /* finally allocate hvc */ 857 /* finally allocate hvc */
846 priv->hvc = hvc_alloc(HVC_IUCV_MAGIC + id, /* PAGE_SIZE */ 858 priv->hvc = hvc_alloc(HVC_IUCV_MAGIC + id, /* PAGE_SIZE */
847 HVC_IUCV_MAGIC + id, &hvc_iucv_ops, 256); 859 HVC_IUCV_MAGIC + id, &hvc_iucv_ops, 256);
@@ -869,7 +881,8 @@ static int __init hvc_iucv_alloc(int id)
869 */ 881 */
870static int __init hvc_iucv_init(void) 882static int __init hvc_iucv_init(void)
871{ 883{
872 int rc, i; 884 int rc;
885 unsigned int i;
873 886
874 if (!MACHINE_IS_VM) { 887 if (!MACHINE_IS_VM) {
875 pr_info("The z/VM IUCV HVC device driver cannot " 888 pr_info("The z/VM IUCV HVC device driver cannot "
@@ -901,14 +914,16 @@ static int __init hvc_iucv_init(void)
901 914
902 /* register the first terminal device as console 915 /* register the first terminal device as console
903 * (must be done before allocating hvc terminal devices) */ 916 * (must be done before allocating hvc terminal devices) */
904 rc = hvc_instantiate(HVC_IUCV_MAGIC, 0, &hvc_iucv_ops); 917 rc = hvc_instantiate(HVC_IUCV_MAGIC, IUCV_HVC_CON_IDX, &hvc_iucv_ops);
905 if (rc) 918 if (rc) {
906 pr_warning("Registering HVC terminal device as " 919 pr_err("Registering HVC terminal device as "
907 "Linux console failed\n"); 920 "Linux console failed\n");
921 goto out_error_memory;
922 }
908 923
909 /* allocate hvc_iucv_private structs */ 924 /* allocate hvc_iucv_private structs */
910 for (i = 0; i < hvc_iucv_devices; i++) { 925 for (i = 0; i < hvc_iucv_devices; i++) {
911 rc = hvc_iucv_alloc(i); 926 rc = hvc_iucv_alloc(i, (i == IUCV_HVC_CON_IDX) ? 1 : 0);
912 if (rc) { 927 if (rc) {
913 pr_err("Creating a new HVC terminal device " 928 pr_err("Creating a new HVC terminal device "
914 "failed with error code=%d\n", rc); 929 "failed with error code=%d\n", rc);
@@ -935,6 +950,7 @@ out_error_hvc:
935 hvc_remove(hvc_iucv_table[i]->hvc); 950 hvc_remove(hvc_iucv_table[i]->hvc);
936 kfree(hvc_iucv_table[i]); 951 kfree(hvc_iucv_table[i]);
937 } 952 }
953out_error_memory:
938 mempool_destroy(hvc_iucv_mempool); 954 mempool_destroy(hvc_iucv_mempool);
939 kmem_cache_destroy(hvc_iucv_buffer_cache); 955 kmem_cache_destroy(hvc_iucv_buffer_cache);
940 return rc; 956 return rc;