|
@@ -77,6 +77,7 @@ struct hvc_iucv_private {
|
|
struct list_head tty_outqueue; /* outgoing IUCV messages */
|
|
struct list_head tty_outqueue; /* outgoing IUCV messages */
|
|
struct list_head tty_inqueue; /* incoming IUCV messages */
|
|
struct list_head tty_inqueue; /* incoming IUCV messages */
|
|
struct device *dev; /* device structure */
|
|
struct device *dev; /* device structure */
|
|
|
|
+ u8 info_path[16]; /* IUCV path info (dev attr) */
|
|
};
|
|
};
|
|
|
|
|
|
struct iucv_tty_buffer {
|
|
struct iucv_tty_buffer {
|
|
@@ -826,6 +827,10 @@ static int hvc_iucv_path_pending(struct iucv_path *path,
|
|
priv->path = path;
|
|
priv->path = path;
|
|
priv->iucv_state = IUCV_CONNECTED;
|
|
priv->iucv_state = IUCV_CONNECTED;
|
|
|
|
|
|
|
|
+ /* store path information */
|
|
|
|
+ memcpy(priv->info_path, ipvmid, 8);
|
|
|
|
+ memcpy(priv->info_path + 8, ipuser + 8, 8);
|
|
|
|
+
|
|
/* flush buffered output data... */
|
|
/* flush buffered output data... */
|
|
schedule_delayed_work(&priv->sndbuf_work, 5);
|
|
schedule_delayed_work(&priv->sndbuf_work, 5);
|
|
|
|
|
|
@@ -960,6 +965,49 @@ static int hvc_iucv_pm_restore_thaw(struct device *dev)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static ssize_t hvc_iucv_dev_termid_show(struct device *dev,
|
|
|
|
+ struct device_attribute *attr,
|
|
|
|
+ char *buf)
|
|
|
|
+{
|
|
|
|
+ struct hvc_iucv_private *priv = dev_get_drvdata(dev);
|
|
|
|
+ size_t len;
|
|
|
|
+
|
|
|
|
+ len = sizeof(priv->srv_name);
|
|
|
|
+ memcpy(buf, priv->srv_name, len);
|
|
|
|
+ EBCASC(buf, len);
|
|
|
|
+ buf[len++] = '\n';
|
|
|
|
+ return len;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ssize_t hvc_iucv_dev_state_show(struct device *dev,
|
|
|
|
+ struct device_attribute *attr,
|
|
|
|
+ char *buf)
|
|
|
|
+{
|
|
|
|
+ struct hvc_iucv_private *priv = dev_get_drvdata(dev);
|
|
|
|
+ return sprintf(buf, "%u:%u\n", priv->iucv_state, priv->tty_state);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ssize_t hvc_iucv_dev_peer_show(struct device *dev,
|
|
|
|
+ struct device_attribute *attr,
|
|
|
|
+ char *buf)
|
|
|
|
+{
|
|
|
|
+ struct hvc_iucv_private *priv = dev_get_drvdata(dev);
|
|
|
|
+ char vmid[9], ipuser[9];
|
|
|
|
+
|
|
|
|
+ memset(vmid, 0, sizeof(vmid));
|
|
|
|
+ memset(ipuser, 0, sizeof(ipuser));
|
|
|
|
+
|
|
|
|
+ spin_lock_bh(&priv->lock);
|
|
|
|
+ if (priv->iucv_state == IUCV_CONNECTED) {
|
|
|
|
+ memcpy(vmid, priv->info_path, 8);
|
|
|
|
+ memcpy(ipuser, priv->info_path + 8, 8);
|
|
|
|
+ }
|
|
|
|
+ spin_unlock_bh(&priv->lock);
|
|
|
|
+ EBCASC(ipuser, 8);
|
|
|
|
+
|
|
|
|
+ return sprintf(buf, "%s:%s\n", vmid, ipuser);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
|
|
/* HVC operations */
|
|
/* HVC operations */
|
|
static const struct hv_ops hvc_iucv_ops = {
|
|
static const struct hv_ops hvc_iucv_ops = {
|
|
@@ -985,6 +1033,25 @@ static struct device_driver hvc_iucv_driver = {
|
|
.pm = &hvc_iucv_pm_ops,
|
|
.pm = &hvc_iucv_pm_ops,
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+/* IUCV HVC device attributes */
|
|
|
|
+static DEVICE_ATTR(termid, 0640, hvc_iucv_dev_termid_show, NULL);
|
|
|
|
+static DEVICE_ATTR(state, 0640, hvc_iucv_dev_state_show, NULL);
|
|
|
|
+static DEVICE_ATTR(peer, 0640, hvc_iucv_dev_peer_show, NULL);
|
|
|
|
+static struct attribute *hvc_iucv_dev_attrs[] = {
|
|
|
|
+ &dev_attr_termid.attr,
|
|
|
|
+ &dev_attr_state.attr,
|
|
|
|
+ &dev_attr_peer.attr,
|
|
|
|
+ NULL,
|
|
|
|
+};
|
|
|
|
+static struct attribute_group hvc_iucv_dev_attr_group = {
|
|
|
|
+ .attrs = hvc_iucv_dev_attrs,
|
|
|
|
+};
|
|
|
|
+static const struct attribute_group *hvc_iucv_dev_attr_groups[] = {
|
|
|
|
+ &hvc_iucv_dev_attr_group,
|
|
|
|
+ NULL,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance
|
|
* hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance
|
|
* @id: hvc_iucv_table index
|
|
* @id: hvc_iucv_table index
|
|
@@ -1046,6 +1113,7 @@ static int __init hvc_iucv_alloc(int id, unsigned int is_console)
|
|
priv->dev->bus = &iucv_bus;
|
|
priv->dev->bus = &iucv_bus;
|
|
priv->dev->parent = iucv_root;
|
|
priv->dev->parent = iucv_root;
|
|
priv->dev->driver = &hvc_iucv_driver;
|
|
priv->dev->driver = &hvc_iucv_driver;
|
|
|
|
+ priv->dev->groups = hvc_iucv_dev_attr_groups;
|
|
priv->dev->release = (void (*)(struct device *)) kfree;
|
|
priv->dev->release = (void (*)(struct device *)) kfree;
|
|
rc = device_register(priv->dev);
|
|
rc = device_register(priv->dev);
|
|
if (rc) {
|
|
if (rc) {
|