diff options
author | Hendrik Brueckner <brueckner@linux.vnet.ibm.com> | 2014-01-17 08:42:00 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2014-01-22 08:02:13 -0500 |
commit | f1206bad2557de8868878a188cf5c506bb676ff7 (patch) | |
tree | b044ea8c9f4bfd9611e5a6eb5906bbf732e31c2a | |
parent | 2ee13c6e98011200058686ad45219532c871afeb (diff) |
s390/hvc_iucv: Display connection details through device attributes
Add device attributes to display details about the connection status
of HVC IUCV terminals.
Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | drivers/tty/hvc/hvc_iucv.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c index ba6b3f4b15df..fbd023cee4ba 100644 --- a/drivers/tty/hvc/hvc_iucv.c +++ b/drivers/tty/hvc/hvc_iucv.c | |||
@@ -77,6 +77,7 @@ struct hvc_iucv_private { | |||
77 | struct list_head tty_outqueue; /* outgoing IUCV messages */ | 77 | struct list_head tty_outqueue; /* outgoing IUCV messages */ |
78 | struct list_head tty_inqueue; /* incoming IUCV messages */ | 78 | struct list_head tty_inqueue; /* incoming IUCV messages */ |
79 | struct device *dev; /* device structure */ | 79 | struct device *dev; /* device structure */ |
80 | u8 info_path[16]; /* IUCV path info (dev attr) */ | ||
80 | }; | 81 | }; |
81 | 82 | ||
82 | struct iucv_tty_buffer { | 83 | struct iucv_tty_buffer { |
@@ -826,6 +827,10 @@ static int hvc_iucv_path_pending(struct iucv_path *path, | |||
826 | priv->path = path; | 827 | priv->path = path; |
827 | priv->iucv_state = IUCV_CONNECTED; | 828 | priv->iucv_state = IUCV_CONNECTED; |
828 | 829 | ||
830 | /* store path information */ | ||
831 | memcpy(priv->info_path, ipvmid, 8); | ||
832 | memcpy(priv->info_path + 8, ipuser + 8, 8); | ||
833 | |||
829 | /* flush buffered output data... */ | 834 | /* flush buffered output data... */ |
830 | schedule_delayed_work(&priv->sndbuf_work, 5); | 835 | schedule_delayed_work(&priv->sndbuf_work, 5); |
831 | 836 | ||
@@ -960,6 +965,49 @@ static int hvc_iucv_pm_restore_thaw(struct device *dev) | |||
960 | return 0; | 965 | return 0; |
961 | } | 966 | } |
962 | 967 | ||
968 | static ssize_t hvc_iucv_dev_termid_show(struct device *dev, | ||
969 | struct device_attribute *attr, | ||
970 | char *buf) | ||
971 | { | ||
972 | struct hvc_iucv_private *priv = dev_get_drvdata(dev); | ||
973 | size_t len; | ||
974 | |||
975 | len = sizeof(priv->srv_name); | ||
976 | memcpy(buf, priv->srv_name, len); | ||
977 | EBCASC(buf, len); | ||
978 | buf[len++] = '\n'; | ||
979 | return len; | ||
980 | } | ||
981 | |||
982 | static ssize_t hvc_iucv_dev_state_show(struct device *dev, | ||
983 | struct device_attribute *attr, | ||
984 | char *buf) | ||
985 | { | ||
986 | struct hvc_iucv_private *priv = dev_get_drvdata(dev); | ||
987 | return sprintf(buf, "%u:%u\n", priv->iucv_state, priv->tty_state); | ||
988 | } | ||
989 | |||
990 | static ssize_t hvc_iucv_dev_peer_show(struct device *dev, | ||
991 | struct device_attribute *attr, | ||
992 | char *buf) | ||
993 | { | ||
994 | struct hvc_iucv_private *priv = dev_get_drvdata(dev); | ||
995 | char vmid[9], ipuser[9]; | ||
996 | |||
997 | memset(vmid, 0, sizeof(vmid)); | ||
998 | memset(ipuser, 0, sizeof(ipuser)); | ||
999 | |||
1000 | spin_lock_bh(&priv->lock); | ||
1001 | if (priv->iucv_state == IUCV_CONNECTED) { | ||
1002 | memcpy(vmid, priv->info_path, 8); | ||
1003 | memcpy(ipuser, priv->info_path + 8, 8); | ||
1004 | } | ||
1005 | spin_unlock_bh(&priv->lock); | ||
1006 | EBCASC(ipuser, 8); | ||
1007 | |||
1008 | return sprintf(buf, "%s:%s\n", vmid, ipuser); | ||
1009 | } | ||
1010 | |||
963 | 1011 | ||
964 | /* HVC operations */ | 1012 | /* HVC operations */ |
965 | static const struct hv_ops hvc_iucv_ops = { | 1013 | static const struct hv_ops hvc_iucv_ops = { |
@@ -985,6 +1033,25 @@ static struct device_driver hvc_iucv_driver = { | |||
985 | .pm = &hvc_iucv_pm_ops, | 1033 | .pm = &hvc_iucv_pm_ops, |
986 | }; | 1034 | }; |
987 | 1035 | ||
1036 | /* IUCV HVC device attributes */ | ||
1037 | static DEVICE_ATTR(termid, 0640, hvc_iucv_dev_termid_show, NULL); | ||
1038 | static DEVICE_ATTR(state, 0640, hvc_iucv_dev_state_show, NULL); | ||
1039 | static DEVICE_ATTR(peer, 0640, hvc_iucv_dev_peer_show, NULL); | ||
1040 | static struct attribute *hvc_iucv_dev_attrs[] = { | ||
1041 | &dev_attr_termid.attr, | ||
1042 | &dev_attr_state.attr, | ||
1043 | &dev_attr_peer.attr, | ||
1044 | NULL, | ||
1045 | }; | ||
1046 | static struct attribute_group hvc_iucv_dev_attr_group = { | ||
1047 | .attrs = hvc_iucv_dev_attrs, | ||
1048 | }; | ||
1049 | static const struct attribute_group *hvc_iucv_dev_attr_groups[] = { | ||
1050 | &hvc_iucv_dev_attr_group, | ||
1051 | NULL, | ||
1052 | }; | ||
1053 | |||
1054 | |||
988 | /** | 1055 | /** |
989 | * hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance | 1056 | * hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance |
990 | * @id: hvc_iucv_table index | 1057 | * @id: hvc_iucv_table index |
@@ -1046,6 +1113,7 @@ static int __init hvc_iucv_alloc(int id, unsigned int is_console) | |||
1046 | priv->dev->bus = &iucv_bus; | 1113 | priv->dev->bus = &iucv_bus; |
1047 | priv->dev->parent = iucv_root; | 1114 | priv->dev->parent = iucv_root; |
1048 | priv->dev->driver = &hvc_iucv_driver; | 1115 | priv->dev->driver = &hvc_iucv_driver; |
1116 | priv->dev->groups = hvc_iucv_dev_attr_groups; | ||
1049 | priv->dev->release = (void (*)(struct device *)) kfree; | 1117 | priv->dev->release = (void (*)(struct device *)) kfree; |
1050 | rc = device_register(priv->dev); | 1118 | rc = device_register(priv->dev); |
1051 | if (rc) { | 1119 | if (rc) { |