mirror of
https://github.com/torvalds/linux.git
synced 2024-12-31 23:31:29 +00:00
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
This commit is contained in:
commit
e770d73ceb
@ -73,6 +73,7 @@ Code Seq#(hex) Include File Comments
|
|||||||
0x09 all linux/raid/md_u.h
|
0x09 all linux/raid/md_u.h
|
||||||
0x10 00-0F drivers/char/s390/vmcp.h
|
0x10 00-0F drivers/char/s390/vmcp.h
|
||||||
0x10 10-1F arch/s390/include/uapi/sclp_ctl.h
|
0x10 10-1F arch/s390/include/uapi/sclp_ctl.h
|
||||||
|
0x10 20-2F arch/s390/include/uapi/asm/hypfs.h
|
||||||
0x12 all linux/fs.h
|
0x12 all linux/fs.h
|
||||||
linux/blkpg.h
|
linux/blkpg.h
|
||||||
0x1b all InfiniBand Subsystem <http://infiniband.sourceforge.net/>
|
0x1b all InfiniBand Subsystem <http://infiniband.sourceforge.net/>
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
/*?
|
|
||||||
* Text: "Cryptographic device %x failed and was set offline\n"
|
|
||||||
* Severity: Error
|
|
||||||
* Parameter:
|
|
||||||
* @1: device index
|
|
||||||
* Description:
|
|
||||||
* A cryptographic device failed to process a cryptographic request.
|
|
||||||
* The cryptographic device driver could not correct the error and
|
|
||||||
* set the device offline. The application that issued the
|
|
||||||
* request received an indication that the request has failed.
|
|
||||||
* User action:
|
|
||||||
* Use the lszcrypt command to confirm that the cryptographic
|
|
||||||
* hardware is still configured to your LPAR or z/VM guest virtual
|
|
||||||
* machine. If the device is available to your Linux instance the
|
|
||||||
* command output contains a line that begins with 'card<device index>',
|
|
||||||
* where <device index> is the two-digit decimal number in the message text.
|
|
||||||
* After ensuring that the device is available, use the chzcrypt command to
|
|
||||||
* set it online again.
|
|
||||||
* If the error persists, contact your support organization.
|
|
||||||
*/
|
|
@ -596,7 +596,7 @@ config CRASH_DUMP
|
|||||||
config ZFCPDUMP
|
config ZFCPDUMP
|
||||||
def_bool n
|
def_bool n
|
||||||
prompt "zfcpdump support"
|
prompt "zfcpdump support"
|
||||||
depends on SMP
|
depends on 64BIT && SMP
|
||||||
help
|
help
|
||||||
Select this option if you want to build an zfcpdump enabled kernel.
|
Select this option if you want to build an zfcpdump enabled kernel.
|
||||||
Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this.
|
Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this.
|
||||||
|
@ -4,4 +4,4 @@
|
|||||||
|
|
||||||
obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o
|
obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o
|
||||||
|
|
||||||
s390_hypfs-objs := inode.o hypfs_diag.o hypfs_vm.o hypfs_dbfs.o
|
s390_hypfs-objs := inode.o hypfs_diag.o hypfs_vm.o hypfs_dbfs.o hypfs_sprp.o
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/kref.h>
|
#include <linux/kref.h>
|
||||||
|
#include <asm/hypfs.h>
|
||||||
|
|
||||||
#define REG_FILE_MODE 0440
|
#define REG_FILE_MODE 0440
|
||||||
#define UPDATE_FILE_MODE 0220
|
#define UPDATE_FILE_MODE 0220
|
||||||
@ -36,6 +37,10 @@ extern int hypfs_vm_init(void);
|
|||||||
extern void hypfs_vm_exit(void);
|
extern void hypfs_vm_exit(void);
|
||||||
extern int hypfs_vm_create_files(struct dentry *root);
|
extern int hypfs_vm_create_files(struct dentry *root);
|
||||||
|
|
||||||
|
/* Set Partition-Resource Parameter */
|
||||||
|
int hypfs_sprp_init(void);
|
||||||
|
void hypfs_sprp_exit(void);
|
||||||
|
|
||||||
/* debugfs interface */
|
/* debugfs interface */
|
||||||
struct hypfs_dbfs_file;
|
struct hypfs_dbfs_file;
|
||||||
|
|
||||||
@ -52,6 +57,8 @@ struct hypfs_dbfs_file {
|
|||||||
int (*data_create)(void **data, void **data_free_ptr,
|
int (*data_create)(void **data, void **data_free_ptr,
|
||||||
size_t *size);
|
size_t *size);
|
||||||
void (*data_free)(const void *buf_free_ptr);
|
void (*data_free)(const void *buf_free_ptr);
|
||||||
|
long (*unlocked_ioctl) (struct file *, unsigned int,
|
||||||
|
unsigned long);
|
||||||
|
|
||||||
/* Private data for hypfs_dbfs.c */
|
/* Private data for hypfs_dbfs.c */
|
||||||
struct hypfs_dbfs_data *data;
|
struct hypfs_dbfs_data *data;
|
||||||
|
@ -81,9 +81,25 @@ static ssize_t dbfs_read(struct file *file, char __user *buf,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static long dbfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
struct hypfs_dbfs_file *df;
|
||||||
|
long rc;
|
||||||
|
|
||||||
|
df = file->f_path.dentry->d_inode->i_private;
|
||||||
|
mutex_lock(&df->lock);
|
||||||
|
if (df->unlocked_ioctl)
|
||||||
|
rc = df->unlocked_ioctl(file, cmd, arg);
|
||||||
|
else
|
||||||
|
rc = -ENOTTY;
|
||||||
|
mutex_unlock(&df->lock);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct file_operations dbfs_ops = {
|
static const struct file_operations dbfs_ops = {
|
||||||
.read = dbfs_read,
|
.read = dbfs_read,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
|
.unlocked_ioctl = dbfs_ioctl,
|
||||||
};
|
};
|
||||||
|
|
||||||
int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df)
|
int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df)
|
||||||
|
141
arch/s390/hypfs/hypfs_sprp.c
Normal file
141
arch/s390/hypfs/hypfs_sprp.c
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* Hypervisor filesystem for Linux on s390.
|
||||||
|
* Set Partition-Resource Parameter interface.
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2013
|
||||||
|
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/compat.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/gfp.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
#include <asm/compat.h>
|
||||||
|
#include <asm/sclp.h>
|
||||||
|
#include "hypfs.h"
|
||||||
|
|
||||||
|
#define DIAG304_SET_WEIGHTS 0
|
||||||
|
#define DIAG304_QUERY_PRP 1
|
||||||
|
#define DIAG304_SET_CAPPING 2
|
||||||
|
|
||||||
|
#define DIAG304_CMD_MAX 2
|
||||||
|
|
||||||
|
static unsigned long hypfs_sprp_diag304(void *data, unsigned long cmd)
|
||||||
|
{
|
||||||
|
register unsigned long _data asm("2") = (unsigned long) data;
|
||||||
|
register unsigned long _rc asm("3");
|
||||||
|
register unsigned long _cmd asm("4") = cmd;
|
||||||
|
|
||||||
|
asm volatile("diag %1,%2,0x304\n"
|
||||||
|
: "=d" (_rc) : "d" (_data), "d" (_cmd) : "memory");
|
||||||
|
|
||||||
|
return _rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hypfs_sprp_free(const void *data)
|
||||||
|
{
|
||||||
|
free_page((unsigned long) data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hypfs_sprp_create(void **data_ptr, void **free_ptr, size_t *size)
|
||||||
|
{
|
||||||
|
unsigned long rc;
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
data = (void *) get_zeroed_page(GFP_KERNEL);
|
||||||
|
if (!data)
|
||||||
|
return -ENOMEM;
|
||||||
|
rc = hypfs_sprp_diag304(data, DIAG304_QUERY_PRP);
|
||||||
|
if (rc != 1) {
|
||||||
|
*data_ptr = *free_ptr = NULL;
|
||||||
|
*size = 0;
|
||||||
|
free_page((unsigned long) data);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
*data_ptr = *free_ptr = data;
|
||||||
|
*size = PAGE_SIZE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __hypfs_sprp_ioctl(void __user *user_area)
|
||||||
|
{
|
||||||
|
struct hypfs_diag304 diag304;
|
||||||
|
unsigned long cmd;
|
||||||
|
void __user *udata;
|
||||||
|
void *data;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (copy_from_user(&diag304, user_area, sizeof(diag304)))
|
||||||
|
return -EFAULT;
|
||||||
|
if ((diag304.args[0] >> 8) != 0 || diag304.args[1] > DIAG304_CMD_MAX)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
data = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
|
||||||
|
if (!data)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
udata = (void __user *)(unsigned long) diag304.data;
|
||||||
|
if (diag304.args[1] == DIAG304_SET_WEIGHTS ||
|
||||||
|
diag304.args[1] == DIAG304_SET_CAPPING)
|
||||||
|
if (copy_from_user(data, udata, PAGE_SIZE)) {
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = *(unsigned long *) &diag304.args[0];
|
||||||
|
diag304.rc = hypfs_sprp_diag304(data, cmd);
|
||||||
|
|
||||||
|
if (diag304.args[1] == DIAG304_QUERY_PRP)
|
||||||
|
if (copy_to_user(udata, data, PAGE_SIZE)) {
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = copy_to_user(user_area, &diag304, sizeof(diag304)) ? -EFAULT : 0;
|
||||||
|
out:
|
||||||
|
free_page((unsigned long) data);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long hypfs_sprp_ioctl(struct file *file, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
void __user *argp;
|
||||||
|
|
||||||
|
if (!capable(CAP_SYS_ADMIN))
|
||||||
|
return -EACCES;
|
||||||
|
if (is_compat_task())
|
||||||
|
argp = compat_ptr(arg);
|
||||||
|
else
|
||||||
|
argp = (void __user *) arg;
|
||||||
|
switch (cmd) {
|
||||||
|
case HYPFS_DIAG304:
|
||||||
|
return __hypfs_sprp_ioctl(argp);
|
||||||
|
default: /* unknown ioctl number */
|
||||||
|
return -ENOTTY;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct hypfs_dbfs_file hypfs_sprp_file = {
|
||||||
|
.name = "diag_304",
|
||||||
|
.data_create = hypfs_sprp_create,
|
||||||
|
.data_free = hypfs_sprp_free,
|
||||||
|
.unlocked_ioctl = hypfs_sprp_ioctl,
|
||||||
|
};
|
||||||
|
|
||||||
|
int hypfs_sprp_init(void)
|
||||||
|
{
|
||||||
|
if (!sclp_has_sprp())
|
||||||
|
return 0;
|
||||||
|
return hypfs_dbfs_create_file(&hypfs_sprp_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hypfs_sprp_exit(void)
|
||||||
|
{
|
||||||
|
if (!sclp_has_sprp())
|
||||||
|
return;
|
||||||
|
hypfs_dbfs_remove_file(&hypfs_sprp_file);
|
||||||
|
}
|
@ -478,10 +478,14 @@ static int __init hypfs_init(void)
|
|||||||
rc = -ENODATA;
|
rc = -ENODATA;
|
||||||
goto fail_hypfs_diag_exit;
|
goto fail_hypfs_diag_exit;
|
||||||
}
|
}
|
||||||
|
if (hypfs_sprp_init()) {
|
||||||
|
rc = -ENODATA;
|
||||||
|
goto fail_hypfs_vm_exit;
|
||||||
|
}
|
||||||
s390_kobj = kobject_create_and_add("s390", hypervisor_kobj);
|
s390_kobj = kobject_create_and_add("s390", hypervisor_kobj);
|
||||||
if (!s390_kobj) {
|
if (!s390_kobj) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto fail_hypfs_vm_exit;
|
goto fail_hypfs_sprp_exit;
|
||||||
}
|
}
|
||||||
rc = register_filesystem(&hypfs_type);
|
rc = register_filesystem(&hypfs_type);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -490,6 +494,8 @@ static int __init hypfs_init(void)
|
|||||||
|
|
||||||
fail_filesystem:
|
fail_filesystem:
|
||||||
kobject_put(s390_kobj);
|
kobject_put(s390_kobj);
|
||||||
|
fail_hypfs_sprp_exit:
|
||||||
|
hypfs_sprp_exit();
|
||||||
fail_hypfs_vm_exit:
|
fail_hypfs_vm_exit:
|
||||||
hypfs_vm_exit();
|
hypfs_vm_exit();
|
||||||
fail_hypfs_diag_exit:
|
fail_hypfs_diag_exit:
|
||||||
@ -502,11 +508,12 @@ fail_dbfs_exit:
|
|||||||
|
|
||||||
static void __exit hypfs_exit(void)
|
static void __exit hypfs_exit(void)
|
||||||
{
|
{
|
||||||
hypfs_diag_exit();
|
|
||||||
hypfs_vm_exit();
|
|
||||||
hypfs_dbfs_exit();
|
|
||||||
unregister_filesystem(&hypfs_type);
|
unregister_filesystem(&hypfs_type);
|
||||||
kobject_put(s390_kobj);
|
kobject_put(s390_kobj);
|
||||||
|
hypfs_sprp_exit();
|
||||||
|
hypfs_vm_exit();
|
||||||
|
hypfs_diag_exit();
|
||||||
|
hypfs_dbfs_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(hypfs_init)
|
module_init(hypfs_init)
|
||||||
|
@ -185,11 +185,12 @@ static inline unsigned long long __cmpxchg64(void *ptr,
|
|||||||
{
|
{
|
||||||
register_pair rp_old = {.pair = old};
|
register_pair rp_old = {.pair = old};
|
||||||
register_pair rp_new = {.pair = new};
|
register_pair rp_new = {.pair = new};
|
||||||
|
unsigned long long *ullptr = ptr;
|
||||||
|
|
||||||
asm volatile(
|
asm volatile(
|
||||||
" cds %0,%2,%1"
|
" cds %0,%2,%1"
|
||||||
: "+&d" (rp_old), "=Q" (ptr)
|
: "+d" (rp_old), "+Q" (*ullptr)
|
||||||
: "d" (rp_new), "Q" (ptr)
|
: "d" (rp_new)
|
||||||
: "memory", "cc");
|
: "memory", "cc");
|
||||||
return rp_old.pair;
|
return rp_old.pair;
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,7 @@ int sclp_chp_read_info(struct sclp_chp_info *info);
|
|||||||
void sclp_get_ipl_info(struct sclp_ipl_info *info);
|
void sclp_get_ipl_info(struct sclp_ipl_info *info);
|
||||||
bool __init sclp_has_linemode(void);
|
bool __init sclp_has_linemode(void);
|
||||||
bool __init sclp_has_vt220(void);
|
bool __init sclp_has_vt220(void);
|
||||||
|
bool sclp_has_sprp(void);
|
||||||
int sclp_pci_configure(u32 fid);
|
int sclp_pci_configure(u32 fid);
|
||||||
int sclp_pci_deconfigure(u32 fid);
|
int sclp_pci_deconfigure(u32 fid);
|
||||||
int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode);
|
int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode);
|
||||||
|
25
arch/s390/include/uapi/asm/hypfs.h
Normal file
25
arch/s390/include/uapi/asm/hypfs.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* IOCTL interface for hypfs
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2013
|
||||||
|
*
|
||||||
|
* Author: Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ASM_HYPFS_CTL_H
|
||||||
|
#define _ASM_HYPFS_CTL_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
struct hypfs_diag304 {
|
||||||
|
__u32 args[2];
|
||||||
|
__u64 data;
|
||||||
|
__u64 rc;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#define HYPFS_IOCTL_MAGIC 0x10
|
||||||
|
|
||||||
|
#define HYPFS_DIAG304 \
|
||||||
|
_IOWR(HYPFS_IOCTL_MAGIC, 0x20, struct hypfs_diag304)
|
||||||
|
|
||||||
|
#endif
|
@ -35,11 +35,11 @@ struct statfs {
|
|||||||
struct statfs64 {
|
struct statfs64 {
|
||||||
unsigned int f_type;
|
unsigned int f_type;
|
||||||
unsigned int f_bsize;
|
unsigned int f_bsize;
|
||||||
unsigned long f_blocks;
|
unsigned long long f_blocks;
|
||||||
unsigned long f_bfree;
|
unsigned long long f_bfree;
|
||||||
unsigned long f_bavail;
|
unsigned long long f_bavail;
|
||||||
unsigned long f_files;
|
unsigned long long f_files;
|
||||||
unsigned long f_ffree;
|
unsigned long long f_ffree;
|
||||||
__kernel_fsid_t f_fsid;
|
__kernel_fsid_t f_fsid;
|
||||||
unsigned int f_namelen;
|
unsigned int f_namelen;
|
||||||
unsigned int f_frsize;
|
unsigned int f_frsize;
|
||||||
|
@ -280,6 +280,8 @@
|
|||||||
#define __NR_s390_runtime_instr 342
|
#define __NR_s390_runtime_instr 342
|
||||||
#define __NR_kcmp 343
|
#define __NR_kcmp 343
|
||||||
#define __NR_finit_module 344
|
#define __NR_finit_module 344
|
||||||
|
#define __NR_sched_setattr 345
|
||||||
|
#define __NR_sched_getattr 346
|
||||||
#define NR_syscalls 345
|
#define NR_syscalls 345
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1412,3 +1412,14 @@ ENTRY(sys_finit_module_wrapper)
|
|||||||
llgtr %r3,%r3 # const char __user *
|
llgtr %r3,%r3 # const char __user *
|
||||||
lgfr %r4,%r4 # int
|
lgfr %r4,%r4 # int
|
||||||
jg sys_finit_module
|
jg sys_finit_module
|
||||||
|
|
||||||
|
ENTRY(sys_sched_setattr_wrapper)
|
||||||
|
lgfr %r2,%r2 # pid_t
|
||||||
|
llgtr %r3,%r3 # struct sched_attr __user *
|
||||||
|
jg sys_sched_setattr
|
||||||
|
|
||||||
|
ENTRY(sys_sched_getattr_wrapper)
|
||||||
|
lgfr %r2,%r2 # pid_t
|
||||||
|
llgtr %r3,%r3 # const char __user *
|
||||||
|
llgfr %r3,%r3 # unsigned int
|
||||||
|
jg sys_sched_getattr
|
||||||
|
@ -353,3 +353,5 @@ SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev
|
|||||||
SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper)
|
SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper)
|
||||||
SYSCALL(sys_kcmp,sys_kcmp,sys_kcmp_wrapper)
|
SYSCALL(sys_kcmp,sys_kcmp,sys_kcmp_wrapper)
|
||||||
SYSCALL(sys_finit_module,sys_finit_module,sys_finit_module_wrapper)
|
SYSCALL(sys_finit_module,sys_finit_module,sys_finit_module_wrapper)
|
||||||
|
SYSCALL(sys_sched_setattr,sys_sched_setattr,sys_sched_setattr_wrapper) /* 345 */
|
||||||
|
SYSCALL(sys_sched_getattr,sys_sched_getattr,sys_sched_getattr_wrapper)
|
||||||
|
@ -6,15 +6,6 @@
|
|||||||
#ifndef __ARCH_S390_LIB_UACCESS_H
|
#ifndef __ARCH_S390_LIB_UACCESS_H
|
||||||
#define __ARCH_S390_LIB_UACCESS_H
|
#define __ARCH_S390_LIB_UACCESS_H
|
||||||
|
|
||||||
extern size_t copy_from_user_std(size_t, const void __user *, void *);
|
|
||||||
extern size_t copy_to_user_std(size_t, void __user *, const void *);
|
|
||||||
extern size_t strnlen_user_std(size_t, const char __user *);
|
|
||||||
extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
|
|
||||||
extern int futex_atomic_cmpxchg_std(u32 *, u32 __user *, u32, u32);
|
|
||||||
extern int futex_atomic_op_std(int, u32 __user *, int, int *);
|
|
||||||
|
|
||||||
extern size_t copy_from_user_pt(size_t, const void __user *, void *);
|
|
||||||
extern size_t copy_to_user_pt(size_t, void __user *, const void *);
|
|
||||||
extern int futex_atomic_op_pt(int, u32 __user *, int, int *);
|
extern int futex_atomic_op_pt(int, u32 __user *, int, int *);
|
||||||
extern int futex_atomic_cmpxchg_pt(u32 *, u32 __user *, u32, u32);
|
extern int futex_atomic_cmpxchg_pt(u32 *, u32 __user *, u32, u32);
|
||||||
|
|
||||||
|
@ -153,6 +153,8 @@ static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,
|
|||||||
unsigned long offset, done, size, kaddr;
|
unsigned long offset, done, size, kaddr;
|
||||||
void *from, *to;
|
void *from, *to;
|
||||||
|
|
||||||
|
if (!mm)
|
||||||
|
return n;
|
||||||
done = 0;
|
done = 0;
|
||||||
retry:
|
retry:
|
||||||
spin_lock(&mm->page_table_lock);
|
spin_lock(&mm->page_table_lock);
|
||||||
@ -209,7 +211,7 @@ fault:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t copy_from_user_pt(size_t n, const void __user *from, void *to)
|
static size_t copy_from_user_pt(size_t n, const void __user *from, void *to)
|
||||||
{
|
{
|
||||||
size_t rc;
|
size_t rc;
|
||||||
|
|
||||||
@ -221,7 +223,7 @@ size_t copy_from_user_pt(size_t n, const void __user *from, void *to)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t copy_to_user_pt(size_t n, void __user *to, const void *from)
|
static size_t copy_to_user_pt(size_t n, void __user *to, const void *from)
|
||||||
{
|
{
|
||||||
if (segment_eq(get_fs(), KERNEL_DS))
|
if (segment_eq(get_fs(), KERNEL_DS))
|
||||||
return copy_in_kernel(n, to, (void __user *) from);
|
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)
|
|||||||
return 0;
|
return 0;
|
||||||
if (segment_eq(get_fs(), KERNEL_DS))
|
if (segment_eq(get_fs(), KERNEL_DS))
|
||||||
return strnlen_kernel(count, src);
|
return strnlen_kernel(count, src);
|
||||||
|
if (!mm)
|
||||||
|
return 0;
|
||||||
done = 0;
|
done = 0;
|
||||||
retry:
|
retry:
|
||||||
spin_lock(&mm->page_table_lock);
|
spin_lock(&mm->page_table_lock);
|
||||||
@ -323,6 +327,8 @@ static size_t copy_in_user_pt(size_t n, void __user *to,
|
|||||||
|
|
||||||
if (segment_eq(get_fs(), KERNEL_DS))
|
if (segment_eq(get_fs(), KERNEL_DS))
|
||||||
return copy_in_kernel(n, to, from);
|
return copy_in_kernel(n, to, from);
|
||||||
|
if (!mm)
|
||||||
|
return n;
|
||||||
done = 0;
|
done = 0;
|
||||||
retry:
|
retry:
|
||||||
spin_lock(&mm->page_table_lock);
|
spin_lock(&mm->page_table_lock);
|
||||||
@ -411,6 +417,8 @@ int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
|
|||||||
|
|
||||||
if (segment_eq(get_fs(), KERNEL_DS))
|
if (segment_eq(get_fs(), KERNEL_DS))
|
||||||
return __futex_atomic_op_pt(op, uaddr, oparg, old);
|
return __futex_atomic_op_pt(op, uaddr, oparg, old);
|
||||||
|
if (unlikely(!current->mm))
|
||||||
|
return -EFAULT;
|
||||||
spin_lock(¤t->mm->page_table_lock);
|
spin_lock(¤t->mm->page_table_lock);
|
||||||
uaddr = (u32 __force __user *)
|
uaddr = (u32 __force __user *)
|
||||||
__dat_user_addr((__force unsigned long) uaddr, 1);
|
__dat_user_addr((__force unsigned long) uaddr, 1);
|
||||||
@ -448,6 +456,8 @@ int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
|
|||||||
|
|
||||||
if (segment_eq(get_fs(), KERNEL_DS))
|
if (segment_eq(get_fs(), KERNEL_DS))
|
||||||
return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
|
return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
|
||||||
|
if (unlikely(!current->mm))
|
||||||
|
return -EFAULT;
|
||||||
spin_lock(¤t->mm->page_table_lock);
|
spin_lock(¤t->mm->page_table_lock);
|
||||||
uaddr = (u32 __force __user *)
|
uaddr = (u32 __force __user *)
|
||||||
__dat_user_addr((__force unsigned long) uaddr, 1);
|
__dat_user_addr((__force unsigned long) uaddr, 1);
|
||||||
|
@ -257,6 +257,7 @@ static int __init xpram_setup_sizes(unsigned long pages)
|
|||||||
unsigned long mem_needed;
|
unsigned long mem_needed;
|
||||||
unsigned long mem_auto;
|
unsigned long mem_auto;
|
||||||
unsigned long long size;
|
unsigned long long size;
|
||||||
|
char *sizes_end;
|
||||||
int mem_auto_no;
|
int mem_auto_no;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -275,8 +276,8 @@ static int __init xpram_setup_sizes(unsigned long pages)
|
|||||||
mem_auto_no = 0;
|
mem_auto_no = 0;
|
||||||
for (i = 0; i < xpram_devs; i++) {
|
for (i = 0; i < xpram_devs; i++) {
|
||||||
if (sizes[i]) {
|
if (sizes[i]) {
|
||||||
size = simple_strtoull(sizes[i], &sizes[i], 0);
|
size = simple_strtoull(sizes[i], &sizes_end, 0);
|
||||||
switch (sizes[i][0]) {
|
switch (*sizes_end) {
|
||||||
case 'g':
|
case 'g':
|
||||||
case 'G':
|
case 'G':
|
||||||
size <<= 20;
|
size <<= 20;
|
||||||
|
@ -700,3 +700,8 @@ out:
|
|||||||
free_page((unsigned long) sccb);
|
free_page((unsigned long) sccb);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sclp_has_sprp(void)
|
||||||
|
{
|
||||||
|
return !!(sclp_fac84 & 0x2);
|
||||||
|
}
|
||||||
|
@ -922,8 +922,8 @@ static int ur_set_online(struct ccw_device *cdev)
|
|||||||
goto fail_free_cdev;
|
goto fail_free_cdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
urd->device = device_create(vmur_class, NULL, urd->char_device->dev,
|
urd->device = device_create(vmur_class, &cdev->dev,
|
||||||
NULL, "%s", node_id);
|
urd->char_device->dev, NULL, "%s", node_id);
|
||||||
if (IS_ERR(urd->device)) {
|
if (IS_ERR(urd->device)) {
|
||||||
rc = PTR_ERR(urd->device);
|
rc = PTR_ERR(urd->device);
|
||||||
TRACE("ur_set_online: device_create rc=%d\n", rc);
|
TRACE("ur_set_online: device_create rc=%d\n", rc);
|
||||||
|
@ -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 {
|
||||||
@ -126,7 +127,7 @@ static struct iucv_handler hvc_iucv_handler = {
|
|||||||
* This function returns the struct hvc_iucv_private instance that corresponds
|
* This function returns the struct hvc_iucv_private instance that corresponds
|
||||||
* to the HVC virtual terminal number specified as parameter @num.
|
* to the HVC virtual terminal number specified as parameter @num.
|
||||||
*/
|
*/
|
||||||
struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num)
|
static struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num)
|
||||||
{
|
{
|
||||||
if ((num < HVC_IUCV_MAGIC) || (num - HVC_IUCV_MAGIC > hvc_iucv_devices))
|
if ((num < HVC_IUCV_MAGIC) || (num - HVC_IUCV_MAGIC > hvc_iucv_devices))
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -772,18 +773,37 @@ static int hvc_iucv_filter_connreq(u8 ipvmid[8])
|
|||||||
static int hvc_iucv_path_pending(struct iucv_path *path,
|
static int hvc_iucv_path_pending(struct iucv_path *path,
|
||||||
u8 ipvmid[8], u8 ipuser[16])
|
u8 ipvmid[8], u8 ipuser[16])
|
||||||
{
|
{
|
||||||
struct hvc_iucv_private *priv;
|
struct hvc_iucv_private *priv, *tmp;
|
||||||
|
u8 wildcard[9] = "lnxhvc ";
|
||||||
|
int i, rc, find_unused;
|
||||||
u8 nuser_data[16];
|
u8 nuser_data[16];
|
||||||
u8 vm_user_id[9];
|
u8 vm_user_id[9];
|
||||||
int i, rc;
|
|
||||||
|
|
||||||
|
ASCEBC(wildcard, sizeof(wildcard));
|
||||||
|
find_unused = !memcmp(wildcard, ipuser, 8);
|
||||||
|
|
||||||
|
/* First, check if the pending path request is managed by this
|
||||||
|
* IUCV handler:
|
||||||
|
* - find a disconnected device if ipuser contains the wildcard
|
||||||
|
* - find the device that matches the terminal ID in ipuser
|
||||||
|
*/
|
||||||
priv = NULL;
|
priv = NULL;
|
||||||
for (i = 0; i < hvc_iucv_devices; i++)
|
for (i = 0; i < hvc_iucv_devices; i++) {
|
||||||
if (hvc_iucv_table[i] &&
|
tmp = hvc_iucv_table[i];
|
||||||
(0 == memcmp(hvc_iucv_table[i]->srv_name, ipuser, 8))) {
|
if (!tmp)
|
||||||
priv = hvc_iucv_table[i];
|
continue;
|
||||||
|
|
||||||
|
if (find_unused) {
|
||||||
|
spin_lock(&tmp->lock);
|
||||||
|
if (tmp->iucv_state == IUCV_DISCONN)
|
||||||
|
priv = tmp;
|
||||||
|
spin_unlock(&tmp->lock);
|
||||||
|
|
||||||
|
} else if (!memcmp(tmp->srv_name, ipuser, 8))
|
||||||
|
priv = tmp;
|
||||||
|
if (priv)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!priv)
|
if (!priv)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
@ -826,6 +846,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 +984,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 +1052,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 +1132,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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user