diff options
| -rw-r--r-- | Documentation/ioctl/ioctl-number.txt | 1 | ||||
| -rw-r--r-- | Documentation/kmsg/s390/zcrypt | 20 | ||||
| -rw-r--r-- | arch/s390/Kconfig | 2 | ||||
| -rw-r--r-- | arch/s390/hypfs/Makefile | 2 | ||||
| -rw-r--r-- | arch/s390/hypfs/hypfs.h | 7 | ||||
| -rw-r--r-- | arch/s390/hypfs/hypfs_dbfs.c | 16 | ||||
| -rw-r--r-- | arch/s390/hypfs/hypfs_sprp.c | 141 | ||||
| -rw-r--r-- | arch/s390/hypfs/inode.c | 15 | ||||
| -rw-r--r-- | arch/s390/include/asm/cmpxchg.h | 5 | ||||
| -rw-r--r-- | arch/s390/include/asm/sclp.h | 1 | ||||
| -rw-r--r-- | arch/s390/include/uapi/asm/hypfs.h | 25 | ||||
| -rw-r--r-- | arch/s390/include/uapi/asm/statfs.h | 10 | ||||
| -rw-r--r-- | arch/s390/include/uapi/asm/unistd.h | 2 | ||||
| -rw-r--r-- | arch/s390/kernel/compat_wrapper.S | 11 | ||||
| -rw-r--r-- | arch/s390/kernel/syscalls.S | 2 | ||||
| -rw-r--r-- | arch/s390/lib/uaccess.h | 9 | ||||
| -rw-r--r-- | arch/s390/lib/uaccess_pt.c | 14 | ||||
| -rw-r--r-- | drivers/s390/block/xpram.c | 5 | ||||
| -rw-r--r-- | drivers/s390/char/sclp_cmd.c | 5 | ||||
| -rw-r--r-- | drivers/s390/char/vmur.c | 4 | ||||
| -rw-r--r-- | drivers/tty/hvc/hvc_iucv.c | 103 |
21 files changed, 344 insertions, 56 deletions
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index 7cbfa3c4fc3d..d7e43fa88575 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt | |||
| @@ -73,6 +73,7 @@ Code Seq#(hex) Include File Comments | |||
| 73 | 0x09 all linux/raid/md_u.h | 73 | 0x09 all linux/raid/md_u.h |
| 74 | 0x10 00-0F drivers/char/s390/vmcp.h | 74 | 0x10 00-0F drivers/char/s390/vmcp.h |
| 75 | 0x10 10-1F arch/s390/include/uapi/sclp_ctl.h | 75 | 0x10 10-1F arch/s390/include/uapi/sclp_ctl.h |
| 76 | 0x10 20-2F arch/s390/include/uapi/asm/hypfs.h | ||
| 76 | 0x12 all linux/fs.h | 77 | 0x12 all linux/fs.h |
| 77 | linux/blkpg.h | 78 | linux/blkpg.h |
| 78 | 0x1b all InfiniBand Subsystem <http://infiniband.sourceforge.net/> | 79 | 0x1b all InfiniBand Subsystem <http://infiniband.sourceforge.net/> |
diff --git a/Documentation/kmsg/s390/zcrypt b/Documentation/kmsg/s390/zcrypt deleted file mode 100644 index 7fb2087409d6..000000000000 --- a/Documentation/kmsg/s390/zcrypt +++ /dev/null | |||
| @@ -1,20 +0,0 @@ | |||
| 1 | /*? | ||
| 2 | * Text: "Cryptographic device %x failed and was set offline\n" | ||
| 3 | * Severity: Error | ||
| 4 | * Parameter: | ||
| 5 | * @1: device index | ||
| 6 | * Description: | ||
| 7 | * A cryptographic device failed to process a cryptographic request. | ||
| 8 | * The cryptographic device driver could not correct the error and | ||
| 9 | * set the device offline. The application that issued the | ||
| 10 | * request received an indication that the request has failed. | ||
| 11 | * User action: | ||
| 12 | * Use the lszcrypt command to confirm that the cryptographic | ||
| 13 | * hardware is still configured to your LPAR or z/VM guest virtual | ||
| 14 | * machine. If the device is available to your Linux instance the | ||
| 15 | * command output contains a line that begins with 'card<device index>', | ||
| 16 | * where <device index> is the two-digit decimal number in the message text. | ||
| 17 | * After ensuring that the device is available, use the chzcrypt command to | ||
| 18 | * set it online again. | ||
| 19 | * If the error persists, contact your support organization. | ||
| 20 | */ | ||
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 4f858f77d870..65a07750f4f9 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
| @@ -596,7 +596,7 @@ config CRASH_DUMP | |||
| 596 | config ZFCPDUMP | 596 | config ZFCPDUMP |
| 597 | def_bool n | 597 | def_bool n |
| 598 | prompt "zfcpdump support" | 598 | prompt "zfcpdump support" |
| 599 | depends on SMP | 599 | depends on 64BIT && SMP |
| 600 | help | 600 | help |
| 601 | Select this option if you want to build an zfcpdump enabled kernel. | 601 | Select this option if you want to build an zfcpdump enabled kernel. |
| 602 | Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this. | 602 | Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this. |
diff --git a/arch/s390/hypfs/Makefile b/arch/s390/hypfs/Makefile index 2e671d5004ca..06f8d95a16cd 100644 --- a/arch/s390/hypfs/Makefile +++ b/arch/s390/hypfs/Makefile | |||
| @@ -4,4 +4,4 @@ | |||
| 4 | 4 | ||
| 5 | obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o | 5 | obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o |
| 6 | 6 | ||
| 7 | s390_hypfs-objs := inode.o hypfs_diag.o hypfs_vm.o hypfs_dbfs.o | 7 | s390_hypfs-objs := inode.o hypfs_diag.o hypfs_vm.o hypfs_dbfs.o hypfs_sprp.o |
diff --git a/arch/s390/hypfs/hypfs.h b/arch/s390/hypfs/hypfs.h index 79f2ac55253f..b34b5ab90a31 100644 --- a/arch/s390/hypfs/hypfs.h +++ b/arch/s390/hypfs/hypfs.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/debugfs.h> | 13 | #include <linux/debugfs.h> |
| 14 | #include <linux/workqueue.h> | 14 | #include <linux/workqueue.h> |
| 15 | #include <linux/kref.h> | 15 | #include <linux/kref.h> |
| 16 | #include <asm/hypfs.h> | ||
| 16 | 17 | ||
| 17 | #define REG_FILE_MODE 0440 | 18 | #define REG_FILE_MODE 0440 |
| 18 | #define UPDATE_FILE_MODE 0220 | 19 | #define UPDATE_FILE_MODE 0220 |
| @@ -36,6 +37,10 @@ extern int hypfs_vm_init(void); | |||
| 36 | extern void hypfs_vm_exit(void); | 37 | extern void hypfs_vm_exit(void); |
| 37 | extern int hypfs_vm_create_files(struct dentry *root); | 38 | extern int hypfs_vm_create_files(struct dentry *root); |
| 38 | 39 | ||
| 40 | /* Set Partition-Resource Parameter */ | ||
| 41 | int hypfs_sprp_init(void); | ||
| 42 | void hypfs_sprp_exit(void); | ||
| 43 | |||
| 39 | /* debugfs interface */ | 44 | /* debugfs interface */ |
| 40 | struct hypfs_dbfs_file; | 45 | struct hypfs_dbfs_file; |
| 41 | 46 | ||
| @@ -52,6 +57,8 @@ struct hypfs_dbfs_file { | |||
| 52 | int (*data_create)(void **data, void **data_free_ptr, | 57 | int (*data_create)(void **data, void **data_free_ptr, |
| 53 | size_t *size); | 58 | size_t *size); |
| 54 | void (*data_free)(const void *buf_free_ptr); | 59 | void (*data_free)(const void *buf_free_ptr); |
| 60 | long (*unlocked_ioctl) (struct file *, unsigned int, | ||
| 61 | unsigned long); | ||
| 55 | 62 | ||
| 56 | /* Private data for hypfs_dbfs.c */ | 63 | /* Private data for hypfs_dbfs.c */ |
| 57 | struct hypfs_dbfs_data *data; | 64 | struct hypfs_dbfs_data *data; |
diff --git a/arch/s390/hypfs/hypfs_dbfs.c b/arch/s390/hypfs/hypfs_dbfs.c index 17ab8b7b53cc..2badf2bf9cd7 100644 --- a/arch/s390/hypfs/hypfs_dbfs.c +++ b/arch/s390/hypfs/hypfs_dbfs.c | |||
| @@ -81,9 +81,25 @@ static ssize_t dbfs_read(struct file *file, char __user *buf, | |||
| 81 | return rc; | 81 | return rc; |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | static long dbfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
| 85 | { | ||
| 86 | struct hypfs_dbfs_file *df; | ||
| 87 | long rc; | ||
| 88 | |||
| 89 | df = file->f_path.dentry->d_inode->i_private; | ||
| 90 | mutex_lock(&df->lock); | ||
| 91 | if (df->unlocked_ioctl) | ||
| 92 | rc = df->unlocked_ioctl(file, cmd, arg); | ||
| 93 | else | ||
| 94 | rc = -ENOTTY; | ||
| 95 | mutex_unlock(&df->lock); | ||
| 96 | return rc; | ||
| 97 | } | ||
| 98 | |||
| 84 | static const struct file_operations dbfs_ops = { | 99 | static const struct file_operations dbfs_ops = { |
| 85 | .read = dbfs_read, | 100 | .read = dbfs_read, |
| 86 | .llseek = no_llseek, | 101 | .llseek = no_llseek, |
| 102 | .unlocked_ioctl = dbfs_ioctl, | ||
| 87 | }; | 103 | }; |
| 88 | 104 | ||
| 89 | int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df) | 105 | int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df) |
diff --git a/arch/s390/hypfs/hypfs_sprp.c b/arch/s390/hypfs/hypfs_sprp.c new file mode 100644 index 000000000000..f043c3c7e73c --- /dev/null +++ b/arch/s390/hypfs/hypfs_sprp.c | |||
| @@ -0,0 +1,141 @@ | |||
| 1 | /* | ||
| 2 | * Hypervisor filesystem for Linux on s390. | ||
| 3 | * Set Partition-Resource Parameter interface. | ||
| 4 | * | ||
| 5 | * Copyright IBM Corp. 2013 | ||
| 6 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/compat.h> | ||
| 10 | #include <linux/errno.h> | ||
| 11 | #include <linux/gfp.h> | ||
| 12 | #include <linux/string.h> | ||
| 13 | #include <linux/types.h> | ||
| 14 | #include <linux/uaccess.h> | ||
| 15 | #include <asm/compat.h> | ||
| 16 | #include <asm/sclp.h> | ||
| 17 | #include "hypfs.h" | ||
| 18 | |||
| 19 | #define DIAG304_SET_WEIGHTS 0 | ||
| 20 | #define DIAG304_QUERY_PRP 1 | ||
| 21 | #define DIAG304_SET_CAPPING 2 | ||
| 22 | |||
| 23 | #define DIAG304_CMD_MAX 2 | ||
| 24 | |||
| 25 | static unsigned long hypfs_sprp_diag304(void *data, unsigned long cmd) | ||
| 26 | { | ||
| 27 | register unsigned long _data asm("2") = (unsigned long) data; | ||
| 28 | register unsigned long _rc asm("3"); | ||
| 29 | register unsigned long _cmd asm("4") = cmd; | ||
| 30 | |||
| 31 | asm volatile("diag %1,%2,0x304\n" | ||
| 32 | : "=d" (_rc) : "d" (_data), "d" (_cmd) : "memory"); | ||
| 33 | |||
| 34 | return _rc; | ||
| 35 | } | ||
| 36 | |||
| 37 | static void hypfs_sprp_free(const void *data) | ||
| 38 | { | ||
| 39 | free_page((unsigned long) data); | ||
| 40 | } | ||
| 41 | |||
| 42 | static int hypfs_sprp_create(void **data_ptr, void **free_ptr, size_t *size) | ||
| 43 | { | ||
| 44 | unsigned long rc; | ||
| 45 | void *data; | ||
| 46 | |||
| 47 | data = (void *) get_zeroed_page(GFP_KERNEL); | ||
| 48 | if (!data) | ||
| 49 | return -ENOMEM; | ||
| 50 | rc = hypfs_sprp_diag304(data, DIAG304_QUERY_PRP); | ||
| 51 | if (rc != 1) { | ||
| 52 | *data_ptr = *free_ptr = NULL; | ||
| 53 | *size = 0; | ||
| 54 | free_page((unsigned long) data); | ||
| 55 | return -EIO; | ||
| 56 | } | ||
| 57 | *data_ptr = *free_ptr = data; | ||
| 58 | *size = PAGE_SIZE; | ||
| 59 | return 0; | ||
| 60 | } | ||
| 61 | |||
| 62 | static int __hypfs_sprp_ioctl(void __user *user_area) | ||
| 63 | { | ||
| 64 | struct hypfs_diag304 diag304; | ||
| 65 | unsigned long cmd; | ||
| 66 | void __user *udata; | ||
| 67 | void *data; | ||
| 68 | int rc; | ||
| 69 | |||
| 70 | if (copy_from_user(&diag304, user_area, sizeof(diag304))) | ||
| 71 | return -EFAULT; | ||
| 72 | if ((diag304.args[0] >> 8) != 0 || diag304.args[1] > DIAG304_CMD_MAX) | ||
| 73 | return -EINVAL; | ||
| 74 | |||
| 75 | data = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); | ||
| 76 | if (!data) | ||
| 77 | return -ENOMEM; | ||
| 78 | |||
| 79 | udata = (void __user *)(unsigned long) diag304.data; | ||
| 80 | if (diag304.args[1] == DIAG304_SET_WEIGHTS || | ||
| 81 | diag304.args[1] == DIAG304_SET_CAPPING) | ||
| 82 | if (copy_from_user(data, udata, PAGE_SIZE)) { | ||
| 83 | rc = -EFAULT; | ||
| 84 | goto out; | ||
| 85 | } | ||
| 86 | |||
| 87 | cmd = *(unsigned long *) &diag304.args[0]; | ||
| 88 | diag304.rc = hypfs_sprp_diag304(data, cmd); | ||
| 89 | |||
| 90 | if (diag304.args[1] == DIAG304_QUERY_PRP) | ||
| 91 | if (copy_to_user(udata, data, PAGE_SIZE)) { | ||
| 92 | rc = -EFAULT; | ||
| 93 | goto out; | ||
| 94 | } | ||
| 95 | |||
| 96 | rc = copy_to_user(user_area, &diag304, sizeof(diag304)) ? -EFAULT : 0; | ||
| 97 | out: | ||
| 98 | free_page((unsigned long) data); | ||
| 99 | return rc; | ||
| 100 | } | ||
| 101 | |||
| 102 | static long hypfs_sprp_ioctl(struct file *file, unsigned int cmd, | ||
| 103 | unsigned long arg) | ||
| 104 | { | ||
| 105 | void __user *argp; | ||
| 106 | |||
| 107 | if (!capable(CAP_SYS_ADMIN)) | ||
| 108 | return -EACCES; | ||
| 109 | if (is_compat_task()) | ||
| 110 | argp = compat_ptr(arg); | ||
| 111 | else | ||
| 112 | argp = (void __user *) arg; | ||
| 113 | switch (cmd) { | ||
| 114 | case HYPFS_DIAG304: | ||
| 115 | return __hypfs_sprp_ioctl(argp); | ||
| 116 | default: /* unknown ioctl number */ | ||
| 117 | return -ENOTTY; | ||
| 118 | } | ||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | static struct hypfs_dbfs_file hypfs_sprp_file = { | ||
| 123 | .name = "diag_304", | ||
| 124 | .data_create = hypfs_sprp_create, | ||
| 125 | .data_free = hypfs_sprp_free, | ||
| 126 | .unlocked_ioctl = hypfs_sprp_ioctl, | ||
| 127 | }; | ||
| 128 | |||
| 129 | int hypfs_sprp_init(void) | ||
| 130 | { | ||
| 131 | if (!sclp_has_sprp()) | ||
| 132 | return 0; | ||
| 133 | return hypfs_dbfs_create_file(&hypfs_sprp_file); | ||
| 134 | } | ||
| 135 | |||
| 136 | void hypfs_sprp_exit(void) | ||
| 137 | { | ||
| 138 | if (!sclp_has_sprp()) | ||
| 139 | return; | ||
| 140 | hypfs_dbfs_remove_file(&hypfs_sprp_file); | ||
| 141 | } | ||
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c index ddfe09b45134..c952b981e4f2 100644 --- a/arch/s390/hypfs/inode.c +++ b/arch/s390/hypfs/inode.c | |||
| @@ -478,10 +478,14 @@ static int __init hypfs_init(void) | |||
| 478 | rc = -ENODATA; | 478 | rc = -ENODATA; |
| 479 | goto fail_hypfs_diag_exit; | 479 | goto fail_hypfs_diag_exit; |
| 480 | } | 480 | } |
| 481 | if (hypfs_sprp_init()) { | ||
| 482 | rc = -ENODATA; | ||
| 483 | goto fail_hypfs_vm_exit; | ||
| 484 | } | ||
| 481 | s390_kobj = kobject_create_and_add("s390", hypervisor_kobj); | 485 | s390_kobj = kobject_create_and_add("s390", hypervisor_kobj); |
| 482 | if (!s390_kobj) { | 486 | if (!s390_kobj) { |
| 483 | rc = -ENOMEM; | 487 | rc = -ENOMEM; |
| 484 | goto fail_hypfs_vm_exit; | 488 | goto fail_hypfs_sprp_exit; |
| 485 | } | 489 | } |
| 486 | rc = register_filesystem(&hypfs_type); | 490 | rc = register_filesystem(&hypfs_type); |
| 487 | if (rc) | 491 | if (rc) |
| @@ -490,6 +494,8 @@ static int __init hypfs_init(void) | |||
| 490 | 494 | ||
| 491 | fail_filesystem: | 495 | fail_filesystem: |
| 492 | kobject_put(s390_kobj); | 496 | kobject_put(s390_kobj); |
| 497 | fail_hypfs_sprp_exit: | ||
| 498 | hypfs_sprp_exit(); | ||
| 493 | fail_hypfs_vm_exit: | 499 | fail_hypfs_vm_exit: |
| 494 | hypfs_vm_exit(); | 500 | hypfs_vm_exit(); |
| 495 | fail_hypfs_diag_exit: | 501 | fail_hypfs_diag_exit: |
| @@ -502,11 +508,12 @@ fail_dbfs_exit: | |||
| 502 | 508 | ||
| 503 | static void __exit hypfs_exit(void) | 509 | static void __exit hypfs_exit(void) |
| 504 | { | 510 | { |
| 505 | hypfs_diag_exit(); | ||
| 506 | hypfs_vm_exit(); | ||
| 507 | hypfs_dbfs_exit(); | ||
| 508 | unregister_filesystem(&hypfs_type); | 511 | unregister_filesystem(&hypfs_type); |
| 509 | kobject_put(s390_kobj); | 512 | kobject_put(s390_kobj); |
| 513 | hypfs_sprp_exit(); | ||
| 514 | hypfs_vm_exit(); | ||
| 515 | hypfs_diag_exit(); | ||
| 516 | hypfs_dbfs_exit(); | ||
| 510 | } | 517 | } |
| 511 | 518 | ||
| 512 | module_init(hypfs_init) | 519 | module_init(hypfs_init) |
diff --git a/arch/s390/include/asm/cmpxchg.h b/arch/s390/include/asm/cmpxchg.h index 0f636cbdf342..4236408070e5 100644 --- a/arch/s390/include/asm/cmpxchg.h +++ b/arch/s390/include/asm/cmpxchg.h | |||
| @@ -185,11 +185,12 @@ static inline unsigned long long __cmpxchg64(void *ptr, | |||
| 185 | { | 185 | { |
| 186 | register_pair rp_old = {.pair = old}; | 186 | register_pair rp_old = {.pair = old}; |
| 187 | register_pair rp_new = {.pair = new}; | 187 | register_pair rp_new = {.pair = new}; |
| 188 | unsigned long long *ullptr = ptr; | ||
| 188 | 189 | ||
| 189 | asm volatile( | 190 | asm volatile( |
| 190 | " cds %0,%2,%1" | 191 | " cds %0,%2,%1" |
| 191 | : "+&d" (rp_old), "=Q" (ptr) | 192 | : "+d" (rp_old), "+Q" (*ullptr) |
| 192 | : "d" (rp_new), "Q" (ptr) | 193 | : "d" (rp_new) |
| 193 | : "memory", "cc"); | 194 | : "memory", "cc"); |
| 194 | return rp_old.pair; | 195 | return rp_old.pair; |
| 195 | } | 196 | } |
diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index 220e171413f8..abaca2275c7a 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h | |||
| @@ -54,6 +54,7 @@ int sclp_chp_read_info(struct sclp_chp_info *info); | |||
| 54 | void sclp_get_ipl_info(struct sclp_ipl_info *info); | 54 | void sclp_get_ipl_info(struct sclp_ipl_info *info); |
| 55 | bool __init sclp_has_linemode(void); | 55 | bool __init sclp_has_linemode(void); |
| 56 | bool __init sclp_has_vt220(void); | 56 | bool __init sclp_has_vt220(void); |
| 57 | bool sclp_has_sprp(void); | ||
| 57 | int sclp_pci_configure(u32 fid); | 58 | int sclp_pci_configure(u32 fid); |
| 58 | int sclp_pci_deconfigure(u32 fid); | 59 | int sclp_pci_deconfigure(u32 fid); |
| 59 | int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode); | 60 | int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode); |
diff --git a/arch/s390/include/uapi/asm/hypfs.h b/arch/s390/include/uapi/asm/hypfs.h new file mode 100644 index 000000000000..37998b449531 --- /dev/null +++ b/arch/s390/include/uapi/asm/hypfs.h | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | /* | ||
| 2 | * IOCTL interface for hypfs | ||
| 3 | * | ||
| 4 | * Copyright IBM Corp. 2013 | ||
| 5 | * | ||
| 6 | * Author: Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #ifndef _ASM_HYPFS_CTL_H | ||
| 10 | #define _ASM_HYPFS_CTL_H | ||
| 11 | |||
| 12 | #include <linux/types.h> | ||
| 13 | |||
| 14 | struct hypfs_diag304 { | ||
| 15 | __u32 args[2]; | ||
| 16 | __u64 data; | ||
| 17 | __u64 rc; | ||
| 18 | } __attribute__((packed)); | ||
| 19 | |||
| 20 | #define HYPFS_IOCTL_MAGIC 0x10 | ||
| 21 | |||
| 22 | #define HYPFS_DIAG304 \ | ||
| 23 | _IOWR(HYPFS_IOCTL_MAGIC, 0x20, struct hypfs_diag304) | ||
| 24 | |||
| 25 | #endif | ||
diff --git a/arch/s390/include/uapi/asm/statfs.h b/arch/s390/include/uapi/asm/statfs.h index a61d538756f2..471eb09184d4 100644 --- a/arch/s390/include/uapi/asm/statfs.h +++ b/arch/s390/include/uapi/asm/statfs.h | |||
| @@ -35,11 +35,11 @@ struct statfs { | |||
| 35 | struct statfs64 { | 35 | struct statfs64 { |
| 36 | unsigned int f_type; | 36 | unsigned int f_type; |
| 37 | unsigned int f_bsize; | 37 | unsigned int f_bsize; |
| 38 | unsigned long f_blocks; | 38 | unsigned long long f_blocks; |
| 39 | unsigned long f_bfree; | 39 | unsigned long long f_bfree; |
| 40 | unsigned long f_bavail; | 40 | unsigned long long f_bavail; |
| 41 | unsigned long f_files; | 41 | unsigned long long f_files; |
| 42 | unsigned long f_ffree; | 42 | unsigned long long f_ffree; |
| 43 | __kernel_fsid_t f_fsid; | 43 | __kernel_fsid_t f_fsid; |
| 44 | unsigned int f_namelen; | 44 | unsigned int f_namelen; |
| 45 | unsigned int f_frsize; | 45 | unsigned int f_frsize; |
diff --git a/arch/s390/include/uapi/asm/unistd.h b/arch/s390/include/uapi/asm/unistd.h index 864f693c237f..5eb5c9ddb120 100644 --- a/arch/s390/include/uapi/asm/unistd.h +++ b/arch/s390/include/uapi/asm/unistd.h | |||
| @@ -280,6 +280,8 @@ | |||
| 280 | #define __NR_s390_runtime_instr 342 | 280 | #define __NR_s390_runtime_instr 342 |
| 281 | #define __NR_kcmp 343 | 281 | #define __NR_kcmp 343 |
| 282 | #define __NR_finit_module 344 | 282 | #define __NR_finit_module 344 |
| 283 | #define __NR_sched_setattr 345 | ||
| 284 | #define __NR_sched_getattr 346 | ||
| 283 | #define NR_syscalls 345 | 285 | #define NR_syscalls 345 |
| 284 | 286 | ||
| 285 | /* | 287 | /* |
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 9cb1b975b353..59c8efce1b99 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S | |||
| @@ -1412,3 +1412,14 @@ ENTRY(sys_finit_module_wrapper) | |||
| 1412 | llgtr %r3,%r3 # const char __user * | 1412 | llgtr %r3,%r3 # const char __user * |
| 1413 | lgfr %r4,%r4 # int | 1413 | lgfr %r4,%r4 # int |
| 1414 | jg sys_finit_module | 1414 | jg sys_finit_module |
| 1415 | |||
| 1416 | ENTRY(sys_sched_setattr_wrapper) | ||
| 1417 | lgfr %r2,%r2 # pid_t | ||
| 1418 | llgtr %r3,%r3 # struct sched_attr __user * | ||
| 1419 | jg sys_sched_setattr | ||
| 1420 | |||
| 1421 | ENTRY(sys_sched_getattr_wrapper) | ||
| 1422 | lgfr %r2,%r2 # pid_t | ||
| 1423 | llgtr %r3,%r3 # const char __user * | ||
| 1424 | llgfr %r3,%r3 # unsigned int | ||
| 1425 | jg sys_sched_getattr | ||
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index 913410bd74a3..143992152ec9 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S | |||
| @@ -353,3 +353,5 @@ SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev | |||
| 353 | SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper) | 353 | SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper) |
| 354 | SYSCALL(sys_kcmp,sys_kcmp,sys_kcmp_wrapper) | 354 | SYSCALL(sys_kcmp,sys_kcmp,sys_kcmp_wrapper) |
| 355 | SYSCALL(sys_finit_module,sys_finit_module,sys_finit_module_wrapper) | 355 | SYSCALL(sys_finit_module,sys_finit_module,sys_finit_module_wrapper) |
| 356 | SYSCALL(sys_sched_setattr,sys_sched_setattr,sys_sched_setattr_wrapper) /* 345 */ | ||
| 357 | SYSCALL(sys_sched_getattr,sys_sched_getattr,sys_sched_getattr_wrapper) | ||
diff --git a/arch/s390/lib/uaccess.h b/arch/s390/lib/uaccess.h index 315dbe09983e..b1a22173d027 100644 --- a/arch/s390/lib/uaccess.h +++ b/arch/s390/lib/uaccess.h | |||
| @@ -6,15 +6,6 @@ | |||
| 6 | #ifndef __ARCH_S390_LIB_UACCESS_H | 6 | #ifndef __ARCH_S390_LIB_UACCESS_H |
| 7 | #define __ARCH_S390_LIB_UACCESS_H | 7 | #define __ARCH_S390_LIB_UACCESS_H |
| 8 | 8 | ||
| 9 | extern size_t copy_from_user_std(size_t, const void __user *, void *); | ||
| 10 | extern size_t copy_to_user_std(size_t, void __user *, const void *); | ||
| 11 | extern size_t strnlen_user_std(size_t, const char __user *); | ||
| 12 | extern size_t strncpy_from_user_std(size_t, const char __user *, char *); | ||
| 13 | extern int futex_atomic_cmpxchg_std(u32 *, u32 __user *, u32, u32); | ||
| 14 | extern int futex_atomic_op_std(int, u32 __user *, int, int *); | ||
| 15 | |||
| 16 | extern size_t copy_from_user_pt(size_t, const void __user *, void *); | ||
| 17 | extern size_t copy_to_user_pt(size_t, void __user *, const void *); | ||
| 18 | extern int futex_atomic_op_pt(int, u32 __user *, int, int *); | 9 | extern int futex_atomic_op_pt(int, u32 __user *, int, int *); |
| 19 | extern int futex_atomic_cmpxchg_pt(u32 *, u32 __user *, u32, u32); | 10 | extern int futex_atomic_cmpxchg_pt(u32 *, u32 __user *, u32, u32); |
| 20 | 11 | ||
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c index 0632dc50da78..61ebcc9ccb34 100644 --- a/arch/s390/lib/uaccess_pt.c +++ b/arch/s390/lib/uaccess_pt.c | |||
| @@ -153,6 +153,8 @@ static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr, | |||
| 153 | unsigned long offset, done, size, kaddr; | 153 | unsigned long offset, done, size, kaddr; |
| 154 | void *from, *to; | 154 | void *from, *to; |
| 155 | 155 | ||
| 156 | if (!mm) | ||
| 157 | return n; | ||
| 156 | done = 0; | 158 | done = 0; |
| 157 | retry: | 159 | retry: |
| 158 | spin_lock(&mm->page_table_lock); | 160 | spin_lock(&mm->page_table_lock); |
| @@ -209,7 +211,7 @@ fault: | |||
| 209 | return 0; | 211 | return 0; |
| 210 | } | 212 | } |
| 211 | 213 | ||
| 212 | size_t copy_from_user_pt(size_t n, const void __user *from, void *to) | 214 | static size_t copy_from_user_pt(size_t n, const void __user *from, void *to) |
| 213 | { | 215 | { |
| 214 | size_t rc; | 216 | size_t rc; |
| 215 | 217 | ||
| @@ -221,7 +223,7 @@ size_t copy_from_user_pt(size_t n, const void __user *from, void *to) | |||
| 221 | return rc; | 223 | return rc; |
| 222 | } | 224 | } |
| 223 | 225 | ||
| 224 | size_t copy_to_user_pt(size_t n, void __user *to, const void *from) | 226 | static size_t copy_to_user_pt(size_t n, void __user *to, const void *from) |
| 225 | { | 227 | { |
| 226 | if (segment_eq(get_fs(), KERNEL_DS)) | 228 | if (segment_eq(get_fs(), KERNEL_DS)) |
| 227 | return copy_in_kernel(n, to, (void __user *) from); | 229 | return copy_in_kernel(n, to, (void __user *) from); |
| @@ -262,6 +264,8 @@ static size_t strnlen_user_pt(size_t count, const char __user *src) | |||
| 262 | return 0; | 264 | return 0; |
| 263 | if (segment_eq(get_fs(), KERNEL_DS)) | 265 | if (segment_eq(get_fs(), KERNEL_DS)) |
| 264 | return strnlen_kernel(count, src); | 266 | return strnlen_kernel(count, src); |
| 267 | if (!mm) | ||
| 268 | return 0; | ||
| 265 | done = 0; | 269 | done = 0; |
| 266 | retry: | 270 | retry: |
| 267 | spin_lock(&mm->page_table_lock); | 271 | spin_lock(&mm->page_table_lock); |
| @@ -323,6 +327,8 @@ static size_t copy_in_user_pt(size_t n, void __user *to, | |||
| 323 | 327 | ||
| 324 | if (segment_eq(get_fs(), KERNEL_DS)) | 328 | if (segment_eq(get_fs(), KERNEL_DS)) |
| 325 | return copy_in_kernel(n, to, from); | 329 | return copy_in_kernel(n, to, from); |
| 330 | if (!mm) | ||
| 331 | return n; | ||
| 326 | done = 0; | 332 | done = 0; |
| 327 | retry: | 333 | retry: |
| 328 | spin_lock(&mm->page_table_lock); | 334 | spin_lock(&mm->page_table_lock); |
| @@ -411,6 +417,8 @@ int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old) | |||
| 411 | 417 | ||
| 412 | if (segment_eq(get_fs(), KERNEL_DS)) | 418 | if (segment_eq(get_fs(), KERNEL_DS)) |
| 413 | return __futex_atomic_op_pt(op, uaddr, oparg, old); | 419 | return __futex_atomic_op_pt(op, uaddr, oparg, old); |
| 420 | if (unlikely(!current->mm)) | ||
| 421 | return -EFAULT; | ||
| 414 | spin_lock(¤t->mm->page_table_lock); | 422 | spin_lock(¤t->mm->page_table_lock); |
| 415 | uaddr = (u32 __force __user *) | 423 | uaddr = (u32 __force __user *) |
| 416 | __dat_user_addr((__force unsigned long) uaddr, 1); | 424 | __dat_user_addr((__force unsigned long) uaddr, 1); |
| @@ -448,6 +456,8 @@ int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr, | |||
| 448 | 456 | ||
| 449 | if (segment_eq(get_fs(), KERNEL_DS)) | 457 | if (segment_eq(get_fs(), KERNEL_DS)) |
| 450 | return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval); | 458 | return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval); |
| 459 | if (unlikely(!current->mm)) | ||
| 460 | return -EFAULT; | ||
| 451 | spin_lock(¤t->mm->page_table_lock); | 461 | spin_lock(¤t->mm->page_table_lock); |
| 452 | uaddr = (u32 __force __user *) | 462 | uaddr = (u32 __force __user *) |
| 453 | __dat_user_addr((__force unsigned long) uaddr, 1); | 463 | __dat_user_addr((__force unsigned long) uaddr, 1); |
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 | |||
| 704 | bool 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 | ||
| 82 | struct iucv_tty_buffer { | 83 | struct 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 | */ |
| 129 | struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num) | 130 | static 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]) | |||
| 772 | static int hvc_iucv_path_pending(struct iucv_path *path, | 773 | static 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 | ||
| 987 | static 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 | |||
| 1001 | static 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 | |||
| 1009 | static 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 */ |
| 965 | static const struct hv_ops hvc_iucv_ops = { | 1032 | static 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 */ | ||
| 1056 | static DEVICE_ATTR(termid, 0640, hvc_iucv_dev_termid_show, NULL); | ||
| 1057 | static DEVICE_ATTR(state, 0640, hvc_iucv_dev_state_show, NULL); | ||
| 1058 | static DEVICE_ATTR(peer, 0640, hvc_iucv_dev_peer_show, NULL); | ||
| 1059 | static struct attribute *hvc_iucv_dev_attrs[] = { | ||
| 1060 | &dev_attr_termid.attr, | ||
| 1061 | &dev_attr_state.attr, | ||
| 1062 | &dev_attr_peer.attr, | ||
| 1063 | NULL, | ||
| 1064 | }; | ||
| 1065 | static struct attribute_group hvc_iucv_dev_attr_group = { | ||
| 1066 | .attrs = hvc_iucv_dev_attrs, | ||
| 1067 | }; | ||
| 1068 | static 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) { |
