aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-28 12:02:24 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-28 12:02:24 -0500
commite770d73ceb93c235525cb9bbbf1374c9b61a0895 (patch)
treeac72b64d1978fece984c8b5a27442acbef7f172c /drivers
parentbe86497152220677e3e5cb326519e19d727f8674 (diff)
parent07be0382097027cde68d9268cc628741069b5762 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 patches from Martin Schwidefsky: "A new binary interface to be able to query and modify the LPAR scheduler weight and cap settings. Some improvements for the hvc terminal over iucv and a couple of bux fixes" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: s390/hypfs: add interface for diagnose 0x304 s390: wire up sys_sched_setattr/sys_sched_getattr s390/uapi: fix struct statfs64 definition s390/uaccess: remove dead extern declarations, make functions static s390/uaccess: test if current->mm is set before walking page tables s390/zfcpdump: make zfcpdump depend on 64BIT s390/32bit: fix cmpxchg64 s390/xpram: don't modify module parameters s390/zcrypt: remove zcrypt kmsg documentation again s390/hvc_iucv: Automatically assign free HVC terminal devices s390/hvc_iucv: Display connection details through device attributes s390/hvc_iucv: fix sparse warning s390/vmur: Link parent CCW device during UR device creation
Diffstat (limited to 'drivers')
-rw-r--r--drivers/s390/block/xpram.c5
-rw-r--r--drivers/s390/char/sclp_cmd.c5
-rw-r--r--drivers/s390/char/vmur.c4
-rw-r--r--drivers/tty/hvc/hvc_iucv.c103
4 files changed, 105 insertions, 12 deletions
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index 464dd29d06c0..58141f0651f2 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -257,6 +257,7 @@ static int __init xpram_setup_sizes(unsigned long pages)
257 unsigned long mem_needed; 257 unsigned long mem_needed;
258 unsigned long mem_auto; 258 unsigned long mem_auto;
259 unsigned long long size; 259 unsigned long long size;
260 char *sizes_end;
260 int mem_auto_no; 261 int mem_auto_no;
261 int i; 262 int i;
262 263
@@ -275,8 +276,8 @@ static int __init xpram_setup_sizes(unsigned long pages)
275 mem_auto_no = 0; 276 mem_auto_no = 0;
276 for (i = 0; i < xpram_devs; i++) { 277 for (i = 0; i < xpram_devs; i++) {
277 if (sizes[i]) { 278 if (sizes[i]) {
278 size = simple_strtoull(sizes[i], &sizes[i], 0); 279 size = simple_strtoull(sizes[i], &sizes_end, 0);
279 switch (sizes[i][0]) { 280 switch (*sizes_end) {
280 case 'g': 281 case 'g':
281 case 'G': 282 case 'G':
282 size <<= 20; 283 size <<= 20;
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index cb3c4e05a385..49af8eeb90ea 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -700,3 +700,8 @@ out:
700 free_page((unsigned long) sccb); 700 free_page((unsigned long) sccb);
701 return rc; 701 return rc;
702} 702}
703
704bool sclp_has_sprp(void)
705{
706 return !!(sclp_fac84 & 0x2);
707}
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index 64c467998a90..0efb27f6f199 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -922,8 +922,8 @@ static int ur_set_online(struct ccw_device *cdev)
922 goto fail_free_cdev; 922 goto fail_free_cdev;
923 } 923 }
924 924
925 urd->device = device_create(vmur_class, NULL, urd->char_device->dev, 925 urd->device = device_create(vmur_class, &cdev->dev,
926 NULL, "%s", node_id); 926 urd->char_device->dev, NULL, "%s", node_id);
927 if (IS_ERR(urd->device)) { 927 if (IS_ERR(urd->device)) {
928 rc = PTR_ERR(urd->device); 928 rc = PTR_ERR(urd->device);
929 TRACE("ur_set_online: device_create rc=%d\n", rc); 929 TRACE("ur_set_online: device_create rc=%d\n", rc);
diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c
index db19a38c8c69..ea74460f3638 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
82struct iucv_tty_buffer { 83struct iucv_tty_buffer {
@@ -126,7 +127,7 @@ static struct iucv_handler hvc_iucv_handler = {
126 * This function returns the struct hvc_iucv_private instance that corresponds 127 * This function returns the struct hvc_iucv_private instance that corresponds
127 * to the HVC virtual terminal number specified as parameter @num. 128 * to the HVC virtual terminal number specified as parameter @num.
128 */ 129 */
129struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num) 130static struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num)
130{ 131{
131 if ((num < HVC_IUCV_MAGIC) || (num - HVC_IUCV_MAGIC > hvc_iucv_devices)) 132 if ((num < HVC_IUCV_MAGIC) || (num - HVC_IUCV_MAGIC > hvc_iucv_devices))
132 return NULL; 133 return NULL;
@@ -772,18 +773,37 @@ static int hvc_iucv_filter_connreq(u8 ipvmid[8])
772static int hvc_iucv_path_pending(struct iucv_path *path, 773static int hvc_iucv_path_pending(struct iucv_path *path,
773 u8 ipvmid[8], u8 ipuser[16]) 774 u8 ipvmid[8], u8 ipuser[16])
774{ 775{
775 struct hvc_iucv_private *priv; 776 struct hvc_iucv_private *priv, *tmp;
777 u8 wildcard[9] = "lnxhvc ";
778 int i, rc, find_unused;
776 u8 nuser_data[16]; 779 u8 nuser_data[16];
777 u8 vm_user_id[9]; 780 u8 vm_user_id[9];
778 int i, rc;
779 781
782 ASCEBC(wildcard, sizeof(wildcard));
783 find_unused = !memcmp(wildcard, ipuser, 8);
784
785 /* First, check if the pending path request is managed by this
786 * IUCV handler:
787 * - find a disconnected device if ipuser contains the wildcard
788 * - find the device that matches the terminal ID in ipuser
789 */
780 priv = NULL; 790 priv = NULL;
781 for (i = 0; i < hvc_iucv_devices; i++) 791 for (i = 0; i < hvc_iucv_devices; i++) {
782 if (hvc_iucv_table[i] && 792 tmp = hvc_iucv_table[i];
783 (0 == memcmp(hvc_iucv_table[i]->srv_name, ipuser, 8))) { 793 if (!tmp)
784 priv = hvc_iucv_table[i]; 794 continue;
795
796 if (find_unused) {
797 spin_lock(&tmp->lock);
798 if (tmp->iucv_state == IUCV_DISCONN)
799 priv = tmp;
800 spin_unlock(&tmp->lock);
801
802 } else if (!memcmp(tmp->srv_name, ipuser, 8))
803 priv = tmp;
804 if (priv)
785 break; 805 break;
786 } 806 }
787 if (!priv) 807 if (!priv)
788 return -ENODEV; 808 return -ENODEV;
789 809
@@ -826,6 +846,10 @@ static int hvc_iucv_path_pending(struct iucv_path *path,
826 priv->path = path; 846 priv->path = path;
827 priv->iucv_state = IUCV_CONNECTED; 847 priv->iucv_state = IUCV_CONNECTED;
828 848
849 /* store path information */
850 memcpy(priv->info_path, ipvmid, 8);
851 memcpy(priv->info_path + 8, ipuser + 8, 8);
852
829 /* flush buffered output data... */ 853 /* flush buffered output data... */
830 schedule_delayed_work(&priv->sndbuf_work, 5); 854 schedule_delayed_work(&priv->sndbuf_work, 5);
831 855
@@ -960,6 +984,49 @@ static int hvc_iucv_pm_restore_thaw(struct device *dev)
960 return 0; 984 return 0;
961} 985}
962 986
987static ssize_t hvc_iucv_dev_termid_show(struct device *dev,
988 struct device_attribute *attr,
989 char *buf)
990{
991 struct hvc_iucv_private *priv = dev_get_drvdata(dev);
992 size_t len;
993
994 len = sizeof(priv->srv_name);
995 memcpy(buf, priv->srv_name, len);
996 EBCASC(buf, len);
997 buf[len++] = '\n';
998 return len;
999}
1000
1001static ssize_t hvc_iucv_dev_state_show(struct device *dev,
1002 struct device_attribute *attr,
1003 char *buf)
1004{
1005 struct hvc_iucv_private *priv = dev_get_drvdata(dev);
1006 return sprintf(buf, "%u:%u\n", priv->iucv_state, priv->tty_state);
1007}
1008
1009static ssize_t hvc_iucv_dev_peer_show(struct device *dev,
1010 struct device_attribute *attr,
1011 char *buf)
1012{
1013 struct hvc_iucv_private *priv = dev_get_drvdata(dev);
1014 char vmid[9], ipuser[9];
1015
1016 memset(vmid, 0, sizeof(vmid));
1017 memset(ipuser, 0, sizeof(ipuser));
1018
1019 spin_lock_bh(&priv->lock);
1020 if (priv->iucv_state == IUCV_CONNECTED) {
1021 memcpy(vmid, priv->info_path, 8);
1022 memcpy(ipuser, priv->info_path + 8, 8);
1023 }
1024 spin_unlock_bh(&priv->lock);
1025 EBCASC(ipuser, 8);
1026
1027 return sprintf(buf, "%s:%s\n", vmid, ipuser);
1028}
1029
963 1030
964/* HVC operations */ 1031/* HVC operations */
965static const struct hv_ops hvc_iucv_ops = { 1032static const struct hv_ops hvc_iucv_ops = {
@@ -985,6 +1052,25 @@ static struct device_driver hvc_iucv_driver = {
985 .pm = &hvc_iucv_pm_ops, 1052 .pm = &hvc_iucv_pm_ops,
986}; 1053};
987 1054
1055/* IUCV HVC device attributes */
1056static DEVICE_ATTR(termid, 0640, hvc_iucv_dev_termid_show, NULL);
1057static DEVICE_ATTR(state, 0640, hvc_iucv_dev_state_show, NULL);
1058static DEVICE_ATTR(peer, 0640, hvc_iucv_dev_peer_show, NULL);
1059static struct attribute *hvc_iucv_dev_attrs[] = {
1060 &dev_attr_termid.attr,
1061 &dev_attr_state.attr,
1062 &dev_attr_peer.attr,
1063 NULL,
1064};
1065static struct attribute_group hvc_iucv_dev_attr_group = {
1066 .attrs = hvc_iucv_dev_attrs,
1067};
1068static const struct attribute_group *hvc_iucv_dev_attr_groups[] = {
1069 &hvc_iucv_dev_attr_group,
1070 NULL,
1071};
1072
1073
988/** 1074/**
989 * hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance 1075 * hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance
990 * @id: hvc_iucv_table index 1076 * @id: hvc_iucv_table index
@@ -1046,6 +1132,7 @@ static int __init hvc_iucv_alloc(int id, unsigned int is_console)
1046 priv->dev->bus = &iucv_bus; 1132 priv->dev->bus = &iucv_bus;
1047 priv->dev->parent = iucv_root; 1133 priv->dev->parent = iucv_root;
1048 priv->dev->driver = &hvc_iucv_driver; 1134 priv->dev->driver = &hvc_iucv_driver;
1135 priv->dev->groups = hvc_iucv_dev_attr_groups;
1049 priv->dev->release = (void (*)(struct device *)) kfree; 1136 priv->dev->release = (void (*)(struct device *)) kfree;
1050 rc = device_register(priv->dev); 1137 rc = device_register(priv->dev);
1051 if (rc) { 1138 if (rc) {