Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband: (104 commits)
IB/iser: Don't change itt endianness
IB/mlx4: Update module version and release date
IPoIB: Handle case when P_Key is deleted and re-added at same index
IB/iser: Release connection resources on RDMA_CM_EVENT_DEVICE_REMOVAL event
IB/mlx4: Fix incorrect comment
IB/mlx4: Fix race when detaching a QP from a multicast group
IB/ehca: Support all ibv_devinfo values in query_device() and query_port()
RDMA/nes: Free IRQ before killing tasklet
IB/mthca: Update module version and release date
IB/mlx4: Update QP state if query QP succeeds
IB/mthca: Update QP state if query QP succeeds
RDMA/amso1100: Add check for NULL reply_msg in c2_intr()
IB/mlx4: Add support for resizing CQs
IB/mlx4: Add support for modifying CQ moderation parameters
IPoIB: Support modifying IPoIB CQ event moderation
IB/core: Add support for modify CQ
IPoIB: Add basic ethtool support
mlx4_core: Increase max number of QPs to 128K
RDMA/amso1100: Add support for "send with invalidate" work requests
IB/core: Add support for "send with invalidate" work requests
...
diff --git a/Documentation/s390/s390dbf.txt b/Documentation/s390/s390dbf.txt
index 0eb7c58..e054209 100644
--- a/Documentation/s390/s390dbf.txt
+++ b/Documentation/s390/s390dbf.txt
@@ -115,6 +115,27 @@
Description: Allocates memory for a debug log
Must not be called within an interrupt handler
+----------------------------------------------------------------------------
+debug_info_t *debug_register_mode(char *name, int pages, int nr_areas,
+ int buf_size, mode_t mode, uid_t uid,
+ gid_t gid);
+
+Parameter: name: Name of debug log (e.g. used for debugfs entry)
+ pages: Number of pages, which will be allocated per area
+ nr_areas: Number of debug areas
+ buf_size: Size of data area in each debug entry
+ mode: File mode for debugfs files. E.g. S_IRWXUGO
+ uid: User ID for debugfs files. Currently only 0 is
+ supported.
+ gid: Group ID for debugfs files. Currently only 0 is
+ supported.
+
+Return Value: Handle for generated debug area
+ NULL if register failed
+
+Description: Allocates memory for a debug log
+ Must not be called within an interrupt handler
+
---------------------------------------------------------------------------
void debug_unregister (debug_info_t * id);
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 1831833..f6a68e1 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -3,6 +3,10 @@
# see Documentation/kbuild/kconfig-language.txt.
#
+config SCHED_MC
+ def_bool y
+ depends on SMP
+
config MMU
def_bool y
@@ -39,6 +43,9 @@
config GENERIC_TIME
def_bool y
+config GENERIC_CLOCKEVENTS
+ def_bool y
+
config GENERIC_BUG
bool
depends on BUG
@@ -69,6 +76,8 @@
comment "Processor type and features"
+source "kernel/time/Kconfig"
+
config 64BIT
bool "64 bit kernel"
help
@@ -301,10 +310,7 @@
tristate "QDIO support"
---help---
This driver provides the Queued Direct I/O base support for
- IBM mainframes.
-
- For details please refer to the documentation provided by IBM at
- <http://www10.software.ibm.com/developerworks/opensource/linux390>
+ IBM System z.
To compile this driver as a module, choose M here: the
module will be called qdio.
@@ -486,25 +492,6 @@
source kernel/Kconfig.hz
-config NO_IDLE_HZ
- bool "No HZ timer ticks in idle"
- help
- Switches the regular HZ timer off when the system is going idle.
- This helps z/VM to detect that the Linux system is idle. VM can
- then "swap-out" this guest which reduces memory usage. It also
- reduces the overhead of idle systems.
-
- The HZ timer can be switched on/off via /proc/sys/kernel/hz_timer.
- hz_timer=0 means HZ timer is disabled. hz_timer=1 means HZ
- timer is active.
-
-config NO_IDLE_HZ_INIT
- bool "HZ timer in idle off by default"
- depends on NO_IDLE_HZ
- help
- The HZ timer is switched off in idle by default. That means the
- HZ timer is already disabled at boot time.
-
config S390_HYPFS_FS
bool "s390 hypervisor file system support"
select SYS_HYPERVISOR
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index a3f67f8..e33f32b 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -499,7 +499,7 @@
}
};
-static int __init aes_init(void)
+static int __init aes_s390_init(void)
{
int ret;
@@ -542,15 +542,15 @@
goto out;
}
-static void __exit aes_fini(void)
+static void __exit aes_s390_fini(void)
{
crypto_unregister_alg(&cbc_aes_alg);
crypto_unregister_alg(&ecb_aes_alg);
crypto_unregister_alg(&aes_alg);
}
-module_init(aes_init);
-module_exit(aes_fini);
+module_init(aes_s390_init);
+module_exit(aes_s390_fini);
MODULE_ALIAS("aes");
diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c
index ea22707..4aba83b 100644
--- a/arch/s390/crypto/des_s390.c
+++ b/arch/s390/crypto/des_s390.c
@@ -550,7 +550,7 @@
}
};
-static int init(void)
+static int des_s390_init(void)
{
int ret = 0;
@@ -612,7 +612,7 @@
goto out;
}
-static void __exit fini(void)
+static void __exit des_s390_fini(void)
{
crypto_unregister_alg(&cbc_des3_192_alg);
crypto_unregister_alg(&ecb_des3_192_alg);
@@ -625,8 +625,8 @@
crypto_unregister_alg(&des_alg);
}
-module_init(init);
-module_exit(fini);
+module_init(des_s390_init);
+module_exit(des_s390_fini);
MODULE_ALIAS("des");
MODULE_ALIAS("des3_ede");
diff --git a/arch/s390/crypto/sha1_s390.c b/arch/s390/crypto/sha1_s390.c
index 5a834f6..9cf9eca 100644
--- a/arch/s390/crypto/sha1_s390.c
+++ b/arch/s390/crypto/sha1_s390.c
@@ -137,7 +137,7 @@
.dia_final = sha1_final } }
};
-static int __init init(void)
+static int __init sha1_s390_init(void)
{
if (!crypt_s390_func_available(KIMD_SHA_1))
return -EOPNOTSUPP;
@@ -145,13 +145,13 @@
return crypto_register_alg(&alg);
}
-static void __exit fini(void)
+static void __exit sha1_s390_fini(void)
{
crypto_unregister_alg(&alg);
}
-module_init(init);
-module_exit(fini);
+module_init(sha1_s390_init);
+module_exit(sha1_s390_fini);
MODULE_ALIAS("sha1");
diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c
index ccf8633..2a3d756 100644
--- a/arch/s390/crypto/sha256_s390.c
+++ b/arch/s390/crypto/sha256_s390.c
@@ -133,7 +133,7 @@
.dia_final = sha256_final } }
};
-static int init(void)
+static int sha256_s390_init(void)
{
if (!crypt_s390_func_available(KIMD_SHA_256))
return -EOPNOTSUPP;
@@ -141,13 +141,13 @@
return crypto_register_alg(&alg);
}
-static void __exit fini(void)
+static void __exit sha256_s390_fini(void)
{
crypto_unregister_alg(&alg);
}
-module_init(init);
-module_exit(fini);
+module_init(sha256_s390_init);
+module_exit(sha256_s390_fini);
MODULE_ALIAS("sha256");
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 62f6b5a..dcc3ec2 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -3,6 +3,7 @@
# Linux kernel version: 2.6.25-rc4
# Wed Mar 5 11:22:59 2008
#
+CONFIG_SCHED_MC=y
CONFIG_MMU=y
CONFIG_ZONE_DMA=y
CONFIG_LOCKDEP_SUPPORT=y
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 4d3e383..ef2b2470 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -19,7 +19,7 @@
extra-y += head.o init_task.o vmlinux.lds
obj-$(CONFIG_MODULES) += s390_ksyms.o module.o
-obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_SMP) += smp.o topology.o
obj-$(CONFIG_AUDIT) += audit.o
compat-obj-$(CONFIG_AUDIT) += compat_audit.o
diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
index e89f8c0..20723a0 100644
--- a/arch/s390/kernel/compat_linux.h
+++ b/arch/s390/kernel/compat_linux.h
@@ -162,4 +162,77 @@
compat_sigset_t uc_sigmask; /* mask last for extensibility */
};
+struct __sysctl_args32;
+struct stat64_emu31;
+struct mmap_arg_struct_emu31;
+struct fadvise64_64_args;
+struct old_sigaction32;
+struct old_sigaction32;
+
+long sys32_chown16(const char __user * filename, u16 user, u16 group);
+long sys32_lchown16(const char __user * filename, u16 user, u16 group);
+long sys32_fchown16(unsigned int fd, u16 user, u16 group);
+long sys32_setregid16(u16 rgid, u16 egid);
+long sys32_setgid16(u16 gid);
+long sys32_setreuid16(u16 ruid, u16 euid);
+long sys32_setuid16(u16 uid);
+long sys32_setresuid16(u16 ruid, u16 euid, u16 suid);
+long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid);
+long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid);
+long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid);
+long sys32_setfsuid16(u16 uid);
+long sys32_setfsgid16(u16 gid);
+long sys32_getgroups16(int gidsetsize, u16 __user *grouplist);
+long sys32_setgroups16(int gidsetsize, u16 __user *grouplist);
+long sys32_getuid16(void);
+long sys32_geteuid16(void);
+long sys32_getgid16(void);
+long sys32_getegid16(void);
+long sys32_ipc(u32 call, int first, int second, int third, u32 ptr);
+long sys32_truncate64(const char __user * path, unsigned long high,
+ unsigned long low);
+long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low);
+long sys32_sched_rr_get_interval(compat_pid_t pid,
+ struct compat_timespec __user *interval);
+long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
+ compat_sigset_t __user *oset, size_t sigsetsize);
+long sys32_rt_sigpending(compat_sigset_t __user *set, size_t sigsetsize);
+long sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo);
+long sys32_execve(void);
+long sys32_init_module(void __user *umod, unsigned long len,
+ const char __user *uargs);
+long sys32_delete_module(const char __user *name_user, unsigned int flags);
+long sys32_gettimeofday(struct compat_timeval __user *tv,
+ struct timezone __user *tz);
+long sys32_settimeofday(struct compat_timeval __user *tv,
+ struct timezone __user *tz);
+long sys32_pause(void);
+long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count,
+ u32 poshi, u32 poslo);
+long sys32_pwrite64(unsigned int fd, const char __user *ubuf,
+ size_t count, u32 poshi, u32 poslo);
+compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count);
+long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,
+ size_t count);
+long sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset,
+ s32 count);
+long sys32_sysctl(struct __sysctl_args32 __user *args);
+long sys32_stat64(char __user * filename, struct stat64_emu31 __user * statbuf);
+long sys32_lstat64(char __user * filename,
+ struct stat64_emu31 __user * statbuf);
+long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf);
+long sys32_fstatat64(unsigned int dfd, char __user *filename,
+ struct stat64_emu31 __user* statbuf, int flag);
+unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg);
+long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg);
+long sys32_read(unsigned int fd, char __user * buf, size_t count);
+long sys32_write(unsigned int fd, char __user * buf, size_t count);
+long sys32_clone(void);
+long sys32_fadvise64(int fd, loff_t offset, size_t len, int advise);
+long sys32_fadvise64_64(struct fadvise64_64_args __user *args);
+long sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
+ struct old_sigaction32 __user *oact);
+long sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
+ struct sigaction32 __user *oact, size_t sigsetsize);
+long sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss);
#endif /* _ASM_S390X_S390_H */
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index a5692c4..c7f02e7 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -29,6 +29,7 @@
#include <asm/lowcore.h>
#include "compat_linux.h"
#include "compat_ptrace.h"
+#include "entry.h"
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -428,6 +429,10 @@
/* Default to using normal stack */
sp = (unsigned long) A(regs->gprs[15]);
+ /* Overflow on alternate signal stack gives SIGSEGV. */
+ if (on_sig_stack(sp) && !on_sig_stack((sp - frame_size) & -8UL))
+ return (void __user *) -1UL;
+
/* This is the X/Open sanctioned signal stack switching. */
if (ka->sa.sa_flags & SA_ONSTACK) {
if (! sas_ss_flags(sp))
@@ -461,6 +466,9 @@
if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe32)))
goto give_sigsegv;
+ if (frame == (void __user *) -1UL)
+ goto give_sigsegv;
+
if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
goto give_sigsegv;
@@ -514,6 +522,9 @@
if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe32)))
goto give_sigsegv;
+ if (frame == (void __user *) -1UL)
+ goto give_sigsegv;
+
if (copy_siginfo_to_user32(&frame->info, info))
goto give_sigsegv;
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 1b2f5ce..1e7d4ac 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -73,7 +73,7 @@
static int debug_open(struct inode *inode, struct file *file);
static int debug_close(struct inode *inode, struct file *file);
static debug_info_t* debug_info_create(char *name, int pages_per_area,
- int nr_areas, int buf_size);
+ int nr_areas, int buf_size, mode_t mode);
static void debug_info_get(debug_info_t *);
static void debug_info_put(debug_info_t *);
static int debug_prolog_level_fn(debug_info_t * id,
@@ -157,7 +157,7 @@
};
/* used by dump analysis tools to determine version of debug feature */
-unsigned int debug_feature_version = __DEBUG_FEATURE_VERSION;
+static unsigned int __used debug_feature_version = __DEBUG_FEATURE_VERSION;
/* static globals */
@@ -327,7 +327,8 @@
*/
static debug_info_t*
-debug_info_create(char *name, int pages_per_area, int nr_areas, int buf_size)
+debug_info_create(char *name, int pages_per_area, int nr_areas, int buf_size,
+ mode_t mode)
{
debug_info_t* rc;
@@ -336,6 +337,8 @@
if(!rc)
goto out;
+ rc->mode = mode & ~S_IFMT;
+
/* create root directory */
rc->debugfs_root_entry = debugfs_create_dir(rc->name,
debug_debugfs_root_entry);
@@ -676,23 +679,30 @@
}
/*
- * debug_register:
- * - creates and initializes debug area for the caller
- * - returns handle for debug area
+ * debug_register_mode:
+ * - Creates and initializes debug area for the caller
+ * The mode parameter allows to specify access rights for the s390dbf files
+ * - Returns handle for debug area
*/
-debug_info_t*
-debug_register (char *name, int pages_per_area, int nr_areas, int buf_size)
+debug_info_t *debug_register_mode(char *name, int pages_per_area, int nr_areas,
+ int buf_size, mode_t mode, uid_t uid,
+ gid_t gid)
{
debug_info_t *rc = NULL;
+ /* Since debugfs currently does not support uid/gid other than root, */
+ /* we do not allow gid/uid != 0 until we get support for that. */
+ if ((uid != 0) || (gid != 0))
+ printk(KERN_WARNING "debug: Warning - Currently only uid/gid "
+ "= 0 are supported. Using root as owner now!");
if (!initialized)
BUG();
mutex_lock(&debug_mutex);
/* create new debug_info */
- rc = debug_info_create(name, pages_per_area, nr_areas, buf_size);
+ rc = debug_info_create(name, pages_per_area, nr_areas, buf_size, mode);
if(!rc)
goto out;
debug_register_view(rc, &debug_level_view);
@@ -705,6 +715,20 @@
mutex_unlock(&debug_mutex);
return rc;
}
+EXPORT_SYMBOL(debug_register_mode);
+
+/*
+ * debug_register:
+ * - creates and initializes debug area for the caller
+ * - returns handle for debug area
+ */
+
+debug_info_t *debug_register(char *name, int pages_per_area, int nr_areas,
+ int buf_size)
+{
+ return debug_register_mode(name, pages_per_area, nr_areas, buf_size,
+ S_IRUSR | S_IWUSR, 0, 0);
+}
/*
* debug_unregister:
@@ -1073,15 +1097,16 @@
int rc = 0;
int i;
unsigned long flags;
- mode_t mode = S_IFREG;
+ mode_t mode;
struct dentry *pde;
if (!id)
goto out;
- if (view->prolog_proc || view->format_proc || view->header_proc)
- mode |= S_IRUSR;
- if (view->input_proc)
- mode |= S_IWUSR;
+ mode = (id->mode | S_IFREG) & ~S_IXUGO;
+ if (!(view->prolog_proc || view->format_proc || view->header_proc))
+ mode &= ~(S_IRUSR | S_IRGRP | S_IROTH);
+ if (!view->input_proc)
+ mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
pde = debugfs_create_file(view->name, mode, id->debugfs_root_entry,
id , &debug_file_ops);
if (!pde){
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 01832c4..540a67f 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -21,6 +21,7 @@
#include <asm/setup.h>
#include <asm/cpcmd.h>
#include <asm/sclp.h>
+#include "entry.h"
/*
* Create a Kernel NSS if the SAVESYS= parameter is defined
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
new file mode 100644
index 0000000..6b18963
--- /dev/null
+++ b/arch/s390/kernel/entry.h
@@ -0,0 +1,60 @@
+#ifndef _ENTRY_H
+#define _ENTRY_H
+
+#include <linux/types.h>
+#include <linux/signal.h>
+#include <asm/ptrace.h>
+
+typedef void pgm_check_handler_t(struct pt_regs *, long);
+extern pgm_check_handler_t *pgm_check_table[128];
+pgm_check_handler_t do_protection_exception;
+pgm_check_handler_t do_dat_exception;
+
+extern int sysctl_userprocess_debug;
+
+void do_single_step(struct pt_regs *regs);
+void syscall_trace(struct pt_regs *regs, int entryexit);
+void kernel_stack_overflow(struct pt_regs * regs);
+void do_signal(struct pt_regs *regs);
+int handle_signal32(unsigned long sig, struct k_sigaction *ka,
+ siginfo_t *info, sigset_t *oldset, struct pt_regs *regs);
+
+void do_extint(struct pt_regs *regs, unsigned short code);
+int __cpuinit start_secondary(void *cpuvoid);
+void __init startup_init(void);
+void die(const char * str, struct pt_regs * regs, long err);
+
+struct new_utsname;
+struct mmap_arg_struct;
+struct fadvise64_64_args;
+struct old_sigaction;
+struct sel_arg_struct;
+
+long sys_pipe(unsigned long __user *fildes);
+long sys_mmap2(struct mmap_arg_struct __user *arg);
+long old_mmap(struct mmap_arg_struct __user *arg);
+long sys_ipc(uint call, int first, unsigned long second,
+ unsigned long third, void __user *ptr);
+long s390x_newuname(struct new_utsname __user *name);
+long s390x_personality(unsigned long personality);
+long s390_fadvise64(int fd, u32 offset_high, u32 offset_low,
+ size_t len, int advice);
+long s390_fadvise64_64(struct fadvise64_64_args __user *args);
+long s390_fallocate(int fd, int mode, loff_t offset, u32 len_high, u32 len_low);
+long sys_fork(void);
+long sys_clone(void);
+long sys_vfork(void);
+void execve_tail(void);
+long sys_execve(void);
+int sys_sigsuspend(int history0, int history1, old_sigset_t mask);
+long sys_sigaction(int sig, const struct old_sigaction __user *act,
+ struct old_sigaction __user *oact);
+long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss);
+long sys_sigreturn(void);
+long sys_rt_sigreturn(void);
+long sys32_sigreturn(void);
+long sys32_rt_sigreturn(void);
+long old_select(struct sel_arg_struct __user *arg);
+long sys_ptrace(long request, long pid, long addr, long data);
+
+#endif /* _ENTRY_H */
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index efde6e1..cd959c0 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -475,6 +475,7 @@
pgm_no_vtime:
#endif
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
+ mvc SP_ARGS(8,%r15),__LC_LAST_BREAK
TRACE_IRQS_OFF
lgf %r3,__LC_PGM_ILC # load program interruption code
lghi %r8,0x7f
@@ -847,6 +848,7 @@
je 0f
la %r1,__LC_SAVE_AREA+32
0: mvc SP_R12(32,%r15),0(%r1) # move %r12-%r15 to stack
+ mvc SP_ARGS(8,%r15),__LC_LAST_BREAK
xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain
la %r2,SP_PTREGS(%r15) # load pt_regs
jg kernel_stack_overflow
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 375232c..5325424 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -655,7 +655,7 @@
static struct kset *reipl_kset;
-void reipl_run(struct shutdown_trigger *trigger)
+static void reipl_run(struct shutdown_trigger *trigger)
{
struct ccw_dev_id devid;
static char buf[100];
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index c5549a2..ed04d13 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -360,7 +360,7 @@
* - When the probed function returns, this probe
* causes the handlers to fire
*/
-void kretprobe_trampoline_holder(void)
+static void __used kretprobe_trampoline_holder(void)
{
asm volatile(".global kretprobe_trampoline\n"
"kretprobe_trampoline: bcr 0,0\n");
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index ce20315..c1aff19 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -36,6 +36,8 @@
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/utsname.h>
+#include <linux/tick.h>
+#include <linux/elfcore.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
@@ -44,6 +46,7 @@
#include <asm/irq.h>
#include <asm/timer.h>
#include <asm/cpu.h>
+#include "entry.h"
asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
@@ -76,6 +79,7 @@
* Need to know about CPUs going idle?
*/
static ATOMIC_NOTIFIER_HEAD(idle_chain);
+DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
int register_idle_notifier(struct notifier_block *nb)
{
@@ -89,9 +93,33 @@
}
EXPORT_SYMBOL(unregister_idle_notifier);
-void do_monitor_call(struct pt_regs *regs, long interruption_code)
+static int s390_idle_enter(void)
{
-#ifdef CONFIG_SMP
+ struct s390_idle_data *idle;
+ int nr_calls = 0;
+ void *hcpu;
+ int rc;
+
+ hcpu = (void *)(long)smp_processor_id();
+ rc = __atomic_notifier_call_chain(&idle_chain, S390_CPU_IDLE, hcpu, -1,
+ &nr_calls);
+ if (rc == NOTIFY_BAD) {
+ nr_calls--;
+ __atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
+ hcpu, nr_calls, NULL);
+ return rc;
+ }
+ idle = &__get_cpu_var(s390_idle);
+ spin_lock(&idle->lock);
+ idle->idle_count++;
+ idle->in_idle = 1;
+ idle->idle_enter = get_clock();
+ spin_unlock(&idle->lock);
+ return NOTIFY_OK;
+}
+
+void s390_idle_leave(void)
+{
struct s390_idle_data *idle;
idle = &__get_cpu_var(s390_idle);
@@ -99,10 +127,6 @@
idle->idle_time += get_clock() - idle->idle_enter;
idle->in_idle = 0;
spin_unlock(&idle->lock);
-#endif
- /* disable monitor call class 0 */
- __ctl_clear_bit(8, 15);
-
atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
(void *)(long) smp_processor_id());
}
@@ -113,61 +137,30 @@
*/
static void default_idle(void)
{
- int cpu, rc;
- int nr_calls = 0;
- void *hcpu;
-#ifdef CONFIG_SMP
- struct s390_idle_data *idle;
-#endif
-
/* CPU is going idle. */
- cpu = smp_processor_id();
- hcpu = (void *)(long)cpu;
local_irq_disable();
if (need_resched()) {
local_irq_enable();
return;
}
-
- rc = __atomic_notifier_call_chain(&idle_chain, S390_CPU_IDLE, hcpu, -1,
- &nr_calls);
- if (rc == NOTIFY_BAD) {
- nr_calls--;
- __atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
- hcpu, nr_calls, NULL);
+ if (s390_idle_enter() == NOTIFY_BAD) {
local_irq_enable();
return;
}
-
- /* enable monitor call class 0 */
- __ctl_set_bit(8, 15);
-
#ifdef CONFIG_HOTPLUG_CPU
- if (cpu_is_offline(cpu)) {
+ if (cpu_is_offline(smp_processor_id())) {
preempt_enable_no_resched();
cpu_die();
}
#endif
-
local_mcck_disable();
if (test_thread_flag(TIF_MCCK_PENDING)) {
local_mcck_enable();
- /* disable monitor call class 0 */
- __ctl_clear_bit(8, 15);
- atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
- hcpu);
+ s390_idle_leave();
local_irq_enable();
s390_handle_mcck();
return;
}
-#ifdef CONFIG_SMP
- idle = &__get_cpu_var(s390_idle);
- spin_lock(&idle->lock);
- idle->idle_count++;
- idle->in_idle = 1;
- idle->idle_enter = get_clock();
- spin_unlock(&idle->lock);
-#endif
trace_hardirqs_on();
/* Wait for external, I/O or machine check interrupt. */
__load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
@@ -177,9 +170,10 @@
void cpu_idle(void)
{
for (;;) {
+ tick_nohz_stop_sched_tick();
while (!need_resched())
default_idle();
-
+ tick_nohz_restart_sched_tick();
preempt_enable_no_resched();
schedule();
preempt_disable();
@@ -201,6 +195,7 @@
/* Show stack backtrace if pt_regs is from kernel mode */
if (!(regs->psw.mask & PSW_MASK_PSTATE))
show_trace(NULL, (unsigned long *) regs->gprs[15]);
+ show_last_breaking_event(regs);
}
extern void kernel_thread_starter(void);
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 6e036ba..58a0642 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -41,6 +41,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
+#include "entry.h"
#ifdef CONFIG_COMPAT
#include "compat_ptrace.h"
diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c
index acf93db..e019b41 100644
--- a/arch/s390/kernel/s390_ext.c
+++ b/arch/s390/kernel/s390_ext.c
@@ -13,11 +13,12 @@
#include <linux/errno.h>
#include <linux/kernel_stat.h>
#include <linux/interrupt.h>
-
+#include <asm/cpu.h>
#include <asm/lowcore.h>
#include <asm/s390_ext.h>
#include <asm/irq_regs.h>
#include <asm/irq.h>
+#include "entry.h"
/*
* ext_int_hash[index] is the start of the list for all external interrupts
@@ -119,13 +120,10 @@
old_regs = set_irq_regs(regs);
irq_enter();
- asm volatile ("mc 0,0");
- if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer)
- /**
- * Make sure that the i/o interrupt did not "overtake"
- * the last HZ timer interrupt.
- */
- account_ticks(S390_lowcore.int_clock);
+ s390_idle_check();
+ if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
+ /* Serve timer interrupts first. */
+ clock_comparator_work();
kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
index = ext_hash(code);
for (p = ext_int_hash[index]; p; p = p->next) {
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 290e504..7141147 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -39,6 +39,7 @@
#include <linux/pfn.h>
#include <linux/ctype.h>
#include <linux/reboot.h>
+#include <linux/topology.h>
#include <asm/ipl.h>
#include <asm/uaccess.h>
@@ -427,7 +428,7 @@
lc->io_new_psw.mask = psw_kernel_bits;
lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
lc->ipl_device = S390_lowcore.ipl_device;
- lc->jiffy_timer = -1LL;
+ lc->clock_comparator = -1ULL;
lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
lc->async_stack = (unsigned long)
__alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE;
@@ -687,7 +688,7 @@
return S390_lowcore.stfl_fac_list;
}
-static __init int stfle(unsigned long long *list, int doublewords)
+static int __init __stfle(unsigned long long *list, int doublewords)
{
typedef struct { unsigned long long _[doublewords]; } addrtype;
register unsigned long __nr asm("0") = doublewords - 1;
@@ -697,6 +698,13 @@
return __nr + 1;
}
+int __init stfle(unsigned long long *list, int doublewords)
+{
+ if (!(stfl() & (1UL << 24)))
+ return -EOPNOTSUPP;
+ return __stfle(list, doublewords);
+}
+
/*
* Setup hardware capabilities.
*/
@@ -741,7 +749,7 @@
* HWCAP_S390_DFP bit 6.
*/
if ((elf_hwcap & (1UL << 2)) &&
- stfle(&facility_list_extended, 1) > 0) {
+ __stfle(&facility_list_extended, 1) > 0) {
if (facility_list_extended & (1ULL << (64 - 43)))
elf_hwcap |= 1UL << 6;
}
@@ -823,6 +831,7 @@
cpu_init();
__cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr;
+ s390_init_cpu_topology();
/*
* Setup capabilities (ELF_HWCAP & ELF_PLATFORM).
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 4449bf3..b976820 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -27,6 +27,7 @@
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/lowcore.h>
+#include "entry.h"
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -235,6 +236,10 @@
/* Default to using normal stack */
sp = regs->gprs[15];
+ /* Overflow on alternate signal stack gives SIGSEGV. */
+ if (on_sig_stack(sp) && !on_sig_stack((sp - frame_size) & -8UL))
+ return (void __user *) -1UL;
+
/* This is the X/Open sanctioned signal stack switching. */
if (ka->sa.sa_flags & SA_ONSTACK) {
if (! sas_ss_flags(sp))
@@ -270,6 +275,9 @@
if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe)))
goto give_sigsegv;
+ if (frame == (void __user *) -1UL)
+ goto give_sigsegv;
+
if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE))
goto give_sigsegv;
@@ -327,6 +335,9 @@
if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe)))
goto give_sigsegv;
+ if (frame == (void __user *) -1UL)
+ goto give_sigsegv;
+
if (copy_siginfo_to_user(&frame->info, info))
goto give_sigsegv;
@@ -474,11 +485,6 @@
int ret;
#ifdef CONFIG_COMPAT
if (test_thread_flag(TIF_31BIT)) {
- extern int handle_signal32(unsigned long sig,
- struct k_sigaction *ka,
- siginfo_t *info,
- sigset_t *oldset,
- struct pt_regs *regs);
ret = handle_signal32(signr, &ka, &info, oldset, regs);
}
else
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 8f894d3..0dfa988 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -44,6 +44,7 @@
#include <asm/lowcore.h>
#include <asm/sclp.h>
#include <asm/cpu.h>
+#include "entry.h"
/*
* An array with a pointer the lowcore of every CPU.
@@ -67,13 +68,12 @@
CPU_STATE_CONFIGURED,
};
-#ifdef CONFIG_HOTPLUG_CPU
-static DEFINE_MUTEX(smp_cpu_state_mutex);
-#endif
+DEFINE_MUTEX(smp_cpu_state_mutex);
+int smp_cpu_polarization[NR_CPUS];
static int smp_cpu_state[NR_CPUS];
+static int cpu_management;
static DEFINE_PER_CPU(struct cpu, cpu_devices);
-DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
static void smp_ext_bitcall(int, ec_bit_sig);
@@ -298,7 +298,7 @@
/*
* this function sends a 'purge tlb' signal to another CPU.
*/
-void smp_ptlb_callback(void *info)
+static void smp_ptlb_callback(void *info)
{
__tlb_flush_local();
}
@@ -456,6 +456,7 @@
if (cpu_known(cpu_id))
continue;
__cpu_logical_map[logical_cpu] = cpu_id;
+ smp_cpu_polarization[logical_cpu] = POLARIZATION_UNKNWN;
if (!cpu_stopped(logical_cpu))
continue;
cpu_set(logical_cpu, cpu_present_map);
@@ -489,6 +490,7 @@
if (cpu_known(cpu_id))
continue;
__cpu_logical_map[logical_cpu] = cpu_id;
+ smp_cpu_polarization[logical_cpu] = POLARIZATION_UNKNWN;
cpu_set(logical_cpu, cpu_present_map);
if (cpu >= info->configured)
smp_cpu_state[logical_cpu] = CPU_STATE_STANDBY;
@@ -846,6 +848,7 @@
S390_lowcore.percpu_offset = __per_cpu_offset[0];
current_set[0] = current;
smp_cpu_state[0] = CPU_STATE_CONFIGURED;
+ smp_cpu_polarization[0] = POLARIZATION_UNKNWN;
spin_lock_init(&(&__get_cpu_var(s390_idle))->lock);
}
@@ -897,15 +900,19 @@
case 0:
if (smp_cpu_state[cpu] == CPU_STATE_CONFIGURED) {
rc = sclp_cpu_deconfigure(__cpu_logical_map[cpu]);
- if (!rc)
+ if (!rc) {
smp_cpu_state[cpu] = CPU_STATE_STANDBY;
+ smp_cpu_polarization[cpu] = POLARIZATION_UNKNWN;
+ }
}
break;
case 1:
if (smp_cpu_state[cpu] == CPU_STATE_STANDBY) {
rc = sclp_cpu_configure(__cpu_logical_map[cpu]);
- if (!rc)
+ if (!rc) {
smp_cpu_state[cpu] = CPU_STATE_CONFIGURED;
+ smp_cpu_polarization[cpu] = POLARIZATION_UNKNWN;
+ }
}
break;
default:
@@ -919,6 +926,34 @@
static SYSDEV_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store);
#endif /* CONFIG_HOTPLUG_CPU */
+static ssize_t cpu_polarization_show(struct sys_device *dev, char *buf)
+{
+ int cpu = dev->id;
+ ssize_t count;
+
+ mutex_lock(&smp_cpu_state_mutex);
+ switch (smp_cpu_polarization[cpu]) {
+ case POLARIZATION_HRZ:
+ count = sprintf(buf, "horizontal\n");
+ break;
+ case POLARIZATION_VL:
+ count = sprintf(buf, "vertical:low\n");
+ break;
+ case POLARIZATION_VM:
+ count = sprintf(buf, "vertical:medium\n");
+ break;
+ case POLARIZATION_VH:
+ count = sprintf(buf, "vertical:high\n");
+ break;
+ default:
+ count = sprintf(buf, "unknown\n");
+ break;
+ }
+ mutex_unlock(&smp_cpu_state_mutex);
+ return count;
+}
+static SYSDEV_ATTR(polarization, 0444, cpu_polarization_show, NULL);
+
static ssize_t show_cpu_address(struct sys_device *dev, char *buf)
{
return sprintf(buf, "%d\n", __cpu_logical_map[dev->id]);
@@ -931,6 +966,7 @@
&attr_configure.attr,
#endif
&attr_address.attr,
+ &attr_polarization.attr,
NULL,
};
@@ -1075,11 +1111,48 @@
out:
put_online_cpus();
mutex_unlock(&smp_cpu_state_mutex);
+ if (!cpus_empty(newcpus))
+ topology_schedule_update();
return rc ? rc : count;
}
static SYSDEV_ATTR(rescan, 0200, NULL, rescan_store);
#endif /* CONFIG_HOTPLUG_CPU */
+static ssize_t dispatching_show(struct sys_device *dev, char *buf)
+{
+ ssize_t count;
+
+ mutex_lock(&smp_cpu_state_mutex);
+ count = sprintf(buf, "%d\n", cpu_management);
+ mutex_unlock(&smp_cpu_state_mutex);
+ return count;
+}
+
+static ssize_t dispatching_store(struct sys_device *dev, const char *buf,
+ size_t count)
+{
+ int val, rc;
+ char delim;
+
+ if (sscanf(buf, "%d %c", &val, &delim) != 1)
+ return -EINVAL;
+ if (val != 0 && val != 1)
+ return -EINVAL;
+ rc = 0;
+ mutex_lock(&smp_cpu_state_mutex);
+ get_online_cpus();
+ if (cpu_management == val)
+ goto out;
+ rc = topology_set_cpu_management(val);
+ if (!rc)
+ cpu_management = val;
+out:
+ put_online_cpus();
+ mutex_unlock(&smp_cpu_state_mutex);
+ return rc ? rc : count;
+}
+static SYSDEV_ATTR(dispatching, 0644, dispatching_show, dispatching_store);
+
static int __init topology_init(void)
{
int cpu;
@@ -1093,6 +1166,10 @@
if (rc)
return rc;
#endif
+ rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
+ &attr_dispatching.attr);
+ if (rc)
+ return rc;
for_each_present_cpu(cpu) {
rc = smp_add_present_cpu(cpu);
if (rc)
diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c
index fefee99..988d0d6 100644
--- a/arch/s390/kernel/sys_s390.c
+++ b/arch/s390/kernel/sys_s390.c
@@ -29,8 +29,8 @@
#include <linux/personality.h>
#include <linux/unistd.h>
#include <linux/ipc.h>
-
#include <asm/uaccess.h>
+#include "entry.h"
/*
* sys_pipe() is the normal C calling standard for creating
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index cb232c1..7aec676 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -30,7 +30,7 @@
#include <linux/timex.h>
#include <linux/notifier.h>
#include <linux/clocksource.h>
-
+#include <linux/clockchips.h>
#include <asm/uaccess.h>
#include <asm/delay.h>
#include <asm/s390_ext.h>
@@ -39,6 +39,7 @@
#include <asm/irq_regs.h>
#include <asm/timer.h>
#include <asm/etr.h>
+#include <asm/cio.h>
/* change this if you have some constant time drift */
#define USECS_PER_JIFFY ((unsigned long) 1000000/HZ)
@@ -57,16 +58,16 @@
static ext_int_info_t ext_int_info_cc;
static ext_int_info_t ext_int_etr_cc;
-static u64 init_timer_cc;
static u64 jiffies_timer_cc;
-static u64 xtime_cc;
+
+static DEFINE_PER_CPU(struct clock_event_device, comparators);
/*
* Scheduler clock - returns current time in nanosec units.
*/
unsigned long long sched_clock(void)
{
- return ((get_clock() - jiffies_timer_cc) * 125) >> 9;
+ return ((get_clock_xt() - jiffies_timer_cc) * 125) >> 9;
}
/*
@@ -95,162 +96,40 @@
#define s390_do_profile() do { ; } while(0)
#endif /* CONFIG_PROFILING */
-/*
- * Advance the per cpu tick counter up to the time given with the
- * "time" argument. The per cpu update consists of accounting
- * the virtual cpu time, calling update_process_times and calling
- * the profiling hook. If xtime is before time it is advanced as well.
- */
-void account_ticks(u64 time)
+void clock_comparator_work(void)
{
- __u32 ticks;
- __u64 tmp;
+ struct clock_event_device *cd;
- /* Calculate how many ticks have passed. */
- if (time < S390_lowcore.jiffy_timer)
- return;
- tmp = time - S390_lowcore.jiffy_timer;
- if (tmp >= 2*CLK_TICKS_PER_JIFFY) { /* more than two ticks ? */
- ticks = __div(tmp, CLK_TICKS_PER_JIFFY) + 1;
- S390_lowcore.jiffy_timer +=
- CLK_TICKS_PER_JIFFY * (__u64) ticks;
- } else if (tmp >= CLK_TICKS_PER_JIFFY) {
- ticks = 2;
- S390_lowcore.jiffy_timer += 2*CLK_TICKS_PER_JIFFY;
- } else {
- ticks = 1;
- S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY;
- }
-
-#ifdef CONFIG_SMP
- /*
- * Do not rely on the boot cpu to do the calls to do_timer.
- * Spread it over all cpus instead.
- */
- write_seqlock(&xtime_lock);
- if (S390_lowcore.jiffy_timer > xtime_cc) {
- __u32 xticks;
- tmp = S390_lowcore.jiffy_timer - xtime_cc;
- if (tmp >= 2*CLK_TICKS_PER_JIFFY) {
- xticks = __div(tmp, CLK_TICKS_PER_JIFFY);
- xtime_cc += (__u64) xticks * CLK_TICKS_PER_JIFFY;
- } else {
- xticks = 1;
- xtime_cc += CLK_TICKS_PER_JIFFY;
- }
- do_timer(xticks);
- }
- write_sequnlock(&xtime_lock);
-#else
- do_timer(ticks);
-#endif
-
- while (ticks--)
- update_process_times(user_mode(get_irq_regs()));
-
+ S390_lowcore.clock_comparator = -1ULL;
+ set_clock_comparator(S390_lowcore.clock_comparator);
+ cd = &__get_cpu_var(comparators);
+ cd->event_handler(cd);
s390_do_profile();
}
-#ifdef CONFIG_NO_IDLE_HZ
-
-#ifdef CONFIG_NO_IDLE_HZ_INIT
-int sysctl_hz_timer = 0;
-#else
-int sysctl_hz_timer = 1;
-#endif
-
/*
- * Stop the HZ tick on the current CPU.
- * Only cpu_idle may call this function.
+ * Fixup the clock comparator.
*/
-static void stop_hz_timer(void)
+static void fixup_clock_comparator(unsigned long long delta)
{
- unsigned long flags;
- unsigned long seq, next;
- __u64 timer, todval;
- int cpu = smp_processor_id();
-
- if (sysctl_hz_timer != 0)
+ /* If nobody is waiting there's nothing to fix. */
+ if (S390_lowcore.clock_comparator == -1ULL)
return;
-
- cpu_set(cpu, nohz_cpu_mask);
-
- /*
- * Leave the clock comparator set up for the next timer
- * tick if either rcu or a softirq is pending.
- */
- if (rcu_needs_cpu(cpu) || local_softirq_pending()) {
- cpu_clear(cpu, nohz_cpu_mask);
- return;
- }
-
- /*
- * This cpu is going really idle. Set up the clock comparator
- * for the next event.
- */
- next = next_timer_interrupt();
- do {
- seq = read_seqbegin_irqsave(&xtime_lock, flags);
- timer = ((__u64) next) - ((__u64) jiffies) + jiffies_64;
- } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
- todval = -1ULL;
- /* Be careful about overflows. */
- if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) {
- timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY;
- if (timer >= jiffies_timer_cc)
- todval = timer;
- }
- set_clock_comparator(todval);
+ S390_lowcore.clock_comparator += delta;
+ set_clock_comparator(S390_lowcore.clock_comparator);
}
-/*
- * Start the HZ tick on the current CPU.
- * Only cpu_idle may call this function.
- */
-static void start_hz_timer(void)
+static int s390_next_event(unsigned long delta,
+ struct clock_event_device *evt)
{
- if (!cpu_isset(smp_processor_id(), nohz_cpu_mask))
- return;
- account_ticks(get_clock());
- set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION);
- cpu_clear(smp_processor_id(), nohz_cpu_mask);
+ S390_lowcore.clock_comparator = get_clock() + delta;
+ set_clock_comparator(S390_lowcore.clock_comparator);
+ return 0;
}
-static int nohz_idle_notify(struct notifier_block *self,
- unsigned long action, void *hcpu)
+static void s390_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
{
- switch (action) {
- case S390_CPU_IDLE:
- stop_hz_timer();
- break;
- case S390_CPU_NOT_IDLE:
- start_hz_timer();
- break;
- }
- return NOTIFY_OK;
-}
-
-static struct notifier_block nohz_idle_nb = {
- .notifier_call = nohz_idle_notify,
-};
-
-static void __init nohz_init(void)
-{
- if (register_idle_notifier(&nohz_idle_nb))
- panic("Couldn't register idle notifier");
-}
-
-#endif
-
-/*
- * Set up per cpu jiffy timer and set the clock comparator.
- */
-static void setup_jiffy_timer(void)
-{
- /* Set up clock comparator to next jiffy. */
- S390_lowcore.jiffy_timer =
- jiffies_timer_cc + (jiffies_64 + 1) * CLK_TICKS_PER_JIFFY;
- set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION);
}
/*
@@ -259,7 +138,26 @@
*/
void init_cpu_timer(void)
{
- setup_jiffy_timer();
+ struct clock_event_device *cd;
+ int cpu;
+
+ S390_lowcore.clock_comparator = -1ULL;
+ set_clock_comparator(S390_lowcore.clock_comparator);
+
+ cpu = smp_processor_id();
+ cd = &per_cpu(comparators, cpu);
+ cd->name = "comparator";
+ cd->features = CLOCK_EVT_FEAT_ONESHOT;
+ cd->mult = 16777;
+ cd->shift = 12;
+ cd->min_delta_ns = 1;
+ cd->max_delta_ns = LONG_MAX;
+ cd->rating = 400;
+ cd->cpumask = cpumask_of_cpu(cpu);
+ cd->set_next_event = s390_next_event;
+ cd->set_mode = s390_set_mode;
+
+ clockevents_register_device(cd);
/* Enable clock comparator timer interrupt. */
__ctl_set_bit(0,11);
@@ -270,8 +168,6 @@
static void clock_comparator_interrupt(__u16 code)
{
- /* set clock comparator for next tick */
- set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION);
}
static void etr_reset(void);
@@ -316,8 +212,9 @@
*/
void __init time_init(void)
{
+ u64 init_timer_cc;
+
init_timer_cc = reset_tod_clock();
- xtime_cc = init_timer_cc + CLK_TICKS_PER_JIFFY;
jiffies_timer_cc = init_timer_cc - jiffies_64 * CLK_TICKS_PER_JIFFY;
/* set xtime */
@@ -342,10 +239,6 @@
/* Enable TOD clock interrupts on the boot cpu. */
init_cpu_timer();
-#ifdef CONFIG_NO_IDLE_HZ
- nohz_init();
-#endif
-
#ifdef CONFIG_VIRT_TIMER
vtime_init();
#endif
@@ -699,53 +592,49 @@
}
/*
- * The time is "clock". xtime is what we think the time is.
+ * The time is "clock". old is what we think the time is.
* Adjust the value by a multiple of jiffies and add the delta to ntp.
* "delay" is an approximation how long the synchronization took. If
* the time correction is positive, then "delay" is subtracted from
* the time difference and only the remaining part is passed to ntp.
*/
-static void etr_adjust_time(unsigned long long clock, unsigned long long delay)
+static unsigned long long etr_adjust_time(unsigned long long old,
+ unsigned long long clock,
+ unsigned long long delay)
{
unsigned long long delta, ticks;
struct timex adjust;
- /*
- * We don't have to take the xtime lock because the cpu
- * executing etr_adjust_time is running disabled in
- * tasklet context and all other cpus are looping in
- * etr_sync_cpu_start.
- */
- if (clock > xtime_cc) {
+ if (clock > old) {
/* It is later than we thought. */
- delta = ticks = clock - xtime_cc;
+ delta = ticks = clock - old;
delta = ticks = (delta < delay) ? 0 : delta - delay;
delta -= do_div(ticks, CLK_TICKS_PER_JIFFY);
- init_timer_cc = init_timer_cc + delta;
- jiffies_timer_cc = jiffies_timer_cc + delta;
- xtime_cc = xtime_cc + delta;
adjust.offset = ticks * (1000000 / HZ);
} else {
/* It is earlier than we thought. */
- delta = ticks = xtime_cc - clock;
+ delta = ticks = old - clock;
delta -= do_div(ticks, CLK_TICKS_PER_JIFFY);
- init_timer_cc = init_timer_cc - delta;
- jiffies_timer_cc = jiffies_timer_cc - delta;
- xtime_cc = xtime_cc - delta;
+ delta = -delta;
adjust.offset = -ticks * (1000000 / HZ);
}
+ jiffies_timer_cc += delta;
if (adjust.offset != 0) {
printk(KERN_NOTICE "etr: time adjusted by %li micro-seconds\n",
adjust.offset);
adjust.modes = ADJ_OFFSET_SINGLESHOT;
do_adjtimex(&adjust);
}
+ return delta;
}
+static struct {
+ int in_sync;
+ unsigned long long fixup_cc;
+} etr_sync;
+
static void etr_sync_cpu_start(void *dummy)
{
- int *in_sync = dummy;
-
etr_enable_sync_clock();
/*
* This looks like a busy wait loop but it isn't. etr_sync_cpus
@@ -753,7 +642,7 @@
* __udelay will stop the cpu on an enabled wait psw until the
* TOD is running again.
*/
- while (*in_sync == 0) {
+ while (etr_sync.in_sync == 0) {
__udelay(1);
/*
* A different cpu changes *in_sync. Therefore use
@@ -761,14 +650,14 @@
*/
barrier();
}
- if (*in_sync != 1)
+ if (etr_sync.in_sync != 1)
/* Didn't work. Clear per-cpu in sync bit again. */
etr_disable_sync_clock(NULL);
/*
* This round of TOD syncing is done. Set the clock comparator
* to the next tick and let the processor continue.
*/
- setup_jiffy_timer();
+ fixup_clock_comparator(etr_sync.fixup_cc);
}
static void etr_sync_cpu_end(void *dummy)
@@ -783,8 +672,8 @@
static int etr_sync_clock(struct etr_aib *aib, int port)
{
struct etr_aib *sync_port;
- unsigned long long clock, delay;
- int in_sync, follows;
+ unsigned long long clock, old_clock, delay, delta;
+ int follows;
int rc;
/* Check if the current aib is adjacent to the sync port aib. */
@@ -799,9 +688,9 @@
* successfully synced the clock. smp_call_function will
* return after all other cpus are in etr_sync_cpu_start.
*/
- in_sync = 0;
+ memset(&etr_sync, 0, sizeof(etr_sync));
preempt_disable();
- smp_call_function(etr_sync_cpu_start,&in_sync,0,0);
+ smp_call_function(etr_sync_cpu_start, NULL, 0, 0);
local_irq_disable();
etr_enable_sync_clock();
@@ -809,6 +698,7 @@
__ctl_set_bit(14, 21);
__ctl_set_bit(0, 29);
clock = ((unsigned long long) (aib->edf2.etv + 1)) << 32;
+ old_clock = get_clock();
if (set_clock(clock) == 0) {
__udelay(1); /* Wait for the clock to start. */
__ctl_clear_bit(0, 29);
@@ -817,16 +707,17 @@
/* Adjust Linux timing variables. */
delay = (unsigned long long)
(aib->edf2.etv - sync_port->edf2.etv) << 32;
- etr_adjust_time(clock, delay);
- setup_jiffy_timer();
+ delta = etr_adjust_time(old_clock, clock, delay);
+ etr_sync.fixup_cc = delta;
+ fixup_clock_comparator(delta);
/* Verify that the clock is properly set. */
if (!etr_aib_follows(sync_port, aib, port)) {
/* Didn't work. */
etr_disable_sync_clock(NULL);
- in_sync = -EAGAIN;
+ etr_sync.in_sync = -EAGAIN;
rc = -EAGAIN;
} else {
- in_sync = 1;
+ etr_sync.in_sync = 1;
rc = 0;
}
} else {
@@ -834,7 +725,7 @@
__ctl_clear_bit(0, 29);
__ctl_clear_bit(14, 21);
etr_disable_sync_clock(NULL);
- in_sync = -EAGAIN;
+ etr_sync.in_sync = -EAGAIN;
rc = -EAGAIN;
}
local_irq_enable();
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
new file mode 100644
index 0000000..12b39b3
--- /dev/null
+++ b/arch/s390/kernel/topology.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright IBM Corp. 2007
+ * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/bootmem.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#include <asm/delay.h>
+#include <asm/s390_ext.h>
+#include <asm/sysinfo.h>
+
+#define CPU_BITS 64
+#define NR_MAG 6
+
+#define PTF_HORIZONTAL (0UL)
+#define PTF_VERTICAL (1UL)
+#define PTF_CHECK (2UL)
+
+struct tl_cpu {
+ unsigned char reserved0[4];
+ unsigned char :6;
+ unsigned char pp:2;
+ unsigned char reserved1;
+ unsigned short origin;
+ unsigned long mask[CPU_BITS / BITS_PER_LONG];
+};
+
+struct tl_container {
+ unsigned char reserved[8];
+};
+
+union tl_entry {
+ unsigned char nl;
+ struct tl_cpu cpu;
+ struct tl_container container;
+};
+
+struct tl_info {
+ unsigned char reserved0[2];
+ unsigned short length;
+ unsigned char mag[NR_MAG];
+ unsigned char reserved1;
+ unsigned char mnest;
+ unsigned char reserved2[4];
+ union tl_entry tle[0];
+};
+
+struct core_info {
+ struct core_info *next;
+ cpumask_t mask;
+};
+
+static void topology_work_fn(struct work_struct *work);
+static struct tl_info *tl_info;
+static struct core_info core_info;
+static int machine_has_topology;
+static int machine_has_topology_irq;
+static struct timer_list topology_timer;
+static void set_topology_timer(void);
+static DECLARE_WORK(topology_work, topology_work_fn);
+
+cpumask_t cpu_coregroup_map(unsigned int cpu)
+{
+ struct core_info *core = &core_info;
+ cpumask_t mask;
+
+ cpus_clear(mask);
+ if (!machine_has_topology)
+ return cpu_present_map;
+ mutex_lock(&smp_cpu_state_mutex);
+ while (core) {
+ if (cpu_isset(cpu, core->mask)) {
+ mask = core->mask;
+ break;
+ }
+ core = core->next;
+ }
+ mutex_unlock(&smp_cpu_state_mutex);
+ if (cpus_empty(mask))
+ mask = cpumask_of_cpu(cpu);
+ return mask;
+}
+
+static void add_cpus_to_core(struct tl_cpu *tl_cpu, struct core_info *core)
+{
+ unsigned int cpu;
+
+ for (cpu = find_first_bit(&tl_cpu->mask[0], CPU_BITS);
+ cpu < CPU_BITS;
+ cpu = find_next_bit(&tl_cpu->mask[0], CPU_BITS, cpu + 1))
+ {
+ unsigned int rcpu, lcpu;
+
+ rcpu = CPU_BITS - 1 - cpu + tl_cpu->origin;
+ for_each_present_cpu(lcpu) {
+ if (__cpu_logical_map[lcpu] == rcpu) {
+ cpu_set(lcpu, core->mask);
+ smp_cpu_polarization[lcpu] = tl_cpu->pp;
+ }
+ }
+ }
+}
+
+static void clear_cores(void)
+{
+ struct core_info *core = &core_info;
+
+ while (core) {
+ cpus_clear(core->mask);
+ core = core->next;
+ }
+}
+
+static union tl_entry *next_tle(union tl_entry *tle)
+{
+ if (tle->nl)
+ return (union tl_entry *)((struct tl_container *)tle + 1);
+ else
+ return (union tl_entry *)((struct tl_cpu *)tle + 1);
+}
+
+static void tl_to_cores(struct tl_info *info)
+{
+ union tl_entry *tle, *end;
+ struct core_info *core = &core_info;
+
+ mutex_lock(&smp_cpu_state_mutex);
+ clear_cores();
+ tle = info->tle;
+ end = (union tl_entry *)((unsigned long)info + info->length);
+ while (tle < end) {
+ switch (tle->nl) {
+ case 5:
+ case 4:
+ case 3:
+ case 2:
+ break;
+ case 1:
+ core = core->next;
+ break;
+ case 0:
+ add_cpus_to_core(&tle->cpu, core);
+ break;
+ default:
+ clear_cores();
+ machine_has_topology = 0;
+ return;
+ }
+ tle = next_tle(tle);
+ }
+ mutex_unlock(&smp_cpu_state_mutex);
+}
+
+static void topology_update_polarization_simple(void)
+{
+ int cpu;
+
+ mutex_lock(&smp_cpu_state_mutex);
+ for_each_present_cpu(cpu)
+ smp_cpu_polarization[cpu] = POLARIZATION_HRZ;
+ mutex_unlock(&smp_cpu_state_mutex);
+}
+
+static int ptf(unsigned long fc)
+{
+ int rc;
+
+ asm volatile(
+ " .insn rre,0xb9a20000,%1,%1\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ : "=d" (rc)
+ : "d" (fc) : "cc");
+ return rc;
+}
+
+int topology_set_cpu_management(int fc)
+{
+ int cpu;
+ int rc;
+
+ if (!machine_has_topology)
+ return -EOPNOTSUPP;
+ if (fc)
+ rc = ptf(PTF_VERTICAL);
+ else
+ rc = ptf(PTF_HORIZONTAL);
+ if (rc)
+ return -EBUSY;
+ for_each_present_cpu(cpu)
+ smp_cpu_polarization[cpu] = POLARIZATION_UNKNWN;
+ return rc;
+}
+
+void arch_update_cpu_topology(void)
+{
+ struct tl_info *info = tl_info;
+ struct sys_device *sysdev;
+ int cpu;
+
+ if (!machine_has_topology) {
+ topology_update_polarization_simple();
+ return;
+ }
+ stsi(info, 15, 1, 2);
+ tl_to_cores(info);
+ for_each_online_cpu(cpu) {
+ sysdev = get_cpu_sysdev(cpu);
+ kobject_uevent(&sysdev->kobj, KOBJ_CHANGE);
+ }
+}
+
+static void topology_work_fn(struct work_struct *work)
+{
+ arch_reinit_sched_domains();
+}
+
+void topology_schedule_update(void)
+{
+ schedule_work(&topology_work);
+}
+
+static void topology_timer_fn(unsigned long ignored)
+{
+ if (ptf(PTF_CHECK))
+ topology_schedule_update();
+ set_topology_timer();
+}
+
+static void set_topology_timer(void)
+{
+ topology_timer.function = topology_timer_fn;
+ topology_timer.data = 0;
+ topology_timer.expires = jiffies + 60 * HZ;
+ add_timer(&topology_timer);
+}
+
+static void topology_interrupt(__u16 code)
+{
+ schedule_work(&topology_work);
+}
+
+static int __init init_topology_update(void)
+{
+ int rc;
+
+ if (!machine_has_topology) {
+ topology_update_polarization_simple();
+ return 0;
+ }
+ init_timer_deferrable(&topology_timer);
+ if (machine_has_topology_irq) {
+ rc = register_external_interrupt(0x2005, topology_interrupt);
+ if (rc)
+ return rc;
+ ctl_set_bit(0, 8);
+ }
+ else
+ set_topology_timer();
+ return 0;
+}
+__initcall(init_topology_update);
+
+void __init s390_init_cpu_topology(void)
+{
+ unsigned long long facility_bits;
+ struct tl_info *info;
+ struct core_info *core;
+ int nr_cores;
+ int i;
+
+ if (stfle(&facility_bits, 1) <= 0)
+ return;
+ if (!(facility_bits & (1ULL << 52)) || !(facility_bits & (1ULL << 61)))
+ return;
+ machine_has_topology = 1;
+
+ if (facility_bits & (1ULL << 51))
+ machine_has_topology_irq = 1;
+
+ tl_info = alloc_bootmem_pages(PAGE_SIZE);
+ if (!tl_info)
+ goto error;
+ info = tl_info;
+ stsi(info, 15, 1, 2);
+
+ nr_cores = info->mag[NR_MAG - 2];
+ for (i = 0; i < info->mnest - 2; i++)
+ nr_cores *= info->mag[NR_MAG - 3 - i];
+
+ printk(KERN_INFO "CPU topology:");
+ for (i = 0; i < NR_MAG; i++)
+ printk(" %d", info->mag[i]);
+ printk(" / %d\n", info->mnest);
+
+ core = &core_info;
+ for (i = 0; i < nr_cores; i++) {
+ core->next = alloc_bootmem(sizeof(struct core_info));
+ core = core->next;
+ if (!core)
+ goto error;
+ }
+ return;
+error:
+ machine_has_topology = 0;
+ machine_has_topology_irq = 0;
+}
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 60f728a..57b607b 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -42,11 +42,8 @@
#include <asm/s390_ext.h>
#include <asm/lowcore.h>
#include <asm/debug.h>
+#include "entry.h"
-/* Called from entry.S only */
-extern void handle_per_exception(struct pt_regs *regs);
-
-typedef void pgm_check_handler_t(struct pt_regs *, long);
pgm_check_handler_t *pgm_check_table[128];
#ifdef CONFIG_SYSCTL
@@ -59,7 +56,6 @@
extern pgm_check_handler_t do_protection_exception;
extern pgm_check_handler_t do_dat_exception;
-extern pgm_check_handler_t do_monitor_call;
extern pgm_check_handler_t do_asce_exception;
#define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
@@ -138,7 +134,6 @@
else
__show_trace(sp, S390_lowcore.thread_info,
S390_lowcore.thread_info + THREAD_SIZE);
- printk("\n");
if (!task)
task = current;
debug_show_held_locks(task);
@@ -166,6 +161,15 @@
show_trace(task, sp);
}
+#ifdef CONFIG_64BIT
+void show_last_breaking_event(struct pt_regs *regs)
+{
+ printk("Last Breaking-Event-Address:\n");
+ printk(" [<%016lx>] ", regs->args[0] & PSW_ADDR_INSN);
+ print_symbol("%s\n", regs->args[0] & PSW_ADDR_INSN);
+}
+#endif
+
/*
* The architecture-independent dump_stack generator
*/
@@ -739,6 +743,5 @@
pgm_check_table[0x15] = &operand_exception;
pgm_check_table[0x1C] = &space_switch_exception;
pgm_check_table[0x1D] = &hfp_sqrt_exception;
- pgm_check_table[0x40] = &do_monitor_call;
pfault_irq_init();
}
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index 70f2a86..eae21a8 100644
--- a/arch/s390/lib/delay.c
+++ b/arch/s390/lib/delay.c
@@ -34,7 +34,7 @@
*/
void __udelay(unsigned long usecs)
{
- u64 end, time, jiffy_timer = 0;
+ u64 end, time, old_cc = 0;
unsigned long flags, cr0, mask, dummy;
int irq_context;
@@ -43,8 +43,8 @@
local_bh_disable();
local_irq_save(flags);
if (raw_irqs_disabled_flags(flags)) {
- jiffy_timer = S390_lowcore.jiffy_timer;
- S390_lowcore.jiffy_timer = -1ULL - (4096 << 12);
+ old_cc = S390_lowcore.clock_comparator;
+ S390_lowcore.clock_comparator = -1ULL;
__ctl_store(cr0, 0, 0);
dummy = (cr0 & 0xffff00e0) | 0x00000800;
__ctl_load(dummy , 0, 0);
@@ -55,8 +55,8 @@
end = get_clock() + ((u64) usecs << 12);
do {
- time = end < S390_lowcore.jiffy_timer ?
- end : S390_lowcore.jiffy_timer;
+ time = end < S390_lowcore.clock_comparator ?
+ end : S390_lowcore.clock_comparator;
set_clock_comparator(time);
trace_hardirqs_on();
__load_psw_mask(mask);
@@ -65,10 +65,10 @@
if (raw_irqs_disabled_flags(flags)) {
__ctl_load(cr0, 0, 0);
- S390_lowcore.jiffy_timer = jiffy_timer;
+ S390_lowcore.clock_comparator = old_cc;
}
if (!irq_context)
_local_bh_enable();
- set_clock_comparator(S390_lowcore.jiffy_timer);
+ set_clock_comparator(S390_lowcore.clock_comparator);
local_irq_restore(flags);
}
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 5efdfe9..d66215b 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -302,6 +302,10 @@
pte_t *pte_from, *pte_to;
int write_user;
+ if (segment_eq(get_fs(), KERNEL_DS)) {
+ memcpy((void __force *) to, (void __force *) from, n);
+ return 0;
+ }
done = 0;
retry:
spin_lock(&mm->page_table_lock);
@@ -361,18 +365,10 @@
: "0" (-EFAULT), "d" (oparg), "a" (uaddr), \
"m" (*uaddr) : "cc" );
-int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
{
int oldval = 0, newval, ret;
- spin_lock(¤t->mm->page_table_lock);
- uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
- if (!uaddr) {
- spin_unlock(¤t->mm->page_table_lock);
- return -EFAULT;
- }
- get_page(virt_to_page(uaddr));
- spin_unlock(¤t->mm->page_table_lock);
switch (op) {
case FUTEX_OP_SET:
__futex_atomic_op("lr %2,%5\n",
@@ -397,17 +393,17 @@
default:
ret = -ENOSYS;
}
- put_page(virt_to_page(uaddr));
- *old = oldval;
+ if (ret == 0)
+ *old = oldval;
return ret;
}
-int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
{
int ret;
- if (!current->mm)
- return -EFAULT;
+ if (segment_eq(get_fs(), KERNEL_DS))
+ return __futex_atomic_op_pt(op, uaddr, oparg, old);
spin_lock(¤t->mm->page_table_lock);
uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
if (!uaddr) {
@@ -416,13 +412,40 @@
}
get_page(virt_to_page(uaddr));
spin_unlock(¤t->mm->page_table_lock);
- asm volatile(" cs %1,%4,0(%5)\n"
- "0: lr %0,%1\n"
- "1:\n"
- EX_TABLE(0b,1b)
+ ret = __futex_atomic_op_pt(op, uaddr, oparg, old);
+ put_page(virt_to_page(uaddr));
+ return ret;
+}
+
+static int __futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+{
+ int ret;
+
+ asm volatile("0: cs %1,%4,0(%5)\n"
+ "1: lr %0,%1\n"
+ "2:\n"
+ EX_TABLE(0b,2b) EX_TABLE(1b,2b)
: "=d" (ret), "+d" (oldval), "=m" (*uaddr)
: "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
: "cc", "memory" );
+ return ret;
+}
+
+int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+{
+ int ret;
+
+ if (segment_eq(get_fs(), KERNEL_DS))
+ return __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
+ spin_lock(¤t->mm->page_table_lock);
+ uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
+ if (!uaddr) {
+ spin_unlock(¤t->mm->page_table_lock);
+ return -EFAULT;
+ }
+ get_page(virt_to_page(uaddr));
+ spin_unlock(¤t->mm->page_table_lock);
+ ret = __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
put_page(virt_to_page(uaddr));
return ret;
}
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index 880b0eb..ed2af0a 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -289,22 +289,8 @@
rc = add_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
- switch (rc) {
- case 0:
- break;
- case -ENOSPC:
- PRINT_WARN("segment_load: not loading segment %s - overlaps "
- "storage/segment\n", name);
+ if (rc)
goto out_free;
- case -ERANGE:
- PRINT_WARN("segment_load: not loading segment %s - exceeds "
- "kernel mapping range\n", name);
- goto out_free;
- default:
- PRINT_WARN("segment_load: not loading segment %s (rc: %d)\n",
- name, rc);
- goto out_free;
- }
seg->res = kzalloc(sizeof(struct resource), GFP_KERNEL);
if (seg->res == NULL) {
@@ -582,8 +568,59 @@
mutex_unlock(&dcss_lock);
}
+/*
+ * print appropriate error message for segment_load()/segment_type()
+ * return code
+ */
+void segment_warning(int rc, char *seg_name)
+{
+ switch (rc) {
+ case -ENOENT:
+ PRINT_WARN("cannot load/query segment %s, "
+ "does not exist\n", seg_name);
+ break;
+ case -ENOSYS:
+ PRINT_WARN("cannot load/query segment %s, "
+ "not running on VM\n", seg_name);
+ break;
+ case -EIO:
+ PRINT_WARN("cannot load/query segment %s, "
+ "hardware error\n", seg_name);
+ break;
+ case -ENOTSUPP:
+ PRINT_WARN("cannot load/query segment %s, "
+ "is a multi-part segment\n", seg_name);
+ break;
+ case -ENOSPC:
+ PRINT_WARN("cannot load/query segment %s, "
+ "overlaps with storage\n", seg_name);
+ break;
+ case -EBUSY:
+ PRINT_WARN("cannot load/query segment %s, "
+ "overlaps with already loaded dcss\n", seg_name);
+ break;
+ case -EPERM:
+ PRINT_WARN("cannot load/query segment %s, "
+ "already loaded in incompatible mode\n", seg_name);
+ break;
+ case -ENOMEM:
+ PRINT_WARN("cannot load/query segment %s, "
+ "out of memory\n", seg_name);
+ break;
+ case -ERANGE:
+ PRINT_WARN("cannot load/query segment %s, "
+ "exceeds kernel mapping range\n", seg_name);
+ break;
+ default:
+ PRINT_WARN("cannot load/query segment %s, "
+ "return value %i\n", seg_name, rc);
+ break;
+ }
+}
+
EXPORT_SYMBOL(segment_load);
EXPORT_SYMBOL(segment_unload);
EXPORT_SYMBOL(segment_save);
EXPORT_SYMBOL(segment_type);
EXPORT_SYMBOL(segment_modify_shared);
+EXPORT_SYMBOL(segment_warning);
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index ed13d42..2650f46 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -28,11 +28,11 @@
#include <linux/hardirq.h>
#include <linux/kprobes.h>
#include <linux/uaccess.h>
-
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/s390_ext.h>
#include <asm/mmu_context.h>
+#include "../kernel/entry.h"
#ifndef CONFIG_64BIT
#define __FAIL_ADDR_MASK 0x7ffff000
@@ -50,8 +50,6 @@
extern int sysctl_userprocess_debug;
#endif
-extern void die(const char *,struct pt_regs *,long);
-
#ifdef CONFIG_KPROBES
static inline int notify_page_fault(struct pt_regs *regs, long err)
{
@@ -245,11 +243,6 @@
}
#ifdef CONFIG_S390_EXEC_PROTECT
-extern long sys_sigreturn(struct pt_regs *regs);
-extern long sys_rt_sigreturn(struct pt_regs *regs);
-extern long sys32_sigreturn(struct pt_regs *regs);
-extern long sys32_rt_sigreturn(struct pt_regs *regs);
-
static int signal_return(struct mm_struct *mm, struct pt_regs *regs,
unsigned long address, unsigned long error_code)
{
@@ -270,15 +263,15 @@
#ifdef CONFIG_COMPAT
compat = test_tsk_thread_flag(current, TIF_31BIT);
if (compat && instruction == 0x0a77)
- sys32_sigreturn(regs);
+ sys32_sigreturn();
else if (compat && instruction == 0x0aad)
- sys32_rt_sigreturn(regs);
+ sys32_rt_sigreturn();
else
#endif
if (instruction == 0x0a77)
- sys_sigreturn(regs);
+ sys_sigreturn();
else if (instruction == 0x0aad)
- sys_rt_sigreturn(regs);
+ sys_rt_sigreturn();
else {
current->thread.prot_addr = address;
current->thread.trap_no = error_code;
@@ -424,7 +417,7 @@
}
void __kprobes do_protection_exception(struct pt_regs *regs,
- unsigned long error_code)
+ long error_code)
{
/* Protection exception is supressing, decrement psw address. */
regs->psw.addr -= (error_code >> 16);
@@ -440,7 +433,7 @@
do_exception(regs, 4, 1);
}
-void __kprobes do_dat_exception(struct pt_regs *regs, unsigned long error_code)
+void __kprobes do_dat_exception(struct pt_regs *regs, long error_code)
{
do_exception(regs, error_code & 0xff, 0);
}
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 8053245..202c952 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -50,7 +50,6 @@
printk("Mem-info:\n");
show_free_areas();
- printk("Free swap: %6ldkB\n", nr_swap_pages << (PAGE_SHIFT - 10));
i = max_mapnr;
while (i-- > 0) {
if (!pfn_valid(i))
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 84cdf90..349b6ed 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -116,6 +116,10 @@
err = -EAGAIN;
if (!bytes_read && (filp->f_flags & O_NONBLOCK))
goto out;
+ if (bytes_read < 0) {
+ err = bytes_read;
+ goto out;
+ }
err = -EFAULT;
while (bytes_read && size) {
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 6b658d8..6d2f0c8 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -64,6 +64,7 @@
tristate "Support for PCI-attached cryptographic adapters"
depends on S390
select ZCRYPT_MONOLITHIC if ZCRYPT="y"
+ select HW_RANDOM
help
Select this option if you want to use a PCI-attached cryptographic
adapter like:
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
index e879b21..0788319 100644
--- a/drivers/s390/block/Kconfig
+++ b/drivers/s390/block/Kconfig
@@ -20,6 +20,7 @@
config DASD
tristate "Support for DASD devices"
depends on CCW && BLOCK
+ select IOSCHED_DEADLINE
help
Enable this option if you want to access DASDs directly utilizing
S/390s channel subsystem commands. This is necessary for running
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index ccf46c9..ac6d4d3 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -980,12 +980,12 @@
break;
case -ETIMEDOUT:
printk(KERN_WARNING"%s(%s): request timed out\n",
- __FUNCTION__, cdev->dev.bus_id);
+ __func__, cdev->dev.bus_id);
//FIXME - dasd uses own timeout interface...
break;
default:
printk(KERN_WARNING"%s(%s): unknown error %ld\n",
- __FUNCTION__, cdev->dev.bus_id, PTR_ERR(irb));
+ __func__, cdev->dev.bus_id, PTR_ERR(irb));
}
return;
}
@@ -1956,6 +1956,7 @@
block->request_queue->queuedata = block;
elevator_exit(block->request_queue->elevator);
+ block->request_queue->elevator = NULL;
rc = elevator_init(block->request_queue, "deadline");
if (rc) {
blk_cleanup_queue(block->request_queue);
@@ -2298,9 +2299,8 @@
* in the other openers.
*/
if (device->block) {
- struct dasd_block *block = device->block;
- max_count = block->bdev ? 0 : -1;
- open_count = (int) atomic_read(&block->open_count);
+ max_count = device->block->bdev ? 0 : -1;
+ open_count = atomic_read(&device->block->open_count);
if (open_count > max_count) {
if (open_count > 0)
printk(KERN_WARNING "Can't offline dasd "
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index b19db20..e6700df 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -1996,6 +1996,36 @@
} /* end dasd_3990_erp_compound */
/*
+ *DASD_3990_ERP_HANDLE_SIM
+ *
+ *DESCRIPTION
+ * inspects the SIM SENSE data and starts an appropriate action
+ *
+ * PARAMETER
+ * sense sense data of the actual error
+ *
+ * RETURN VALUES
+ * none
+ */
+void
+dasd_3990_erp_handle_sim(struct dasd_device *device, char *sense)
+{
+ /* print message according to log or message to operator mode */
+ if ((sense[24] & DASD_SIM_MSG_TO_OP) || (sense[1] & 0x10)) {
+
+ /* print SIM SRC from RefCode */
+ DEV_MESSAGE(KERN_ERR, device, "SIM - SRC: "
+ "%02x%02x%02x%02x", sense[22],
+ sense[23], sense[11], sense[12]);
+ } else if (sense[24] & DASD_SIM_LOG) {
+ /* print SIM SRC Refcode */
+ DEV_MESSAGE(KERN_WARNING, device, "SIM - SRC: "
+ "%02x%02x%02x%02x", sense[22],
+ sense[23], sense[11], sense[12]);
+ }
+}
+
+/*
* DASD_3990_ERP_INSPECT_32
*
* DESCRIPTION
@@ -2018,6 +2048,10 @@
erp->function = dasd_3990_erp_inspect_32;
+ /* check for SIM sense data */
+ if ((sense[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)
+ dasd_3990_erp_handle_sim(device, sense);
+
if (sense[25] & DASD_SENSE_BIT_0) {
/* compound program action codes (byte25 bit 0 == '1') */
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
index 3a40bee..2d8df0b 100644
--- a/drivers/s390/block/dasd_alias.c
+++ b/drivers/s390/block/dasd_alias.c
@@ -745,6 +745,19 @@
spin_unlock_irqrestore(&lcu->lock, flags);
}
+static void __stop_device_on_lcu(struct dasd_device *device,
+ struct dasd_device *pos)
+{
+ /* If pos == device then device is already locked! */
+ if (pos == device) {
+ pos->stopped |= DASD_STOPPED_SU;
+ return;
+ }
+ spin_lock(get_ccwdev_lock(pos->cdev));
+ pos->stopped |= DASD_STOPPED_SU;
+ spin_unlock(get_ccwdev_lock(pos->cdev));
+}
+
/*
* This function is called in interrupt context, so the
* cdev lock for device is already locked!
@@ -755,35 +768,15 @@
struct alias_pav_group *pavgroup;
struct dasd_device *pos;
- list_for_each_entry(pos, &lcu->active_devices, alias_list) {
- if (pos != device)
- spin_lock(get_ccwdev_lock(pos->cdev));
- pos->stopped |= DASD_STOPPED_SU;
- if (pos != device)
- spin_unlock(get_ccwdev_lock(pos->cdev));
- }
- list_for_each_entry(pos, &lcu->inactive_devices, alias_list) {
- if (pos != device)
- spin_lock(get_ccwdev_lock(pos->cdev));
- pos->stopped |= DASD_STOPPED_SU;
- if (pos != device)
- spin_unlock(get_ccwdev_lock(pos->cdev));
- }
+ list_for_each_entry(pos, &lcu->active_devices, alias_list)
+ __stop_device_on_lcu(device, pos);
+ list_for_each_entry(pos, &lcu->inactive_devices, alias_list)
+ __stop_device_on_lcu(device, pos);
list_for_each_entry(pavgroup, &lcu->grouplist, group) {
- list_for_each_entry(pos, &pavgroup->baselist, alias_list) {
- if (pos != device)
- spin_lock(get_ccwdev_lock(pos->cdev));
- pos->stopped |= DASD_STOPPED_SU;
- if (pos != device)
- spin_unlock(get_ccwdev_lock(pos->cdev));
- }
- list_for_each_entry(pos, &pavgroup->aliaslist, alias_list) {
- if (pos != device)
- spin_lock(get_ccwdev_lock(pos->cdev));
- pos->stopped |= DASD_STOPPED_SU;
- if (pos != device)
- spin_unlock(get_ccwdev_lock(pos->cdev));
- }
+ list_for_each_entry(pos, &pavgroup->baselist, alias_list)
+ __stop_device_on_lcu(device, pos);
+ list_for_each_entry(pos, &pavgroup->aliaslist, alias_list)
+ __stop_device_on_lcu(device, pos);
}
}
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 61f1693..a0edae0 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1415,6 +1415,13 @@
return;
}
+
+ /* service information message SIM */
+ if ((irb->ecw[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE) {
+ dasd_3990_erp_handle_sim(device, irb->ecw);
+ return;
+ }
+
/* just report other unsolicited interrupts */
DEV_MESSAGE(KERN_DEBUG, device, "%s",
"unsolicited interrupt received");
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index d13ea05..1166115 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -125,7 +125,8 @@
private = (struct dasd_fba_private *) device->private;
if (private == NULL) {
- private = kzalloc(sizeof(struct dasd_fba_private), GFP_KERNEL);
+ private = kzalloc(sizeof(struct dasd_fba_private),
+ GFP_KERNEL | GFP_DMA);
if (private == NULL) {
DEV_MESSAGE(KERN_WARNING, device, "%s",
"memory allocation failed for private "
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 44b2984..6c624bf 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -72,6 +72,11 @@
#define DASD_SENSE_BIT_2 0x20
#define DASD_SENSE_BIT_3 0x10
+/* BIT DEFINITIONS FOR SIM SENSE */
+#define DASD_SIM_SENSE 0x0F
+#define DASD_SIM_MSG_TO_OP 0x03
+#define DASD_SIM_LOG 0x0C
+
/*
* SECTION: MACROs for klogd and s390 debug feature (dbf)
*/
@@ -621,6 +626,7 @@
/* externals in dasd_3990_erp.c */
struct dasd_ccw_req *dasd_3990_erp_action(struct dasd_ccw_req *);
+void dasd_3990_erp_handle_sim(struct dasd_device *, char *);
/* externals in dasd_eer.c */
#ifdef CONFIG_DASD_EER
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index e6c94db..04787ea 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -142,57 +142,6 @@
return NULL;
}
-/*
- * print appropriate error message for segment_load()/segment_type()
- * return code
- */
-static void
-dcssblk_segment_warn(int rc, char* seg_name)
-{
- switch (rc) {
- case -ENOENT:
- PRINT_WARN("cannot load/query segment %s, does not exist\n",
- seg_name);
- break;
- case -ENOSYS:
- PRINT_WARN("cannot load/query segment %s, not running on VM\n",
- seg_name);
- break;
- case -EIO:
- PRINT_WARN("cannot load/query segment %s, hardware error\n",
- seg_name);
- break;
- case -ENOTSUPP:
- PRINT_WARN("cannot load/query segment %s, is a multi-part "
- "segment\n", seg_name);
- break;
- case -ENOSPC:
- PRINT_WARN("cannot load/query segment %s, overlaps with "
- "storage\n", seg_name);
- break;
- case -EBUSY:
- PRINT_WARN("cannot load/query segment %s, overlaps with "
- "already loaded dcss\n", seg_name);
- break;
- case -EPERM:
- PRINT_WARN("cannot load/query segment %s, already loaded in "
- "incompatible mode\n", seg_name);
- break;
- case -ENOMEM:
- PRINT_WARN("cannot load/query segment %s, out of memory\n",
- seg_name);
- break;
- case -ERANGE:
- PRINT_WARN("cannot load/query segment %s, exceeds kernel "
- "mapping range\n", seg_name);
- break;
- default:
- PRINT_WARN("cannot load/query segment %s, return value %i\n",
- seg_name, rc);
- break;
- }
-}
-
static void dcssblk_unregister_callback(struct device *dev)
{
device_unregister(dev);
@@ -423,7 +372,7 @@
rc = segment_load(local_buf, SEGMENT_SHARED,
&dev_info->start, &dev_info->end);
if (rc < 0) {
- dcssblk_segment_warn(rc, dev_info->segment_name);
+ segment_warning(rc, dev_info->segment_name);
goto dealloc_gendisk;
}
seg_byte_size = (dev_info->end - dev_info->start + 1);
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index 67009bf..1e1f506 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -111,56 +111,6 @@
ASCEBC(ebcdic_name, 8);
}
-/*
- * print appropriate error message for segment_load()/segment_type()
- * return code
- */
-static void mon_segment_warn(int rc, char* seg_name)
-{
- switch (rc) {
- case -ENOENT:
- P_WARNING("cannot load/query segment %s, does not exist\n",
- seg_name);
- break;
- case -ENOSYS:
- P_WARNING("cannot load/query segment %s, not running on VM\n",
- seg_name);
- break;
- case -EIO:
- P_WARNING("cannot load/query segment %s, hardware error\n",
- seg_name);
- break;
- case -ENOTSUPP:
- P_WARNING("cannot load/query segment %s, is a multi-part "
- "segment\n", seg_name);
- break;
- case -ENOSPC:
- P_WARNING("cannot load/query segment %s, overlaps with "
- "storage\n", seg_name);
- break;
- case -EBUSY:
- P_WARNING("cannot load/query segment %s, overlaps with "
- "already loaded dcss\n", seg_name);
- break;
- case -EPERM:
- P_WARNING("cannot load/query segment %s, already loaded in "
- "incompatible mode\n", seg_name);
- break;
- case -ENOMEM:
- P_WARNING("cannot load/query segment %s, out of memory\n",
- seg_name);
- break;
- case -ERANGE:
- P_WARNING("cannot load/query segment %s, exceeds kernel "
- "mapping range\n", seg_name);
- break;
- default:
- P_WARNING("cannot load/query segment %s, return value %i\n",
- seg_name, rc);
- break;
- }
-}
-
static inline unsigned long mon_mca_start(struct mon_msg *monmsg)
{
return *(u32 *) &monmsg->msg.rmmsg;
@@ -585,7 +535,7 @@
rc = segment_type(mon_dcss_name);
if (rc < 0) {
- mon_segment_warn(rc, mon_dcss_name);
+ segment_warning(rc, mon_dcss_name);
goto out_iucv;
}
if (rc != SEG_TYPE_SC) {
@@ -598,7 +548,7 @@
rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
&mon_dcss_start, &mon_dcss_end);
if (rc < 0) {
- mon_segment_warn(rc, mon_dcss_name);
+ segment_warning(rc, mon_dcss_name);
rc = -EINVAL;
goto out_iucv;
}
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index 2e616e3..e3b3d39 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -332,7 +332,7 @@
if (sclp_ttybuf == NULL) {
while (list_empty(&sclp_tty_pages)) {
spin_unlock_irqrestore(&sclp_tty_lock, flags);
- if (in_atomic())
+ if (in_interrupt())
sclp_sync_wait();
else
wait_event(sclp_tty_waitq,
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index f7b258d..ed50759 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -383,7 +383,7 @@
*/
static int
__sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
- int convertlf)
+ int convertlf, int may_schedule)
{
unsigned long flags;
void *page;
@@ -398,9 +398,8 @@
/* Create a sclp output buffer if none exists yet */
if (sclp_vt220_current_request == NULL) {
while (list_empty(&sclp_vt220_empty)) {
- spin_unlock_irqrestore(&sclp_vt220_lock,
- flags);
- if (in_atomic())
+ spin_unlock_irqrestore(&sclp_vt220_lock, flags);
+ if (in_interrupt() || !may_schedule)
sclp_sync_wait();
else
wait_event(sclp_vt220_waitq,
@@ -450,7 +449,7 @@
static int
sclp_vt220_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
- return __sclp_vt220_write(buf, count, 1, 0);
+ return __sclp_vt220_write(buf, count, 1, 0, 1);
}
#define SCLP_VT220_SESSION_ENDED 0x01
@@ -529,7 +528,7 @@
static void
sclp_vt220_put_char(struct tty_struct *tty, unsigned char ch)
{
- __sclp_vt220_write(&ch, 1, 0, 0);
+ __sclp_vt220_write(&ch, 1, 0, 0, 1);
}
/*
@@ -746,7 +745,7 @@
static void
sclp_vt220_con_write(struct console *con, const char *buf, unsigned int count)
{
- __sclp_vt220_write((const unsigned char *) buf, count, 1, 1);
+ __sclp_vt220_write((const unsigned char *) buf, count, 1, 1, 0);
}
static struct tty_driver *
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 5b47e9c..874adf3 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -394,7 +394,7 @@
return tape_34xx_erp_failed(request, -ENOSPC);
default:
PRINT_ERR("Invalid op in %s:%i\n",
- __FUNCTION__, __LINE__);
+ __func__, __LINE__);
return tape_34xx_erp_failed(request, 0);
}
}
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index b830a8c..ebe8406 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -83,9 +83,9 @@
void
tapechar_cleanup_device(struct tape_device *device)
{
- unregister_tape_dev(device->rt);
+ unregister_tape_dev(&device->cdev->dev, device->rt);
device->rt = NULL;
- unregister_tape_dev(device->nt);
+ unregister_tape_dev(&device->cdev->dev, device->nt);
device->nt = NULL;
}
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index aa7f166..6dfdb7c 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -99,11 +99,10 @@
}
EXPORT_SYMBOL(register_tape_dev);
-void unregister_tape_dev(struct tape_class_device *tcd)
+void unregister_tape_dev(struct device *device, struct tape_class_device *tcd)
{
if (tcd != NULL && !IS_ERR(tcd)) {
- sysfs_remove_link(&tcd->class_device->kobj,
- tcd->mode_name);
+ sysfs_remove_link(&device->kobj, tcd->mode_name);
device_destroy(tape_class, tcd->char_device->dev);
cdev_del(tcd->char_device);
kfree(tcd);
diff --git a/drivers/s390/char/tape_class.h b/drivers/s390/char/tape_class.h
index e2b5ac9..707b7f4 100644
--- a/drivers/s390/char/tape_class.h
+++ b/drivers/s390/char/tape_class.h
@@ -56,6 +56,6 @@
char * device_name,
char * node_name
);
-void unregister_tape_dev(struct tape_class_device *tcd);
+void unregister_tape_dev(struct device *device, struct tape_class_device *tcd);
#endif /* __TAPE_CLASS_H__ */
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index 7689b50..83ae9a8 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -100,7 +100,8 @@
urd->reclen = cdev->id.driver_info;
ccw_device_get_id(cdev, &urd->dev_id);
mutex_init(&urd->io_mutex);
- mutex_init(&urd->open_mutex);
+ init_waitqueue_head(&urd->wait);
+ spin_lock_init(&urd->open_lock);
atomic_set(&urd->ref_count, 1);
urd->cdev = cdev;
get_device(&cdev->dev);
@@ -678,17 +679,21 @@
if (!urd)
return -ENXIO;
- if (file->f_flags & O_NONBLOCK) {
- if (!mutex_trylock(&urd->open_mutex)) {
+ spin_lock(&urd->open_lock);
+ while (urd->open_flag) {
+ spin_unlock(&urd->open_lock);
+ if (file->f_flags & O_NONBLOCK) {
rc = -EBUSY;
goto fail_put;
}
- } else {
- if (mutex_lock_interruptible(&urd->open_mutex)) {
+ if (wait_event_interruptible(urd->wait, urd->open_flag == 0)) {
rc = -ERESTARTSYS;
goto fail_put;
}
+ spin_lock(&urd->open_lock);
}
+ urd->open_flag++;
+ spin_unlock(&urd->open_lock);
TRACE("ur_open\n");
@@ -720,7 +725,9 @@
fail_urfile_free:
urfile_free(urf);
fail_unlock:
- mutex_unlock(&urd->open_mutex);
+ spin_lock(&urd->open_lock);
+ urd->open_flag--;
+ spin_unlock(&urd->open_lock);
fail_put:
urdev_put(urd);
return rc;
@@ -731,7 +738,10 @@
struct urfile *urf = file->private_data;
TRACE("ur_release\n");
- mutex_unlock(&urf->urd->open_mutex);
+ spin_lock(&urf->urd->open_lock);
+ urf->urd->open_flag--;
+ spin_unlock(&urf->urd->open_lock);
+ wake_up_interruptible(&urf->urd->wait);
urdev_put(urf->urd);
urfile_free(urf);
return 0;
diff --git a/drivers/s390/char/vmur.h b/drivers/s390/char/vmur.h
index fa95964..fa320ad 100644
--- a/drivers/s390/char/vmur.h
+++ b/drivers/s390/char/vmur.h
@@ -62,7 +62,6 @@
struct urdev {
struct ccw_device *cdev; /* Backpointer to ccw device */
struct mutex io_mutex; /* Serialises device IO */
- struct mutex open_mutex; /* Serialises access to device */
struct completion *io_done; /* do_ur_io waits; irq completes */
struct device *device;
struct cdev *char_device;
@@ -71,6 +70,9 @@
int class; /* VM device class */
int io_request_rc; /* return code from I/O request */
atomic_t ref_count; /* reference counter */
+ wait_queue_head_t wait; /* wait queue to serialize open */
+ int open_flag; /* "urdev is open" flag */
+ spinlock_t open_lock; /* serialize critical sections */
};
/*
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index 6f40fac..19f8389 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -96,7 +96,7 @@
if (ret) {
printk(KERN_WARNING "%s: problem setting interval %d, "
- "cmd %s\n", __FUNCTION__, vmwdt_interval,
+ "cmd %s\n", __func__, vmwdt_interval,
vmwdt_cmd);
}
return ret;
@@ -107,7 +107,7 @@
int ret = __diag288(wdt_cancel, 0, "", 0);
if (ret) {
printk(KERN_WARNING "%s: problem disabling watchdog\n",
- __FUNCTION__);
+ __func__);
}
return ret;
}
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index f523501..bbbd14e 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -224,7 +224,7 @@
sa = kmalloc(sizeof(*sa), GFP_KERNEL);
if (!sa) {
- ERROR_MSG("kmalloc failed: %s: %i\n",__FUNCTION__, __LINE__);
+ ERROR_MSG("kmalloc failed: %s: %i\n",__func__, __LINE__);
return -ENOMEM;
}
if (memcpy_hsa_kernel(sa, sys_info.sa_base, sys_info.sa_size) < 0) {
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 007aaeb..5de8690 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -217,6 +217,8 @@
if (chp_get_status(chpid) <= 0)
return;
+ /* Wait until previous actions have settled. */
+ css_wait_for_slow_path();
for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &chpid);
}
@@ -303,7 +305,8 @@
sprintf(dbf_txt, "fla%x", res_data->fla);
CIO_TRACE_EVENT( 2, dbf_txt);
}
-
+ /* Wait until previous actions have settled. */
+ css_wait_for_slow_path();
/*
* I/O resources may have become accessible.
* Scan through all subchannels that may be concerned and
@@ -561,9 +564,12 @@
sprintf(dbf_txt, "cadd%x.%02x", chpid.cssid, chpid.id);
CIO_TRACE_EVENT(2, dbf_txt);
- if (chp_get_status(chpid) != 0)
+ if (chp_get_status(chpid) != 0) {
+ /* Wait until previous actions have settled. */
+ css_wait_for_slow_path();
for_each_subchannel_staged(__chp_add, __chp_add_new_sch,
&chpid);
+ }
}
static void __s390_subchannel_vary_chpid(struct subchannel *sch,
@@ -650,6 +656,8 @@
*/
int chsc_chp_vary(struct chp_id chpid, int on)
{
+ /* Wait until previous actions have settled. */
+ css_wait_for_slow_path();
/*
* Redo PathVerification on the devices the chpid connects to
*/
@@ -758,7 +766,6 @@
if (!secm_area)
return -ENOMEM;
- mutex_lock(&css->mutex);
if (enable && !css->cm_enabled) {
css->cub_addr1 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
css->cub_addr2 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
@@ -766,7 +773,6 @@
free_page((unsigned long)css->cub_addr1);
free_page((unsigned long)css->cub_addr2);
free_page((unsigned long)secm_area);
- mutex_unlock(&css->mutex);
return -ENOMEM;
}
}
@@ -787,7 +793,6 @@
free_page((unsigned long)css->cub_addr1);
free_page((unsigned long)css->cub_addr2);
}
- mutex_unlock(&css->mutex);
free_page((unsigned long)secm_area);
return ret;
}
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 60590a1..23ffcc4 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -24,6 +24,7 @@
#include <asm/ipl.h>
#include <asm/chpid.h>
#include <asm/airq.h>
+#include <asm/cpu.h>
#include "cio.h"
#include "css.h"
#include "chsc.h"
@@ -649,13 +650,10 @@
old_regs = set_irq_regs(regs);
irq_enter();
- asm volatile ("mc 0,0");
- if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer)
- /**
- * Make sure that the i/o interrupt did not "overtake"
- * the last HZ timer interrupt.
- */
- account_ticks(S390_lowcore.int_clock);
+ s390_idle_check();
+ if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
+ /* Serve timer interrupts first. */
+ clock_comparator_work();
/*
* Get interrupt information from lowcore
*/
@@ -672,10 +670,14 @@
continue;
}
sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
- if (sch)
- spin_lock(sch->lock);
+ if (!sch) {
+ /* Clear pending interrupt condition. */
+ tsch(tpi_info->schid, irb);
+ continue;
+ }
+ spin_lock(sch->lock);
/* Store interrupt response block to lowcore. */
- if (tsch (tpi_info->schid, irb) == 0 && sch) {
+ if (tsch(tpi_info->schid, irb) == 0) {
/* Keep subchannel information word up to date. */
memcpy (&sch->schib.scsw, &irb->scsw,
sizeof (irb->scsw));
@@ -683,8 +685,7 @@
if (sch->driver && sch->driver->irq)
sch->driver->irq(sch);
}
- if (sch)
- spin_unlock(sch->lock);
+ spin_unlock(sch->lock);
/*
* Are more interrupts pending?
* If so, the tpi instruction will update the lowcore
@@ -710,8 +711,9 @@
/*
* busy wait for the next interrupt on the console
*/
-void
-wait_cons_dev (void)
+void wait_cons_dev(void)
+ __releases(console_subchannel.lock)
+ __acquires(console_subchannel.lock)
{
unsigned long cr6 __attribute__ ((aligned (8)));
unsigned long save_cr6 __attribute__ ((aligned (8)));
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index 52afa4c..08f2235 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -100,6 +100,7 @@
int cio_create_sch_lock(struct subchannel *);
void do_adapter_IO(void);
+void do_IRQ(struct pt_regs *);
/* Use with care. */
#ifdef CONFIG_CCW_CONSOLE
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 3b45bbe..c1afab5 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -533,6 +533,12 @@
spin_unlock_irqrestore(&slow_subchannel_lock, flags);
}
+void css_wait_for_slow_path(void)
+{
+ flush_workqueue(ccw_device_notify_work);
+ flush_workqueue(slow_path_wq);
+}
+
/* Reprobe subchannel if unregistered. */
static int reprobe_subchannel(struct subchannel_id schid, void *data)
{
@@ -683,10 +689,14 @@
char *buf)
{
struct channel_subsystem *css = to_css(dev);
+ int ret;
if (!css)
return 0;
- return sprintf(buf, "%x\n", css->cm_enabled);
+ mutex_lock(&css->mutex);
+ ret = sprintf(buf, "%x\n", css->cm_enabled);
+ mutex_unlock(&css->mutex);
+ return ret;
}
static ssize_t
@@ -696,6 +706,7 @@
struct channel_subsystem *css = to_css(dev);
int ret;
+ mutex_lock(&css->mutex);
switch (buf[0]) {
case '0':
ret = css->cm_enabled ? chsc_secm(css, 0) : 0;
@@ -706,6 +717,7 @@
default:
ret = -EINVAL;
}
+ mutex_unlock(&css->mutex);
return ret < 0 ? ret : count;
}
@@ -752,9 +764,11 @@
struct channel_subsystem *css;
css = channel_subsystems[i];
+ mutex_lock(&css->mutex);
if (css->cm_enabled)
if (chsc_secm(css, 0))
ret = NOTIFY_BAD;
+ mutex_unlock(&css->mutex);
}
return ret;
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index b705545..e191351 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -144,6 +144,7 @@
int css_sch_is_valid(struct schib *);
extern struct workqueue_struct *slow_path_wq;
+void css_wait_for_slow_path(void);
extern struct attribute_group *subch_attr_groups[];
#endif
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index fec004f..e0c7adb 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -577,7 +577,6 @@
static DEVICE_ATTR(cutype, 0444, cutype_show, NULL);
static DEVICE_ATTR(modalias, 0444, modalias_show, NULL);
static DEVICE_ATTR(online, 0644, online_show, online_store);
-extern struct device_attribute dev_attr_cmb_enable;
static DEVICE_ATTR(availability, 0444, available_show, NULL);
static struct attribute * subch_attrs[] = {
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index d40a2ff..cb08092 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -127,4 +127,5 @@
void retry_set_schib(struct ccw_device *cdev);
void cmf_retry_copy_block(struct ccw_device *);
int cmf_reenable(struct ccw_device *);
+extern struct device_attribute dev_attr_cmb_enable;
#endif
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 49b58eb..a1718a0 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -193,8 +193,15 @@
return -EACCES;
}
ret = cio_start_key (sch, cpa, lpm, key);
- if (ret == 0)
+ switch (ret) {
+ case 0:
cdev->private->intparm = intparm;
+ break;
+ case -EACCES:
+ case -ENODEV:
+ dev_fsm_event(cdev, DEV_EVENT_VERIFY);
+ break;
+ }
return ret;
}
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index ebe0848..4a38993 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -62,7 +62,7 @@
stsch (sch->schid, &sch->schib);
CIO_MSG_EVENT(0, "%s(0.%x.%04x) - path(s) %02x are "
- "not operational \n", __FUNCTION__,
+ "not operational \n", __func__,
sch->schid.ssid, sch->schid.sch_no,
sch->schib.pmcw.pnom);
@@ -312,6 +312,7 @@
{
struct subchannel *sch;
struct ccw1 *sense_ccw;
+ int rc;
sch = to_subchannel(cdev->dev.parent);
@@ -337,7 +338,10 @@
/* Reset internal retry indication. */
cdev->private->flags.intretry = 0;
- return cio_start(sch, sense_ccw, 0xff);
+ rc = cio_start(sch, sense_ccw, 0xff);
+ if (rc == -ENODEV || rc == -EACCES)
+ dev_fsm_event(cdev, DEV_EVENT_VERIFY);
+ return rc;
}
/*
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 2b5bfb7..c359386 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -1399,7 +1399,7 @@
* q->dev_st_chg_ind is the indicator, be it shared or not.
* only clear it, if indicator is non-shared
*/
- if (!spare_ind_was_set)
+ if (q->dev_st_chg_ind != &spare_indicator)
tiqdio_clear_summary_bit((__u32*)q->dev_st_chg_ind);
if (q->hydra_gives_outbound_pcis) {
@@ -2217,9 +2217,78 @@
return cc;
}
+static int
+qdio_get_ssqd_information(struct subchannel_id *schid,
+ struct qdio_chsc_ssqd **ssqd_area)
+{
+ int result;
+
+ QDIO_DBF_TEXT0(0, setup, "getssqd");
+ *ssqd_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
+ if (!ssqd_area) {
+ QDIO_PRINT_WARN("Could not get memory for chsc on sch x%x.\n",
+ schid->sch_no);
+ return -ENOMEM;
+ }
+
+ (*ssqd_area)->request = (struct chsc_header) {
+ .length = 0x0010,
+ .code = 0x0024,
+ };
+ (*ssqd_area)->first_sch = schid->sch_no;
+ (*ssqd_area)->last_sch = schid->sch_no;
+ (*ssqd_area)->ssid = schid->ssid;
+ result = chsc(*ssqd_area);
+
+ if (result) {
+ QDIO_PRINT_WARN("CHSC returned cc %i on sch 0.%x.%x.\n",
+ result, schid->ssid, schid->sch_no);
+ goto out;
+ }
+
+ if ((*ssqd_area)->response.code != QDIO_CHSC_RESPONSE_CODE_OK) {
+ QDIO_PRINT_WARN("CHSC response is 0x%x on sch 0.%x.%x.\n",
+ (*ssqd_area)->response.code,
+ schid->ssid, schid->sch_no);
+ goto out;
+ }
+ if (!((*ssqd_area)->flags & CHSC_FLAG_QDIO_CAPABILITY) ||
+ !((*ssqd_area)->flags & CHSC_FLAG_VALIDITY) ||
+ ((*ssqd_area)->sch != schid->sch_no)) {
+ QDIO_PRINT_WARN("huh? problems checking out sch 0.%x.%x... " \
+ "using all SIGAs.\n",
+ schid->ssid, schid->sch_no);
+ goto out;
+ }
+ return 0;
+out:
+ return -EINVAL;
+}
+
+int
+qdio_get_ssqd_pct(struct ccw_device *cdev)
+{
+ struct qdio_chsc_ssqd *ssqd_area;
+ struct subchannel_id schid;
+ char dbf_text[15];
+ int rc;
+ int pct = 0;
+
+ QDIO_DBF_TEXT0(0, setup, "getpct");
+ schid = ccw_device_get_subchannel_id(cdev);
+ rc = qdio_get_ssqd_information(&schid, &ssqd_area);
+ if (!rc)
+ pct = (int)ssqd_area->pct;
+ if (rc != -ENOMEM)
+ mempool_free(ssqd_area, qdio_mempool_scssc);
+ sprintf(dbf_text, "pct: %d", pct);
+ QDIO_DBF_TEXT2(0, setup, dbf_text);
+ return pct;
+}
+EXPORT_SYMBOL(qdio_get_ssqd_pct);
+
static void
-qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac,
- unsigned long token)
+qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned long token)
{
struct qdio_q *q;
int i;
@@ -2227,7 +2296,7 @@
char dbf_text[15];
/*check if QEBSM is disabled */
- if (!(irq_ptr->is_qebsm) || !(qdioac & 0x01)) {
+ if (!(irq_ptr->is_qebsm) || !(irq_ptr->qdioac & 0x01)) {
irq_ptr->is_qebsm = 0;
irq_ptr->sch_token = 0;
irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM;
@@ -2256,102 +2325,27 @@
}
static void
-qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
+qdio_get_ssqd_siga(struct qdio_irq *irq_ptr)
{
- int result;
- unsigned char qdioac;
- struct {
- struct chsc_header request;
- u16 reserved1:10;
- u16 ssid:2;
- u16 fmt:4;
- u16 first_sch;
- u16 reserved2;
- u16 last_sch;
- u32 reserved3;
- struct chsc_header response;
- u32 reserved4;
- u8 flags;
- u8 reserved5;
- u16 sch;
- u8 qfmt;
- u8 parm;
- u8 qdioac1;
- u8 sch_class;
- u8 reserved7;
- u8 icnt;
- u8 reserved8;
- u8 ocnt;
- u8 reserved9;
- u8 mbccnt;
- u16 qdioac2;
- u64 sch_token;
- } *ssqd_area;
+ int rc;
+ struct qdio_chsc_ssqd *ssqd_area;
QDIO_DBF_TEXT0(0,setup,"getssqd");
- qdioac = 0;
- ssqd_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
- if (!ssqd_area) {
- QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \
- "SIGAs for sch x%x.\n", irq_ptr->schid.sch_no);
+ irq_ptr->qdioac = 0;
+ rc = qdio_get_ssqd_information(&irq_ptr->schid, &ssqd_area);
+ if (rc) {
+ QDIO_PRINT_WARN("using all SIGAs for sch x%x.n",
+ irq_ptr->schid.sch_no);
irq_ptr->qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
irq_ptr->is_qebsm = 0;
- irq_ptr->sch_token = 0;
- irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM;
- return;
- }
+ } else
+ irq_ptr->qdioac = ssqd_area->qdioac1;
- ssqd_area->request = (struct chsc_header) {
- .length = 0x0010,
- .code = 0x0024,
- };
- ssqd_area->first_sch = irq_ptr->schid.sch_no;
- ssqd_area->last_sch = irq_ptr->schid.sch_no;
- ssqd_area->ssid = irq_ptr->schid.ssid;
- result = chsc(ssqd_area);
-
- if (result) {
- QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \
- "SIGAs for sch 0.%x.%x.\n", result,
- irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
- qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
- CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
- CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
- irq_ptr->is_qebsm = 0;
- goto out;
- }
-
- if (ssqd_area->response.code != QDIO_CHSC_RESPONSE_CODE_OK) {
- QDIO_PRINT_WARN("response upon checking SIGA needs " \
- "is 0x%x. Using all SIGAs for sch 0.%x.%x.\n",
- ssqd_area->response.code,
- irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
- qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
- CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
- CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
- irq_ptr->is_qebsm = 0;
- goto out;
- }
- if (!(ssqd_area->flags & CHSC_FLAG_QDIO_CAPABILITY) ||
- !(ssqd_area->flags & CHSC_FLAG_VALIDITY) ||
- (ssqd_area->sch != irq_ptr->schid.sch_no)) {
- QDIO_PRINT_WARN("huh? problems checking out sch 0.%x.%x... " \
- "using all SIGAs.\n",
- irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
- qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
- CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
- CHSC_FLAG_SIGA_SYNC_NECESSARY; /* worst case */
- irq_ptr->is_qebsm = 0;
- goto out;
- }
- qdioac = ssqd_area->qdioac1;
-out:
- qdio_check_subchannel_qebsm(irq_ptr, qdioac,
- ssqd_area->sch_token);
- mempool_free(ssqd_area, qdio_mempool_scssc);
- irq_ptr->qdioac = qdioac;
+ qdio_check_subchannel_qebsm(irq_ptr, ssqd_area->sch_token);
+ if (rc != -ENOMEM)
+ mempool_free(ssqd_area, qdio_mempool_scssc);
}
static unsigned int
@@ -3227,7 +3221,7 @@
return -EIO;
}
- qdio_get_ssqd_information(irq_ptr);
+ qdio_get_ssqd_siga(irq_ptr);
/* if this gets set once, we're running under VM and can omit SVSes */
if (irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY)
omit_svs=1;
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index da8a272..c3df6b2 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -406,6 +406,34 @@
#define CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS 0x08
#define CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS 0x04
+struct qdio_chsc_ssqd {
+ struct chsc_header request;
+ u16 reserved1:10;
+ u16 ssid:2;
+ u16 fmt:4;
+ u16 first_sch;
+ u16 reserved2;
+ u16 last_sch;
+ u32 reserved3;
+ struct chsc_header response;
+ u32 reserved4;
+ u8 flags;
+ u8 reserved5;
+ u16 sch;
+ u8 qfmt;
+ u8 parm;
+ u8 qdioac1;
+ u8 sch_class;
+ u8 pct;
+ u8 icnt;
+ u8 reserved7;
+ u8 ocnt;
+ u8 reserved8;
+ u8 mbccnt;
+ u16 qdioac2;
+ u64 sch_token;
+};
+
struct qdio_perf_stats {
#ifdef CONFIG_64BIT
atomic64_t tl_runs;
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 7b0b819..a1ab3e3 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -45,7 +45,7 @@
static void ap_poll_thread_stop(void);
static void ap_request_timeout(unsigned long);
-/**
+/*
* Module description.
*/
MODULE_AUTHOR("IBM Corporation");
@@ -53,7 +53,7 @@
"Copyright 2006 IBM Corporation");
MODULE_LICENSE("GPL");
-/**
+/*
* Module parameter
*/
int ap_domain_index = -1; /* Adjunct Processor Domain Index */
@@ -69,7 +69,7 @@
static DEFINE_SPINLOCK(ap_device_lock);
static LIST_HEAD(ap_device_list);
-/**
+/*
* Workqueue & timer for bus rescan.
*/
static struct workqueue_struct *ap_work_queue;
@@ -77,7 +77,7 @@
static int ap_config_time = AP_CONFIG_TIME;
static DECLARE_WORK(ap_config_work, ap_scan_bus);
-/**
+/*
* Tasklet & timer for AP request polling.
*/
static struct timer_list ap_poll_timer = TIMER_INITIALIZER(ap_poll_timeout,0,0);
@@ -88,9 +88,9 @@
static DEFINE_MUTEX(ap_poll_thread_mutex);
/**
- * Test if ap instructions are available.
+ * ap_intructions_available() - Test if AP instructions are available.
*
- * Returns 0 if the ap instructions are installed.
+ * Returns 0 if the AP instructions are installed.
*/
static inline int ap_instructions_available(void)
{
@@ -108,12 +108,12 @@
}
/**
- * Test adjunct processor queue.
- * @qid: the ap queue number
- * @queue_depth: pointer to queue depth value
- * @device_type: pointer to device type value
+ * ap_test_queue(): Test adjunct processor queue.
+ * @qid: The AP queue number
+ * @queue_depth: Pointer to queue depth value
+ * @device_type: Pointer to device type value
*
- * Returns ap queue status structure.
+ * Returns AP queue status structure.
*/
static inline struct ap_queue_status
ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
@@ -130,10 +130,10 @@
}
/**
- * Reset adjunct processor queue.
- * @qid: the ap queue number
+ * ap_reset_queue(): Reset adjunct processor queue.
+ * @qid: The AP queue number
*
- * Returns ap queue status structure.
+ * Returns AP queue status structure.
*/
static inline struct ap_queue_status ap_reset_queue(ap_qid_t qid)
{
@@ -148,16 +148,14 @@
}
/**
- * Send message to adjunct processor queue.
- * @qid: the ap queue number
- * @psmid: the program supplied message identifier
- * @msg: the message text
- * @length: the message length
+ * __ap_send(): Send message to adjunct processor queue.
+ * @qid: The AP queue number
+ * @psmid: The program supplied message identifier
+ * @msg: The message text
+ * @length: The message length
*
- * Returns ap queue status structure.
- *
+ * Returns AP queue status structure.
* Condition code 1 on NQAP can't happen because the L bit is 1.
- *
* Condition code 2 on NQAP also means the send is incomplete,
* because a segment boundary was reached. The NQAP is repeated.
*/
@@ -198,23 +196,20 @@
}
EXPORT_SYMBOL(ap_send);
-/*
- * Receive message from adjunct processor queue.
- * @qid: the ap queue number
- * @psmid: pointer to program supplied message identifier
- * @msg: the message text
- * @length: the message length
+/**
+ * __ap_recv(): Receive message from adjunct processor queue.
+ * @qid: The AP queue number
+ * @psmid: Pointer to program supplied message identifier
+ * @msg: The message text
+ * @length: The message length
*
- * Returns ap queue status structure.
- *
+ * Returns AP queue status structure.
* Condition code 1 on DQAP means the receive has taken place
* but only partially. The response is incomplete, hence the
* DQAP is repeated.
- *
* Condition code 2 on DQAP also means the receive is incomplete,
* this time because a segment boundary was reached. Again, the
* DQAP is repeated.
- *
* Note that gpr2 is used by the DQAP instruction to keep track of
* any 'residual' length, in case the instruction gets interrupted.
* Hence it gets zeroed before the instruction.
@@ -263,11 +258,12 @@
EXPORT_SYMBOL(ap_recv);
/**
- * Check if an AP queue is available. The test is repeated for
- * AP_MAX_RESET times.
- * @qid: the ap queue number
- * @queue_depth: pointer to queue depth value
- * @device_type: pointer to device type value
+ * ap_query_queue(): Check if an AP queue is available.
+ * @qid: The AP queue number
+ * @queue_depth: Pointer to queue depth value
+ * @device_type: Pointer to device type value
+ *
+ * The test is repeated for AP_MAX_RESET times.
*/
static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
{
@@ -308,8 +304,10 @@
}
/**
+ * ap_init_queue(): Reset an AP queue.
+ * @qid: The AP queue number
+ *
* Reset an AP queue and wait for it to become available again.
- * @qid: the ap queue number
*/
static int ap_init_queue(ap_qid_t qid)
{
@@ -346,7 +344,10 @@
}
/**
- * Arm request timeout if a AP device was idle and a new request is submitted.
+ * ap_increase_queue_count(): Arm request timeout.
+ * @ap_dev: Pointer to an AP device.
+ *
+ * Arm request timeout if an AP device was idle and a new request is submitted.
*/
static void ap_increase_queue_count(struct ap_device *ap_dev)
{
@@ -360,7 +361,10 @@
}
/**
- * AP device is still alive, re-schedule request timeout if there are still
+ * ap_decrease_queue_count(): Decrease queue count.
+ * @ap_dev: Pointer to an AP device.
+ *
+ * If AP device is still alive, re-schedule request timeout if there are still
* pending requests.
*/
static void ap_decrease_queue_count(struct ap_device *ap_dev)
@@ -371,7 +375,7 @@
if (ap_dev->queue_count > 0)
mod_timer(&ap_dev->timeout, jiffies + timeout);
else
- /**
+ /*
* The timeout timer should to be disabled now - since
* del_timer_sync() is very expensive, we just tell via the
* reset flag to ignore the pending timeout timer.
@@ -379,7 +383,7 @@
ap_dev->reset = AP_RESET_IGNORE;
}
-/**
+/*
* AP device related attributes.
*/
static ssize_t ap_hwtype_show(struct device *dev,
@@ -433,6 +437,10 @@
};
/**
+ * ap_bus_match()
+ * @dev: Pointer to device
+ * @drv: Pointer to device_driver
+ *
* AP bus driver registration/unregistration.
*/
static int ap_bus_match(struct device *dev, struct device_driver *drv)
@@ -441,7 +449,7 @@
struct ap_driver *ap_drv = to_ap_drv(drv);
struct ap_device_id *id;
- /**
+ /*
* Compare device type of the device with the list of
* supported types of the device_driver.
*/
@@ -455,8 +463,12 @@
}
/**
- * uevent function for AP devices. It sets up a single environment
- * variable DEV_TYPE which contains the hardware device type.
+ * ap_uevent(): Uevent function for AP devices.
+ * @dev: Pointer to device
+ * @env: Pointer to kobj_uevent_env
+ *
+ * It sets up a single environment variable DEV_TYPE which contains the
+ * hardware device type.
*/
static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
{
@@ -500,8 +512,10 @@
}
/**
+ * __ap_flush_queue(): Flush requests.
+ * @ap_dev: Pointer to the AP device
+ *
* Flush all requests from the request/pending queue of an AP device.
- * @ap_dev: pointer to the AP device.
*/
static void __ap_flush_queue(struct ap_device *ap_dev)
{
@@ -565,7 +579,7 @@
}
EXPORT_SYMBOL(ap_driver_unregister);
-/**
+/*
* AP bus attributes.
*/
static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
@@ -630,14 +644,16 @@
};
/**
- * Pick one of the 16 ap domains.
+ * ap_select_domain(): Select an AP domain.
+ *
+ * Pick one of the 16 AP domains.
*/
static int ap_select_domain(void)
{
int queue_depth, device_type, count, max_count, best_domain;
int rc, i, j;
- /**
+ /*
* We want to use a single domain. Either the one specified with
* the "domain=" parameter or the domain with the maximum number
* of devices.
@@ -669,8 +685,10 @@
}
/**
- * Find the device type if query queue returned a device type of 0.
+ * ap_probe_device_type(): Find the device type of an AP.
* @ap_dev: pointer to the AP device.
+ *
+ * Find the device type if query queue returned a device type of 0.
*/
static int ap_probe_device_type(struct ap_device *ap_dev)
{
@@ -764,7 +782,11 @@
}
/**
- * Scan the ap bus for new devices.
+ * __ap_scan_bus(): Scan the AP bus.
+ * @dev: Pointer to device
+ * @data: Pointer to data
+ *
+ * Scan the AP bus for new devices.
*/
static int __ap_scan_bus(struct device *dev, void *data)
{
@@ -867,6 +889,8 @@
}
/**
+ * ap_schedule_poll_timer(): Schedule poll timer.
+ *
* Set up the timer to run the poll tasklet
*/
static inline void ap_schedule_poll_timer(void)
@@ -877,10 +901,11 @@
}
/**
- * Receive pending reply messages from an AP device.
+ * ap_poll_read(): Receive pending reply messages from an AP device.
* @ap_dev: pointer to the AP device
* @flags: pointer to control flags, bit 2^0 is set if another poll is
* required, bit 2^1 is set if the poll timer needs to get armed
+ *
* Returns 0 if the device is still present, -ENODEV if not.
*/
static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
@@ -925,10 +950,11 @@
}
/**
- * Send messages from the request queue to an AP device.
+ * ap_poll_write(): Send messages from the request queue to an AP device.
* @ap_dev: pointer to the AP device
* @flags: pointer to control flags, bit 2^0 is set if another poll is
* required, bit 2^1 is set if the poll timer needs to get armed
+ *
* Returns 0 if the device is still present, -ENODEV if not.
*/
static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
@@ -968,11 +994,13 @@
}
/**
- * Poll AP device for pending replies and send new messages. If either
- * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
+ * ap_poll_queue(): Poll AP device for pending replies and send new messages.
* @ap_dev: pointer to the bus device
* @flags: pointer to control flags, bit 2^0 is set if another poll is
* required, bit 2^1 is set if the poll timer needs to get armed
+ *
+ * Poll AP device for pending replies and send new messages. If either
+ * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
* Returns 0.
*/
static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
@@ -986,9 +1014,11 @@
}
/**
- * Queue a message to a device.
+ * __ap_queue_message(): Queue a message to a device.
* @ap_dev: pointer to the AP device
* @ap_msg: the message to be queued
+ *
+ * Queue a message to a device. Returns 0 if successful.
*/
static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
{
@@ -1055,12 +1085,14 @@
EXPORT_SYMBOL(ap_queue_message);
/**
+ * ap_cancel_message(): Cancel a crypto request.
+ * @ap_dev: The AP device that has the message queued
+ * @ap_msg: The message that is to be removed
+ *
* Cancel a crypto request. This is done by removing the request
- * from the devive pendingq or requestq queue. Note that the
+ * from the device pending or request queue. Note that the
* request stays on the AP queue. When it finishes the message
* reply will be discarded because the psmid can't be found.
- * @ap_dev: AP device that has the message queued
- * @ap_msg: the message that is to be removed
*/
void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
{
@@ -1082,7 +1114,10 @@
EXPORT_SYMBOL(ap_cancel_message);
/**
- * AP receive polling for finished AP requests
+ * ap_poll_timeout(): AP receive polling for finished AP requests.
+ * @unused: Unused variable.
+ *
+ * Schedules the AP tasklet.
*/
static void ap_poll_timeout(unsigned long unused)
{
@@ -1090,6 +1125,9 @@
}
/**
+ * ap_reset(): Reset a not responding AP device.
+ * @ap_dev: Pointer to the AP device
+ *
* Reset a not responding AP device and move all requests from the
* pending queue to the request queue.
*/
@@ -1108,11 +1146,6 @@
ap_dev->unregistered = 1;
}
-/**
- * Poll all AP devices on the bus in a round robin fashion. Continue
- * polling until bit 2^0 of the control flags is not set. If bit 2^1
- * of the control flags has been set arm the poll timer.
- */
static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags)
{
spin_lock(&ap_dev->lock);
@@ -1126,6 +1159,14 @@
return 0;
}
+/**
+ * ap_poll_all(): Poll all AP devices.
+ * @dummy: Unused variable
+ *
+ * Poll all AP devices on the bus in a round robin fashion. Continue
+ * polling until bit 2^0 of the control flags is not set. If bit 2^1
+ * of the control flags has been set arm the poll timer.
+ */
static void ap_poll_all(unsigned long dummy)
{
unsigned long flags;
@@ -1144,6 +1185,9 @@
}
/**
+ * ap_poll_thread(): Thread that polls for finished requests.
+ * @data: Unused pointer
+ *
* AP bus poll thread. The purpose of this thread is to poll for
* finished requests in a loop if there is a "free" cpu - that is
* a cpu that doesn't have anything better to do. The polling stops
@@ -1213,7 +1257,10 @@
}
/**
- * Handling of request timeouts
+ * ap_request_timeout(): Handling of request timeouts
+ * @data: Holds the AP device.
+ *
+ * Handles request timeouts.
*/
static void ap_request_timeout(unsigned long data)
{
@@ -1246,7 +1293,9 @@
};
/**
- * The module initialization code.
+ * ap_module_init(): The module initialization code.
+ *
+ * Initializes the module.
*/
int __init ap_module_init(void)
{
@@ -1288,7 +1337,7 @@
if (ap_select_domain() == 0)
ap_scan_bus(NULL);
- /* Setup the ap bus rescan timer. */
+ /* Setup the AP bus rescan timer. */
init_timer(&ap_config_timer);
ap_config_timer.function = ap_config_timeout;
ap_config_timer.data = 0;
@@ -1325,7 +1374,9 @@
}
/**
- * The module termination code
+ * ap_modules_exit(): The module termination code
+ *
+ * Terminates the module.
*/
void ap_module_exit(void)
{
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 87c2d64..c1e1200 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -50,6 +50,15 @@
#define AP_QID_QUEUE(_qid) ((_qid) & 15)
/**
+ * structy ap_queue_status - Holds the AP queue status.
+ * @queue_empty: Shows if queue is empty
+ * @replies_waiting: Waiting replies
+ * @queue_full: Is 1 if the queue is full
+ * @pad: A 4 bit pad
+ * @int_enabled: Shows if interrupts are enabled for the AP
+ * @response_conde: Holds the 8 bit response code
+ * @pad2: A 16 bit pad
+ *
* The ap queue status word is returned by all three AP functions
* (PQAP, NQAP and DQAP). There's a set of flags in the first
* byte, followed by a 1 byte response code.
@@ -75,7 +84,7 @@
#define AP_RESPONSE_NO_FIRST_PART 0x13
#define AP_RESPONSE_MESSAGE_TOO_BIG 0x15
-/**
+/*
* Known device types
*/
#define AP_DEVICE_TYPE_PCICC 3
@@ -84,7 +93,7 @@
#define AP_DEVICE_TYPE_CEX2A 6
#define AP_DEVICE_TYPE_CEX2C 7
-/**
+/*
* AP reset flag states
*/
#define AP_RESET_IGNORE 0 /* request timeout will be ignored */
@@ -152,7 +161,7 @@
.dev_type=(dt), \
.match_flags=AP_DEVICE_ID_MATCH_DEVICE_TYPE,
-/**
+/*
* Note: don't use ap_send/ap_recv after using ap_queue_message
* for the first time. Otherwise the ap message queue will get
* confused.
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index e3625a4..4d36e80 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -36,10 +36,11 @@
#include <linux/compat.h>
#include <asm/atomic.h>
#include <asm/uaccess.h>
+#include <linux/hw_random.h>
#include "zcrypt_api.h"
-/**
+/*
* Module description.
*/
MODULE_AUTHOR("IBM Corporation");
@@ -52,7 +53,10 @@
static int zcrypt_device_count = 0;
static atomic_t zcrypt_open_count = ATOMIC_INIT(0);
-/**
+static int zcrypt_rng_device_add(void);
+static void zcrypt_rng_device_remove(void);
+
+/*
* Device attributes common for all crypto devices.
*/
static ssize_t zcrypt_type_show(struct device *dev,
@@ -99,6 +103,9 @@
};
/**
+ * __zcrypt_increase_preference(): Increase preference of a crypto device.
+ * @zdev: Pointer the crypto device
+ *
* Move the device towards the head of the device list.
* Need to be called while holding the zcrypt device list lock.
* Note: cards with speed_rating of 0 are kept at the end of the list.
@@ -125,6 +132,9 @@
}
/**
+ * __zcrypt_decrease_preference(): Decrease preference of a crypto device.
+ * @zdev: Pointer to a crypto device.
+ *
* Move the device towards the tail of the device list.
* Need to be called while holding the zcrypt device list lock.
* Note: cards with speed_rating of 0 are kept at the end of the list.
@@ -198,7 +208,10 @@
EXPORT_SYMBOL(zcrypt_device_free);
/**
- * Register a crypto device.
+ * zcrypt_device_register() - Register a crypto device.
+ * @zdev: Pointer to a crypto device
+ *
+ * Register a crypto device. Returns 0 if successful.
*/
int zcrypt_device_register(struct zcrypt_device *zdev)
{
@@ -216,16 +229,37 @@
__zcrypt_increase_preference(zdev);
zcrypt_device_count++;
spin_unlock_bh(&zcrypt_device_lock);
+ if (zdev->ops->rng) {
+ rc = zcrypt_rng_device_add();
+ if (rc)
+ goto out_unregister;
+ }
+ return 0;
+
+out_unregister:
+ spin_lock_bh(&zcrypt_device_lock);
+ zcrypt_device_count--;
+ list_del_init(&zdev->list);
+ spin_unlock_bh(&zcrypt_device_lock);
+ sysfs_remove_group(&zdev->ap_dev->device.kobj,
+ &zcrypt_device_attr_group);
+ put_device(&zdev->ap_dev->device);
+ zcrypt_device_put(zdev);
out:
return rc;
}
EXPORT_SYMBOL(zcrypt_device_register);
/**
+ * zcrypt_device_unregister(): Unregister a crypto device.
+ * @zdev: Pointer to crypto device
+ *
* Unregister a crypto device.
*/
void zcrypt_device_unregister(struct zcrypt_device *zdev)
{
+ if (zdev->ops->rng)
+ zcrypt_rng_device_remove();
spin_lock_bh(&zcrypt_device_lock);
zcrypt_device_count--;
list_del_init(&zdev->list);
@@ -238,7 +272,9 @@
EXPORT_SYMBOL(zcrypt_device_unregister);
/**
- * zcrypt_read is not be supported beyond zcrypt 1.3.1
+ * zcrypt_read (): Not supported beyond zcrypt 1.3.1.
+ *
+ * This function is not supported beyond zcrypt 1.3.1.
*/
static ssize_t zcrypt_read(struct file *filp, char __user *buf,
size_t count, loff_t *f_pos)
@@ -247,6 +283,8 @@
}
/**
+ * zcrypt_write(): Not allowed.
+ *
* Write is is not allowed
*/
static ssize_t zcrypt_write(struct file *filp, const char __user *buf,
@@ -256,7 +294,9 @@
}
/**
- * Device open/close functions to count number of users.
+ * zcrypt_open(): Count number of users.
+ *
+ * Device open function to count number of users.
*/
static int zcrypt_open(struct inode *inode, struct file *filp)
{
@@ -264,13 +304,18 @@
return 0;
}
+/**
+ * zcrypt_release(): Count number of users.
+ *
+ * Device close function to count number of users.
+ */
static int zcrypt_release(struct inode *inode, struct file *filp)
{
atomic_dec(&zcrypt_open_count);
return 0;
}
-/**
+/*
* zcrypt ioctls.
*/
static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex)
@@ -280,7 +325,7 @@
if (mex->outputdatalength < mex->inputdatalength)
return -EINVAL;
- /**
+ /*
* As long as outputdatalength is big enough, we can set the
* outputdatalength equal to the inputdatalength, since that is the
* number of bytes we will copy in any case
@@ -326,7 +371,7 @@
if (crt->outputdatalength < crt->inputdatalength ||
(crt->inputdatalength & 1))
return -EINVAL;
- /**
+ /*
* As long as outputdatalength is big enough, we can set the
* outputdatalength equal to the inputdatalength, since that is the
* number of bytes we will copy in any case
@@ -343,7 +388,7 @@
zdev->max_mod_size < crt->inputdatalength)
continue;
if (zdev->short_crt && crt->inputdatalength > 240) {
- /**
+ /*
* Check inputdata for leading zeros for cards
* that can't handle np_prime, bp_key, or
* u_mult_inv > 128 bytes.
@@ -359,7 +404,7 @@
copy_from_user(&z3, crt->u_mult_inv, len))
return -EFAULT;
copied = 1;
- /**
+ /*
* We have to restart device lookup -
* the device list may have changed by now.
*/
@@ -427,6 +472,37 @@
return -ENODEV;
}
+static long zcrypt_rng(char *buffer)
+{
+ struct zcrypt_device *zdev;
+ int rc;
+
+ spin_lock_bh(&zcrypt_device_lock);
+ list_for_each_entry(zdev, &zcrypt_device_list, list) {
+ if (!zdev->online || !zdev->ops->rng)
+ continue;
+ zcrypt_device_get(zdev);
+ get_device(&zdev->ap_dev->device);
+ zdev->request_count++;
+ __zcrypt_decrease_preference(zdev);
+ if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
+ spin_unlock_bh(&zcrypt_device_lock);
+ rc = zdev->ops->rng(zdev, buffer);
+ spin_lock_bh(&zcrypt_device_lock);
+ module_put(zdev->ap_dev->drv->driver.owner);
+ } else
+ rc = -EAGAIN;
+ zdev->request_count--;
+ __zcrypt_increase_preference(zdev);
+ put_device(&zdev->ap_dev->device);
+ zcrypt_device_put(zdev);
+ spin_unlock_bh(&zcrypt_device_lock);
+ return rc;
+ }
+ spin_unlock_bh(&zcrypt_device_lock);
+ return -ENODEV;
+}
+
static void zcrypt_status_mask(char status[AP_DEVICES])
{
struct zcrypt_device *zdev;
@@ -514,6 +590,8 @@
}
/**
+ * zcrypt_ica_status(): Old, depracted combi status call.
+ *
* Old, deprecated combi status call.
*/
static long zcrypt_ica_status(struct file *filp, unsigned long arg)
@@ -615,7 +693,7 @@
(int __user *) arg);
case Z90STAT_DOMAIN_INDEX:
return put_user(ap_domain_index, (int __user *) arg);
- /**
+ /*
* Deprecated ioctls. Don't add another device count ioctl,
* you can count them yourself in the user space with the
* output of the Z90STAT_STATUS_MASK ioctl.
@@ -653,7 +731,7 @@
}
#ifdef CONFIG_COMPAT
-/**
+/*
* ioctl32 conversion routines
*/
struct compat_ica_rsa_modexpo {
@@ -804,7 +882,7 @@
}
#endif
-/**
+/*
* Misc device file operations.
*/
static const struct file_operations zcrypt_fops = {
@@ -819,7 +897,7 @@
.release = zcrypt_release
};
-/**
+/*
* Misc device.
*/
static struct miscdevice zcrypt_misc_device = {
@@ -828,7 +906,7 @@
.fops = &zcrypt_fops,
};
-/**
+/*
* Deprecated /proc entry support.
*/
static struct proc_dir_entry *zcrypt_entry;
@@ -1022,7 +1100,7 @@
}
for (j = 0; j < 64 && *ptr; ptr++) {
- /**
+ /*
* '0' for no device, '1' for PCICA, '2' for PCICC,
* '3' for PCIXCC_MCL2, '4' for PCIXCC_MCL3,
* '5' for CEX2C and '6' for CEX2A'
@@ -1041,7 +1119,76 @@
return count;
}
+static int zcrypt_rng_device_count;
+static u32 *zcrypt_rng_buffer;
+static int zcrypt_rng_buffer_index;
+static DEFINE_MUTEX(zcrypt_rng_mutex);
+
+static int zcrypt_rng_data_read(struct hwrng *rng, u32 *data)
+{
+ int rc;
+
+ /*
+ * We don't need locking here because the RNG API guarantees serialized
+ * read method calls.
+ */
+ if (zcrypt_rng_buffer_index == 0) {
+ rc = zcrypt_rng((char *) zcrypt_rng_buffer);
+ if (rc < 0)
+ return -EIO;
+ zcrypt_rng_buffer_index = rc / sizeof *data;
+ }
+ *data = zcrypt_rng_buffer[--zcrypt_rng_buffer_index];
+ return sizeof *data;
+}
+
+static struct hwrng zcrypt_rng_dev = {
+ .name = "zcrypt",
+ .data_read = zcrypt_rng_data_read,
+};
+
+static int zcrypt_rng_device_add(void)
+{
+ int rc = 0;
+
+ mutex_lock(&zcrypt_rng_mutex);
+ if (zcrypt_rng_device_count == 0) {
+ zcrypt_rng_buffer = (u32 *) get_zeroed_page(GFP_KERNEL);
+ if (!zcrypt_rng_buffer) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ zcrypt_rng_buffer_index = 0;
+ rc = hwrng_register(&zcrypt_rng_dev);
+ if (rc)
+ goto out_free;
+ zcrypt_rng_device_count = 1;
+ } else
+ zcrypt_rng_device_count++;
+ mutex_unlock(&zcrypt_rng_mutex);
+ return 0;
+
+out_free:
+ free_page((unsigned long) zcrypt_rng_buffer);
+out:
+ mutex_unlock(&zcrypt_rng_mutex);
+ return rc;
+}
+
+static void zcrypt_rng_device_remove(void)
+{
+ mutex_lock(&zcrypt_rng_mutex);
+ zcrypt_rng_device_count--;
+ if (zcrypt_rng_device_count == 0) {
+ hwrng_unregister(&zcrypt_rng_dev);
+ free_page((unsigned long) zcrypt_rng_buffer);
+ }
+ mutex_unlock(&zcrypt_rng_mutex);
+}
+
/**
+ * zcrypt_api_init(): Module initialization.
+ *
* The module initialization code.
*/
int __init zcrypt_api_init(void)
@@ -1076,6 +1223,8 @@
}
/**
+ * zcrypt_api_exit(): Module termination.
+ *
* The module termination code.
*/
void zcrypt_api_exit(void)
diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h
index de4877e..5c6e222 100644
--- a/drivers/s390/crypto/zcrypt_api.h
+++ b/drivers/s390/crypto/zcrypt_api.h
@@ -43,17 +43,17 @@
#define DEV_NAME "zcrypt"
#define PRINTK(fmt, args...) \
- printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args)
+ printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __func__ , ## args)
#define PRINTKN(fmt, args...) \
printk(KERN_DEBUG DEV_NAME ": " fmt, ## args)
#define PRINTKW(fmt, args...) \
- printk(KERN_WARNING DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args)
+ printk(KERN_WARNING DEV_NAME ": %s -> " fmt, __func__ , ## args)
#define PRINTKC(fmt, args...) \
- printk(KERN_CRIT DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args)
+ printk(KERN_CRIT DEV_NAME ": %s -> " fmt, __func__ , ## args)
#ifdef ZCRYPT_DEBUG
#define PDEBUG(fmt, args...) \
- printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args)
+ printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __func__ , ## args)
#else
#define PDEBUG(fmt, args...) do {} while (0)
#endif
@@ -100,6 +100,13 @@
#define ZCRYPT_CEX2C 5
#define ZCRYPT_CEX2A 6
+/**
+ * Large random numbers are pulled in 4096 byte chunks from the crypto cards
+ * and stored in a page. Be carefull when increasing this buffer due to size
+ * limitations for AP requests.
+ */
+#define ZCRYPT_RNG_BUFFER_SIZE 4096
+
struct zcrypt_device;
struct zcrypt_ops {
@@ -107,6 +114,7 @@
long (*rsa_modexpo_crt)(struct zcrypt_device *,
struct ica_rsa_modexpo_crt *);
long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *);
+ long (*rng)(struct zcrypt_device *, char *);
};
struct zcrypt_device {
diff --git a/drivers/s390/crypto/zcrypt_cca_key.h b/drivers/s390/crypto/zcrypt_cca_key.h
index 8dbcf0e..ed82f2f 100644
--- a/drivers/s390/crypto/zcrypt_cca_key.h
+++ b/drivers/s390/crypto/zcrypt_cca_key.h
@@ -174,7 +174,7 @@
key->pvtMeHdr = static_pvt_me_hdr;
key->pvtMeSec = static_pvt_me_sec;
key->pubMeSec = static_pub_me_sec;
- /**
+ /*
* In a private key, the modulus doesn't appear in the public
* section. So, an arbitrary public exponent of 0x010001 will be
* used.
@@ -338,7 +338,7 @@
pub = (struct cca_public_sec *)(key->key_parts + key_len);
*pub = static_cca_pub_sec;
pub->modulus_bit_len = 8 * crt->inputdatalength;
- /**
+ /*
* In a private key, the modulus doesn't appear in the public
* section. So, an arbitrary public exponent of 0x010001 will be
* used.
diff --git a/drivers/s390/crypto/zcrypt_error.h b/drivers/s390/crypto/zcrypt_error.h
index 2cb616b..3e27fe7 100644
--- a/drivers/s390/crypto/zcrypt_error.h
+++ b/drivers/s390/crypto/zcrypt_error.h
@@ -108,7 +108,7 @@
return -EINVAL;
case REP82_ERROR_MESSAGE_TYPE:
// REP88_ERROR_MESSAGE_TYPE // '20' CEX2A
- /**
+ /*
* To sent a message of the wrong type is a bug in the
* device driver. Warn about it, disable the device
* and then repeat the request.
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c
index d6d59bf..17ea56c 100644
--- a/drivers/s390/crypto/zcrypt_pcicc.c
+++ b/drivers/s390/crypto/zcrypt_pcicc.c
@@ -42,7 +42,7 @@
#define PCICC_MAX_MOD_SIZE_OLD 128 /* 1024 bits */
#define PCICC_MAX_MOD_SIZE 256 /* 2048 bits */
-/**
+/*
* PCICC cards need a speed rating of 0. This keeps them at the end of
* the zcrypt device list (see zcrypt_api.c). PCICC cards are only
* used if no other cards are present because they are slow and can only
@@ -388,7 +388,7 @@
reply_len = le16_to_cpu(msg->length) - 2;
if (reply_len > outputdatalength)
return -EINVAL;
- /**
+ /*
* For all encipher requests, the length of the ciphertext (reply_len)
* will always equal the modulus length. For MEX decipher requests
* the output needs to get padded. Minimum pad size is 10.
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index 70b9ddc..0bc9b31 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -356,6 +356,55 @@
}
/**
+ * Prepare a type6 CPRB message for random number generation
+ *
+ * @ap_dev: AP device pointer
+ * @ap_msg: pointer to AP message
+ */
+static void rng_type6CPRB_msgX(struct ap_device *ap_dev,
+ struct ap_message *ap_msg,
+ unsigned random_number_length)
+{
+ struct {
+ struct type6_hdr hdr;
+ struct CPRBX cprbx;
+ char function_code[2];
+ short int rule_length;
+ char rule[8];
+ short int verb_length;
+ short int key_length;
+ } __attribute__((packed)) *msg = ap_msg->message;
+ static struct type6_hdr static_type6_hdrX = {
+ .type = 0x06,
+ .offset1 = 0x00000058,
+ .agent_id = {'C', 'A'},
+ .function_code = {'R', 'L'},
+ .ToCardLen1 = sizeof *msg - sizeof(msg->hdr),
+ .FromCardLen1 = sizeof *msg - sizeof(msg->hdr),
+ };
+ static struct CPRBX static_cprbx = {
+ .cprb_len = 0x00dc,
+ .cprb_ver_id = 0x02,
+ .func_id = {0x54, 0x32},
+ .req_parml = sizeof *msg - sizeof(msg->hdr) -
+ sizeof(msg->cprbx),
+ .rpl_msgbl = sizeof *msg - sizeof(msg->hdr),
+ };
+
+ msg->hdr = static_type6_hdrX;
+ msg->hdr.FromCardLen2 = random_number_length,
+ msg->cprbx = static_cprbx;
+ msg->cprbx.rpl_datal = random_number_length,
+ msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid);
+ memcpy(msg->function_code, msg->hdr.function_code, 0x02);
+ msg->rule_length = 0x0a;
+ memcpy(msg->rule, "RANDOM ", 8);
+ msg->verb_length = 0x02;
+ msg->key_length = 0x02;
+ ap_msg->length = sizeof *msg;
+}
+
+/**
* Copy results from a type 86 ICA reply message back to user space.
*
* @zdev: crypto device pointer
@@ -452,7 +501,7 @@
reply_len = msg->length - 2;
if (reply_len > outputdatalength)
return -EINVAL;
- /**
+ /*
* For all encipher requests, the length of the ciphertext (reply_len)
* will always equal the modulus length. For MEX decipher requests
* the output needs to get padded. Minimum pad size is 10.
@@ -509,6 +558,26 @@
return 0;
}
+static int convert_type86_rng(struct zcrypt_device *zdev,
+ struct ap_message *reply,
+ char *buffer)
+{
+ struct {
+ struct type86_hdr hdr;
+ struct type86_fmt2_ext fmt2;
+ struct CPRBX cprbx;
+ } __attribute__((packed)) *msg = reply->message;
+ char *data = reply->message;
+
+ if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0) {
+ PDEBUG("RNG response error on PCIXCC/CEX2C rc=%hu/rs=%hu\n",
+ rc, rs);
+ return -EINVAL;
+ }
+ memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2);
+ return msg->fmt2.count2;
+}
+
static int convert_response_ica(struct zcrypt_device *zdev,
struct ap_message *reply,
char __user *outputdata,
@@ -567,6 +636,31 @@
}
}
+static int convert_response_rng(struct zcrypt_device *zdev,
+ struct ap_message *reply,
+ char *data)
+{
+ struct type86x_reply *msg = reply->message;
+
+ switch (msg->hdr.type) {
+ case TYPE82_RSP_CODE:
+ case TYPE88_RSP_CODE:
+ return -EINVAL;
+ case TYPE86_RSP_CODE:
+ if (msg->hdr.reply_code)
+ return -EINVAL;
+ if (msg->cprbx.cprb_ver_id == 0x02)
+ return convert_type86_rng(zdev, reply, data);
+ /* no break, incorrect cprb version is an unknown response */
+ default: /* Unknown response type, this should NEVER EVER happen */
+ PRINTK("Unrecognized Message Header: %08x%08x\n",
+ *(unsigned int *) reply->message,
+ *(unsigned int *) (reply->message+4));
+ zdev->online = 0;
+ return -EAGAIN; /* repeat the request on a different device. */
+ }
+}
+
/**
* This function is called from the AP bus code after a crypto request
* "msg" has finished with the reply message "reply".
@@ -736,6 +830,42 @@
}
/**
+ * The request distributor calls this function if it picked the PCIXCC/CEX2C
+ * device to generate random data.
+ * @zdev: pointer to zcrypt_device structure that identifies the
+ * PCIXCC/CEX2C device to the request distributor
+ * @buffer: pointer to a memory page to return random data
+ */
+
+static long zcrypt_pcixcc_rng(struct zcrypt_device *zdev,
+ char *buffer)
+{
+ struct ap_message ap_msg;
+ struct response_type resp_type = {
+ .type = PCIXCC_RESPONSE_TYPE_XCRB,
+ };
+ int rc;
+
+ ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
+ if (!ap_msg.message)
+ return -ENOMEM;
+ ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
+ atomic_inc_return(&zcrypt_step);
+ ap_msg.private = &resp_type;
+ rng_type6CPRB_msgX(zdev->ap_dev, &ap_msg, ZCRYPT_RNG_BUFFER_SIZE);
+ init_completion(&resp_type.work);
+ ap_queue_message(zdev->ap_dev, &ap_msg);
+ rc = wait_for_completion_interruptible(&resp_type.work);
+ if (rc == 0)
+ rc = convert_response_rng(zdev, &ap_msg, buffer);
+ else
+ /* Signal pending. */
+ ap_cancel_message(zdev->ap_dev, &ap_msg);
+ kfree(ap_msg.message);
+ return rc;
+}
+
+/**
* The crypto operations for a PCIXCC/CEX2C card.
*/
static struct zcrypt_ops zcrypt_pcixcc_ops = {
@@ -744,6 +874,13 @@
.send_cprb = zcrypt_pcixcc_send_cprb,
};
+static struct zcrypt_ops zcrypt_pcixcc_with_rng_ops = {
+ .rsa_modexpo = zcrypt_pcixcc_modexpo,
+ .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
+ .send_cprb = zcrypt_pcixcc_send_cprb,
+ .rng = zcrypt_pcixcc_rng,
+};
+
/**
* Micro-code detection function. Its sends a message to a pcixcc card
* to find out the microcode level.
@@ -859,6 +996,58 @@
}
/**
+ * Large random number detection function. Its sends a message to a pcixcc
+ * card to find out if large random numbers are supported.
+ * @ap_dev: pointer to the AP device.
+ *
+ * Returns 1 if large random numbers are supported, 0 if not and < 0 on error.
+ */
+static int zcrypt_pcixcc_rng_supported(struct ap_device *ap_dev)
+{
+ struct ap_message ap_msg;
+ unsigned long long psmid;
+ struct {
+ struct type86_hdr hdr;
+ struct type86_fmt2_ext fmt2;
+ struct CPRBX cprbx;
+ } __attribute__((packed)) *reply;
+ int rc, i;
+
+ ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
+ if (!ap_msg.message)
+ return -ENOMEM;
+
+ rng_type6CPRB_msgX(ap_dev, &ap_msg, 4);
+ rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, ap_msg.message,
+ ap_msg.length);
+ if (rc)
+ goto out_free;
+
+ /* Wait for the test message to complete. */
+ for (i = 0; i < 2 * HZ; i++) {
+ msleep(1000 / HZ);
+ rc = ap_recv(ap_dev->qid, &psmid, ap_msg.message, 4096);
+ if (rc == 0 && psmid == 0x0102030405060708ULL)
+ break;
+ }
+
+ if (i >= 2 * HZ) {
+ /* Got no answer. */
+ rc = -ENODEV;
+ goto out_free;
+ }
+
+ reply = ap_msg.message;
+ if (reply->cprbx.ccp_rtcode == 0 && reply->cprbx.ccp_rscode == 0)
+ rc = 1;
+ else
+ rc = 0;
+out_free:
+ free_page((unsigned long) ap_msg.message);
+ return rc;
+}
+
+/**
* Probe function for PCIXCC/CEX2C cards. It always accepts the AP device
* since the bus_match already checked the hardware type. The PCIXCC
* cards come in two flavours: micro code level 2 and micro code level 3.
@@ -874,7 +1063,6 @@
if (!zdev)
return -ENOMEM;
zdev->ap_dev = ap_dev;
- zdev->ops = &zcrypt_pcixcc_ops;
zdev->online = 1;
if (ap_dev->device_type == AP_DEVICE_TYPE_PCIXCC) {
rc = zcrypt_pcixcc_mcl(ap_dev);
@@ -901,6 +1089,15 @@
zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
}
+ rc = zcrypt_pcixcc_rng_supported(ap_dev);
+ if (rc < 0) {
+ zcrypt_device_free(zdev);
+ return rc;
+ }
+ if (rc)
+ zdev->ops = &zcrypt_pcixcc_with_rng_ops;
+ else
+ zdev->ops = &zcrypt_pcixcc_ops;
ap_dev->reply = &zdev->reply;
ap_dev->private = zdev;
rc = zcrypt_device_register(zdev);
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index d8a5c22..04a1d7b 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -299,7 +299,7 @@
struct claw_privbk *privptr=NULL;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s Enter\n",__FUNCTION__);
+ printk(KERN_INFO "%s Enter\n",__func__);
#endif
CLAW_DBF_TEXT(2,setup,"probe");
if (!get_device(&cgdev->dev))
@@ -313,7 +313,7 @@
probe_error(cgdev);
put_device(&cgdev->dev);
printk(KERN_WARNING "Out of memory %s %s Exit Line %d \n",
- cgdev->cdev[0]->dev.bus_id,__FUNCTION__,__LINE__);
+ cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
CLAW_DBF_TEXT_(2,setup,"probex%d",-ENOMEM);
return -ENOMEM;
}
@@ -323,7 +323,7 @@
probe_error(cgdev);
put_device(&cgdev->dev);
printk(KERN_WARNING "Out of memory %s %s Exit Line %d \n",
- cgdev->cdev[0]->dev.bus_id,__FUNCTION__,__LINE__);
+ cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
CLAW_DBF_TEXT_(2,setup,"probex%d",-ENOMEM);
return -ENOMEM;
}
@@ -340,7 +340,7 @@
probe_error(cgdev);
put_device(&cgdev->dev);
printk(KERN_WARNING "add_files failed %s %s Exit Line %d \n",
- cgdev->cdev[0]->dev.bus_id,__FUNCTION__,__LINE__);
+ cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
CLAW_DBF_TEXT_(2,setup,"probex%d",rc);
return rc;
}
@@ -351,7 +351,7 @@
cgdev->dev.driver_data = privptr;
#ifdef FUNCTRACE
printk(KERN_INFO "claw:%s exit on line %d, "
- "rc = 0\n",__FUNCTION__,__LINE__);
+ "rc = 0\n",__func__,__LINE__);
#endif
CLAW_DBF_TEXT(2,setup,"prbext 0");
@@ -371,7 +371,7 @@
struct chbk *p_ch;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s enter\n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s enter\n",dev->name,__func__);
#endif
CLAW_DBF_TEXT(4,trace,"claw_tx");
p_ch=&privptr->channel[WRITE];
@@ -381,7 +381,7 @@
privptr->stats.tx_dropped++;
#ifdef FUNCTRACE
printk(KERN_INFO "%s: %s() exit on line %d, rc = EIO\n",
- dev->name,__FUNCTION__, __LINE__);
+ dev->name,__func__, __LINE__);
#endif
CLAW_DBF_TEXT_(2,trace,"clawtx%d",-EIO);
return -EIO;
@@ -398,7 +398,7 @@
spin_unlock_irqrestore(get_ccwdev_lock(p_ch->cdev), saveflags);
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s exit on line %d, rc = %d\n",
- dev->name, __FUNCTION__, __LINE__, rc);
+ dev->name, __func__, __LINE__, rc);
#endif
CLAW_DBF_TEXT_(4,trace,"clawtx%d",rc);
return rc;
@@ -460,7 +460,7 @@
#ifdef IOTRACE
printk(KERN_INFO "%s: %s() Packed %d len %d\n",
p_env->ndev->name,
- __FUNCTION__,pkt_cnt,new_skb->len);
+ __func__,pkt_cnt,new_skb->len);
#endif
}
CLAW_DBF_TEXT(4,trace,"PackSKBx");
@@ -478,7 +478,7 @@
struct claw_privbk *privptr=dev->priv;
int buff_size;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
#endif
#ifdef DEBUGMSG
printk(KERN_INFO "variable dev =\n");
@@ -491,14 +491,14 @@
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d, rc=EINVAL\n",
dev->name,
- __FUNCTION__, __LINE__);
+ __func__, __LINE__);
#endif
return -EINVAL;
}
dev->mtu = new_mtu;
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",dev->name,
- __FUNCTION__, __LINE__);
+ __func__, __LINE__);
#endif
return 0;
} /* end of claw_change_mtu */
@@ -522,7 +522,7 @@
struct ccwbk *p_buf;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
#endif
CLAW_DBF_TEXT(4,trace,"open");
if (!dev || (dev->name[0] == 0x00)) {
@@ -537,7 +537,7 @@
if (rc) {
printk(KERN_INFO "%s:%s Exit on line %d, rc=ENOMEM\n",
dev->name,
- __FUNCTION__, __LINE__);
+ __func__, __LINE__);
CLAW_DBF_TEXT(2,trace,"openmem");
return -ENOMEM;
}
@@ -661,7 +661,7 @@
claw_clear_busy(dev);
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d, rc=EIO\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(2,trace,"open EIO");
return -EIO;
@@ -673,7 +673,7 @@
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d, rc=0\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"openok");
return 0;
@@ -696,7 +696,7 @@
#ifdef FUNCTRACE
- printk(KERN_INFO "%s enter \n",__FUNCTION__);
+ printk(KERN_INFO "%s enter \n",__func__);
#endif
CLAW_DBF_TEXT(4,trace,"clawirq");
/* Bypass all 'unsolicited interrupts' */
@@ -706,7 +706,7 @@
cdev->dev.bus_id,irb->scsw.cstat, irb->scsw.dstat);
#ifdef FUNCTRACE
printk(KERN_INFO "claw: %s() "
- "exit on line %d\n",__FUNCTION__,__LINE__);
+ "exit on line %d\n",__func__,__LINE__);
#endif
CLAW_DBF_TEXT(2,trace,"badirq");
return;
@@ -752,7 +752,7 @@
#endif
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(2,trace,"chanchk");
/* return; */
@@ -777,7 +777,7 @@
(SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
return;
}
@@ -788,7 +788,7 @@
#endif
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"stop");
return;
@@ -804,7 +804,7 @@
(SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"haltio");
return;
@@ -838,7 +838,7 @@
#endif
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"haltio");
return;
@@ -858,7 +858,7 @@
}
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"notrdy");
return;
@@ -874,7 +874,7 @@
}
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"PCI_read");
return;
@@ -885,7 +885,7 @@
(SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"SPend_rd");
return;
@@ -906,7 +906,7 @@
#endif
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"RdIRQXit");
return;
@@ -929,7 +929,7 @@
}
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"rstrtwrt");
return;
@@ -946,7 +946,7 @@
(SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"writeUE");
return;
@@ -969,7 +969,7 @@
#endif
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"StWtExit");
return;
@@ -978,7 +978,7 @@
"state=%d\n",dev->name,p_ch->claw_state);
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(2,trace,"badIRQ");
return;
@@ -1001,7 +1001,7 @@
p_ch = (struct chbk *) data;
dev = (struct net_device *)p_ch->ndev;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
#endif
#ifdef DEBUGMSG
printk(KERN_INFO "%s: variable p_ch =\n",dev->name);
@@ -1021,7 +1021,7 @@
CLAW_DBF_TEXT(4,trace,"TskletXt");
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
return;
} /* end of claw_irq_bh */
@@ -1048,7 +1048,7 @@
if (!privptr)
return 0;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
#endif
CLAW_DBF_TEXT(4,trace,"release");
#ifdef DEBUGMSG
@@ -1090,7 +1090,7 @@
if(privptr->buffs_alloc != 1) {
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"none2fre");
return 0;
@@ -1171,7 +1171,7 @@
}
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"rlsexit");
return 0;
@@ -1192,7 +1192,7 @@
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
printk(KERN_INFO "claw: variable p_ch =\n");
dumpit((char *) p_ch, sizeof(struct chbk));
#endif
@@ -1200,20 +1200,20 @@
if (p_ch->claw_state == CLAW_STOP) {
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
return;
}
#ifdef DEBUGMSG
printk( KERN_INFO "%s:%s state-%02x\n" ,
dev->name,
- __FUNCTION__,
+ __func__,
p_ch->claw_state);
#endif
claw_strt_out_IO( dev );
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"rtry_xit");
return;
@@ -1235,7 +1235,7 @@
int rc;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",p_ch->ndev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Enter \n",p_ch->ndev->name,__func__);
printk(KERN_INFO "%s: variable p_ch =\n",p_ch->ndev->name);
dumpit((char *) p_ch, sizeof(struct chbk));
#endif
@@ -1262,7 +1262,7 @@
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
return;
} /* end of claw_write_next */
@@ -1276,7 +1276,7 @@
claw_timer ( struct chbk * p_ch )
{
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Entry\n",p_ch->ndev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Entry\n",p_ch->ndev->name,__func__);
printk(KERN_INFO "%s: variable p_ch =\n",p_ch->ndev->name);
dumpit((char *) p_ch, sizeof(struct chbk));
#endif
@@ -1285,7 +1285,7 @@
wake_up(&p_ch->wait);
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- p_ch->ndev->name,__FUNCTION__,__LINE__);
+ p_ch->ndev->name,__func__,__LINE__);
#endif
return;
} /* end of claw_timer */
@@ -1312,7 +1312,7 @@
int order_of_mag=1; /* assume 2 pages */
int nump=2;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s Enter pages = %d \n",__FUNCTION__,num_of_pages);
+ printk(KERN_INFO "%s Enter pages = %d \n",__func__,num_of_pages);
#endif
CLAW_DBF_TEXT_(5,trace,"pages%d",num_of_pages);
if (num_of_pages == 1) {return 0; } /* magnitude of 0 = 1 page */
@@ -1327,7 +1327,7 @@
if (order_of_mag > 9) { order_of_mag = 9; } /* I know it's paranoid */
#ifdef FUNCTRACE
printk(KERN_INFO "%s Exit on line %d, order = %d\n",
- __FUNCTION__,__LINE__, order_of_mag);
+ __func__,__LINE__, order_of_mag);
#endif
CLAW_DBF_TEXT_(5,trace,"mag%d",order_of_mag);
return order_of_mag;
@@ -1349,7 +1349,7 @@
struct ccwbk* p_buf;
#endif
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
#endif
#ifdef DEBUGMSG
printk(KERN_INFO "dev\n");
@@ -1369,7 +1369,7 @@
if ( p_first==NULL) {
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"addexit");
return 0;
@@ -1400,9 +1400,9 @@
if ( privptr-> p_read_active_first ==NULL ) {
#ifdef DEBUGMSG
printk(KERN_INFO "%s:%s p_read_active_first == NULL \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
printk(KERN_INFO "%s:%s Read active first/last changed \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
#endif
privptr-> p_read_active_first= p_first; /* set new first */
privptr-> p_read_active_last = p_last; /* set new last */
@@ -1411,7 +1411,7 @@
#ifdef DEBUGMSG
printk(KERN_INFO "%s:%s Read in progress \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
#endif
/* set up TIC ccw */
temp_ccw.cda= (__u32)__pa(&p_first->read);
@@ -1450,15 +1450,15 @@
privptr->p_read_active_last=p_last;
} /* end of if ( privptr-> p_read_active_first ==NULL) */
#ifdef IOTRACE
- printk(KERN_INFO "%s:%s dump p_last CCW BK \n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s dump p_last CCW BK \n",dev->name,__func__);
dumpit((char *)p_last, sizeof(struct ccwbk));
- printk(KERN_INFO "%s:%s dump p_end CCW BK \n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s dump p_end CCW BK \n",dev->name,__func__);
dumpit((char *)p_end, sizeof(struct endccw));
- printk(KERN_INFO "%s:%s dump p_first CCW BK \n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s dump p_first CCW BK \n",dev->name,__func__);
dumpit((char *)p_first, sizeof(struct ccwbk));
printk(KERN_INFO "%s:%s Dump Active CCW chain \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
p_buf=privptr->p_read_active_first;
while (p_buf!=NULL) {
dumpit((char *)p_buf, sizeof(struct ccwbk));
@@ -1467,7 +1467,7 @@
#endif
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"addexit");
return 0;
@@ -1483,7 +1483,7 @@
{
#ifdef FUNCTRACE
printk(KERN_INFO "%s: %s() > enter \n",
- cdev->dev.bus_id,__FUNCTION__);
+ cdev->dev.bus_id,__func__);
#endif
CLAW_DBF_TEXT(4,trace,"ccwret");
#ifdef DEBUGMSG
@@ -1516,7 +1516,7 @@
}
#ifdef FUNCTRACE
printk(KERN_INFO "%s: %s() > exit on line %d\n",
- cdev->dev.bus_id,__FUNCTION__,__LINE__);
+ cdev->dev.bus_id,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"ccwret");
} /* end of ccw_check_return_code */
@@ -1531,7 +1531,7 @@
struct net_device *dev = p_ch->ndev;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > enter\n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s: %s() > enter\n",dev->name,__func__);
#endif
#ifdef DEBUGMSG
printk(KERN_INFO "%s: variable dev =\n",dev->name);
@@ -1578,7 +1578,7 @@
#ifdef FUNCTRACE
printk(KERN_INFO "%s: %s() exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
} /* end of ccw_check_unit_check */
@@ -1706,7 +1706,7 @@
int rc=0;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s > enter \n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s > enter \n",dev->name,__func__);
#endif
CLAW_DBF_TEXT(2,setup,"findlink");
#ifdef DEBUGMSG
@@ -1739,7 +1739,7 @@
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
return 0;
} /* end of find_link */
@@ -1773,7 +1773,7 @@
struct ccwbk *p_buf;
#endif
#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > enter\n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s: %s() > enter\n",dev->name,__func__);
#endif
CLAW_DBF_TEXT(4,trace,"hw_tx");
#ifdef DEBUGMSG
@@ -1787,7 +1787,7 @@
p_ch=(struct chbk *)&privptr->channel[WRITE];
p_env =privptr->p_env;
#ifdef IOTRACE
- printk(KERN_INFO "%s: %s() dump sk_buff \n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s: %s() dump sk_buff \n",dev->name,__func__);
dumpit((char *)skb ,sizeof(struct sk_buff));
#endif
claw_free_wrt_buf(dev); /* Clean up free chain if posible */
@@ -1877,7 +1877,7 @@
while (len_of_data > 0) {
#ifdef DEBUGMSG
printk(KERN_INFO "%s: %s() length-of-data is %ld \n",
- dev->name ,__FUNCTION__,len_of_data);
+ dev->name ,__func__,len_of_data);
dumpit((char *)pDataAddress ,64);
#endif
p_this_ccw=privptr->p_write_free_chain; /* get a block */
@@ -1913,7 +1913,7 @@
p_last_ccw=p_this_ccw; /* save new last block */
#ifdef IOTRACE
printk(KERN_INFO "%s: %s() > CCW and Buffer %ld bytes long \n",
- dev->name,__FUNCTION__,bytesInThisBuffer);
+ dev->name,__func__,bytesInThisBuffer);
dumpit((char *)p_this_ccw, sizeof(struct ccwbk));
dumpit((char *)p_this_ccw->p_buffer, 64);
#endif
@@ -1998,7 +1998,7 @@
#ifdef IOTRACE
printk(KERN_INFO "%s: %s() > Dump Active CCW chain \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
p_buf=privptr->p_write_active_first;
while (p_buf!=NULL) {
dumpit((char *)p_buf, sizeof(struct ccwbk));
@@ -2018,7 +2018,7 @@
/* if write free count is zero , set NOBUFFER */
#ifdef DEBUGMSG
printk(KERN_INFO "%s: %s() > free_count is %d\n",
- dev->name,__FUNCTION__,
+ dev->name,__func__,
(int) privptr->write_free_count );
#endif
if (privptr->write_free_count==0) {
@@ -2029,7 +2029,7 @@
Done:
#ifdef FUNCTRACE
printk(KERN_INFO "%s: %s() > exit on line %d, rc = %d \n",
- dev->name,__FUNCTION__,__LINE__, rc);
+ dev->name,__func__,__LINE__, rc);
#endif
return(rc);
} /* end of claw_hw_tx */
@@ -2063,7 +2063,7 @@
addr_t real_TIC_address;
int i,j;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() enter \n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s: %s() enter \n",dev->name,__func__);
#endif
CLAW_DBF_TEXT(4,trace,"init_ccw");
#ifdef DEBUGMSG
@@ -2097,15 +2097,15 @@
#ifdef DEBUGMSG
printk(KERN_INFO "%s: %s() "
"ccw_blocks_required=%d\n",
- dev->name,__FUNCTION__,
+ dev->name,__func__,
ccw_blocks_required);
printk(KERN_INFO "%s: %s() "
"PAGE_SIZE=0x%x\n",
- dev->name,__FUNCTION__,
+ dev->name,__func__,
(unsigned int)PAGE_SIZE);
printk(KERN_INFO "%s: %s() > "
"PAGE_MASK=0x%x\n",
- dev->name,__FUNCTION__,
+ dev->name,__func__,
(unsigned int)PAGE_MASK);
#endif
/*
@@ -2117,10 +2117,10 @@
#ifdef DEBUGMSG
printk(KERN_INFO "%s: %s() > ccw_blocks_perpage=%d\n",
- dev->name,__FUNCTION__,
+ dev->name,__func__,
ccw_blocks_perpage);
printk(KERN_INFO "%s: %s() > ccw_pages_required=%d\n",
- dev->name,__FUNCTION__,
+ dev->name,__func__,
ccw_pages_required);
#endif
/*
@@ -2156,29 +2156,29 @@
#ifdef DEBUGMSG
if (privptr->p_env->read_size < PAGE_SIZE) {
printk(KERN_INFO "%s: %s() reads_perpage=%d\n",
- dev->name,__FUNCTION__,
+ dev->name,__func__,
claw_reads_perpage);
}
else {
printk(KERN_INFO "%s: %s() pages_perread=%d\n",
- dev->name,__FUNCTION__,
+ dev->name,__func__,
privptr->p_buff_pages_perread);
}
printk(KERN_INFO "%s: %s() read_pages=%d\n",
- dev->name,__FUNCTION__,
+ dev->name,__func__,
claw_read_pages);
if (privptr->p_env->write_size < PAGE_SIZE) {
printk(KERN_INFO "%s: %s() writes_perpage=%d\n",
- dev->name,__FUNCTION__,
+ dev->name,__func__,
claw_writes_perpage);
}
else {
printk(KERN_INFO "%s: %s() pages_perwrite=%d\n",
- dev->name,__FUNCTION__,
+ dev->name,__func__,
privptr->p_buff_pages_perwrite);
}
printk(KERN_INFO "%s: %s() write_pages=%d\n",
- dev->name,__FUNCTION__,
+ dev->name,__func__,
claw_write_pages);
#endif
@@ -2194,12 +2194,12 @@
printk(KERN_INFO "%s: %s() "
"__get_free_pages for CCWs failed : "
"pages is %d\n",
- dev->name,__FUNCTION__,
+ dev->name,__func__,
ccw_pages_required );
#ifdef FUNCTRACE
printk(KERN_INFO "%s: %s() > "
"exit on line %d, rc = ENOMEM\n",
- dev->name,__FUNCTION__,
+ dev->name,__func__,
__LINE__);
#endif
return -ENOMEM;
@@ -2218,7 +2218,7 @@
/* Initialize ending CCW block */
#ifdef DEBUGMSG
printk(KERN_INFO "%s: %s() begin initialize ending CCW blocks\n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
#endif
p_endccw=privptr->p_end_ccw;
@@ -2276,7 +2276,7 @@
#ifdef IOTRACE
printk(KERN_INFO "%s: %s() dump claw ending CCW BK \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
dumpit((char *)p_endccw, sizeof(struct endccw));
#endif
@@ -2287,7 +2287,7 @@
#ifdef DEBUGMSG
printk(KERN_INFO "%s: %s() Begin build a chain of CCW buffer \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
#endif
p_buff=privptr->p_buff_ccw;
@@ -2306,7 +2306,7 @@
#ifdef DEBUGMSG
printk(KERN_INFO "%s: %s() "
"End build a chain of CCW buffer \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
p_buf=p_free_chain;
while (p_buf!=NULL) {
dumpit((char *)p_buf, sizeof(struct ccwbk));
@@ -2321,7 +2321,7 @@
#ifdef DEBUGMSG
printk(KERN_INFO "%s: %s() "
"Begin initialize ClawSignalBlock \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
#endif
if (privptr->p_claw_signal_blk==NULL) {
privptr->p_claw_signal_blk=p_free_chain;
@@ -2334,7 +2334,7 @@
#ifdef DEBUGMSG
printk(KERN_INFO "%s: %s() > End initialize "
"ClawSignalBlock\n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
dumpit((char *)privptr->p_claw_signal_blk, sizeof(struct ccwbk));
#endif
@@ -2349,14 +2349,14 @@
if (privptr->p_buff_write==NULL) {
printk(KERN_INFO "%s: %s() __get_free_pages for write"
" bufs failed : get is for %d pages\n",
- dev->name,__FUNCTION__,claw_write_pages );
+ dev->name,__func__,claw_write_pages );
free_pages((unsigned long)privptr->p_buff_ccw,
(int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
privptr->p_buff_ccw=NULL;
#ifdef FUNCTRACE
printk(KERN_INFO "%s: %s() > exit on line %d,"
"rc = ENOMEM\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
return -ENOMEM;
}
@@ -2369,7 +2369,7 @@
ccw_pages_required * PAGE_SIZE);
#ifdef DEBUGMSG
printk(KERN_INFO "%s: %s() Begin build claw write free "
- "chain \n",dev->name,__FUNCTION__);
+ "chain \n",dev->name,__func__);
#endif
privptr->p_write_free_chain=NULL;
@@ -2409,14 +2409,14 @@
#ifdef IOTRACE
printk(KERN_INFO "%s:%s __get_free_pages "
"for writes buf: get for %d pages\n",
- dev->name,__FUNCTION__,
+ dev->name,__func__,
privptr->p_buff_pages_perwrite);
#endif
if (p_buff==NULL) {
printk(KERN_INFO "%s:%s __get_free_pages "
"for writes buf failed : get is for %d pages\n",
dev->name,
- __FUNCTION__,
+ __func__,
privptr->p_buff_pages_perwrite );
free_pages((unsigned long)privptr->p_buff_ccw,
(int)pages_to_order_of_mag(
@@ -2433,7 +2433,7 @@
#ifdef FUNCTRACE
printk(KERN_INFO "%s: %s exit on line %d, rc = ENOMEM\n",
dev->name,
- __FUNCTION__,
+ __func__,
__LINE__);
#endif
return -ENOMEM;
@@ -2466,7 +2466,7 @@
#ifdef DEBUGMSG
printk(KERN_INFO "%s:%s End build claw write free chain \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
p_buf=privptr->p_write_free_chain;
while (p_buf!=NULL) {
dumpit((char *)p_buf, sizeof(struct ccwbk));
@@ -2485,7 +2485,7 @@
printk(KERN_INFO "%s: %s() "
"__get_free_pages for read buf failed : "
"get is for %d pages\n",
- dev->name,__FUNCTION__,claw_read_pages );
+ dev->name,__func__,claw_read_pages );
free_pages((unsigned long)privptr->p_buff_ccw,
(int)pages_to_order_of_mag(
privptr->p_buff_ccw_num));
@@ -2497,7 +2497,7 @@
privptr->p_buff_write=NULL;
#ifdef FUNCTRACE
printk(KERN_INFO "%s: %s() > exit on line %d, rc ="
- " ENOMEM\n",dev->name,__FUNCTION__,__LINE__);
+ " ENOMEM\n",dev->name,__func__,__LINE__);
#endif
return -ENOMEM;
}
@@ -2509,7 +2509,7 @@
*/
#ifdef DEBUGMSG
printk(KERN_INFO "%s: %s() Begin build claw read free chain \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
#endif
p_buff=privptr->p_buff_read;
for (i=0 ; i< privptr->p_env->read_buffers ; i++) {
@@ -2590,7 +2590,7 @@
#ifdef DEBUGMSG
printk(KERN_INFO "%s: %s() Begin build claw read free chain \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
#endif
for (i=0 ; i< privptr->p_env->read_buffers ; i++) {
p_buff = (void *)__get_free_pages(__GFP_DMA,
@@ -2598,7 +2598,7 @@
if (p_buff==NULL) {
printk(KERN_INFO "%s: %s() __get_free_pages for read "
"buf failed : get is for %d pages\n",
- dev->name,__FUNCTION__,
+ dev->name,__func__,
privptr->p_buff_pages_perread );
free_pages((unsigned long)privptr->p_buff_ccw,
(int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
@@ -2622,7 +2622,7 @@
privptr->p_buff_write=NULL;
#ifdef FUNCTRACE
printk(KERN_INFO "%s: %s() exit on line %d, rc = ENOMEM\n",
- dev->name,__FUNCTION__,
+ dev->name,__func__,
__LINE__);
#endif
return -ENOMEM;
@@ -2695,7 +2695,7 @@
} /* pBuffread = NULL */
#ifdef DEBUGMSG
printk(KERN_INFO "%s: %s() > End build claw read free chain \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
p_buf=p_first_CCWB;
while (p_buf!=NULL) {
dumpit((char *)p_buf, sizeof(struct ccwbk));
@@ -2707,7 +2707,7 @@
privptr->buffs_alloc = 1;
#ifdef FUNCTRACE
printk(KERN_INFO "%s: %s() exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
return 0;
} /* end of init_ccw_bk */
@@ -2723,11 +2723,11 @@
{
struct claw_privbk *privptr;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s enter \n",__FUNCTION__);
+ printk(KERN_INFO "%s enter \n",__func__);
#endif
CLAW_DBF_TEXT(4,trace,"proberr");
#ifdef DEBUGMSG
- printk(KERN_INFO "%s variable cgdev =\n",__FUNCTION__);
+ printk(KERN_INFO "%s variable cgdev =\n",__func__);
dumpit((char *) cgdev, sizeof(struct ccwgroup_device));
#endif
privptr=(struct claw_privbk *)cgdev->dev.driver_data;
@@ -2741,7 +2741,7 @@
}
#ifdef FUNCTRACE
printk(KERN_INFO "%s > exit on line %d\n",
- __FUNCTION__,__LINE__);
+ __func__,__LINE__);
#endif
return;
@@ -2772,7 +2772,7 @@
struct chbk *p_ch = NULL;
#ifdef FUNCTRACE
printk(KERN_INFO "%s: %s() > enter \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
#endif
CLAW_DBF_TEXT(2,setup,"clw_cntl");
#ifdef DEBUGMSG
@@ -2794,7 +2794,7 @@
#ifdef FUNCTRACE
printk(KERN_INFO "%s: %s() > "
"exit on line %d, rc=0\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
return 0;
}
@@ -3057,7 +3057,7 @@
#ifdef FUNCTRACE
printk(KERN_INFO "%s: %s() exit on line %d, rc = 0\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
return 0;
@@ -3080,7 +3080,7 @@
struct sk_buff *skb;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s > enter \n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s > enter \n",dev->name,__func__);
#endif
CLAW_DBF_TEXT(2,setup,"sndcntl");
#ifdef DEBUGMSG
@@ -3143,10 +3143,10 @@
skb = dev_alloc_skb(sizeof(struct clawctl));
if (!skb) {
printk( "%s:%s low on mem, returning...\n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
#ifdef DEBUG
printk(KERN_INFO "%s:%s Exit, rc = ENOMEM\n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
#endif
return -ENOMEM;
}
@@ -3162,7 +3162,7 @@
claw_hw_tx(skb, dev, 0);
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
return 0;
@@ -3180,7 +3180,7 @@
struct clawctl *p_ctl;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
#endif
CLAW_DBF_TEXT(2,setup,"snd_conn");
#ifdef DEBUGMSG
@@ -3193,7 +3193,7 @@
if ( privptr->system_validate_comp==0x00 ) {
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d, rc = 1\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
return rc;
}
@@ -3209,7 +3209,7 @@
HOST_APPL_NAME, privptr->p_env->api_type);
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
- dev->name,__FUNCTION__,__LINE__, rc);
+ dev->name,__func__,__LINE__, rc);
#endif
return rc;
@@ -3228,7 +3228,7 @@
struct conncmd * p_connect;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
#endif
CLAW_DBF_TEXT(2,setup,"snd_dsc");
#ifdef DEBUGMSG
@@ -3244,7 +3244,7 @@
p_connect->host_name, p_connect->WS_name);
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
- dev->name,__FUNCTION__, __LINE__, rc);
+ dev->name,__func__, __LINE__, rc);
#endif
return rc;
} /* end of claw_snd_disc */
@@ -3265,7 +3265,7 @@
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Enter\n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
#endif
CLAW_DBF_TEXT(2,setup,"chkresp");
#ifdef DEBUGMSG
@@ -3285,7 +3285,7 @@
p_env->adapter_name );
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
- dev->name,__FUNCTION__,__LINE__, rc);
+ dev->name,__func__,__LINE__, rc);
#endif
return rc;
} /* end of claw_snd_sys_validate_rsp */
@@ -3301,7 +3301,7 @@
int rc;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
#endif
CLAW_DBF_TEXT(2,setup,"conn_req");
#ifdef DEBUGMSG
@@ -3311,7 +3311,7 @@
rc=claw_snd_conn_req(dev, 1);
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
- dev->name,__FUNCTION__,__LINE__, rc);
+ dev->name,__func__,__LINE__, rc);
#endif
return rc;
} /* end of claw_strt_conn_req */
@@ -3327,13 +3327,13 @@
{
struct claw_privbk *privptr;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
#endif
CLAW_DBF_TEXT(4,trace,"stats");
privptr = dev->priv;
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
return &privptr->stats;
} /* end of claw_stats */
@@ -3366,7 +3366,7 @@
int p=0;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s enter \n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s enter \n",dev->name,__func__);
#endif
CLAW_DBF_TEXT(4,trace,"unpkread");
p_first_ccw=NULL;
@@ -3408,7 +3408,7 @@
if ((p_this_ccw->header.opcode & MORE_to_COME_FLAG)!=0) {
#ifdef DEBUGMSG
printk(KERN_INFO "%s: %s > More_to_come is ON\n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
#endif
mtc_this_frm=1;
if (p_this_ccw->header.length!=
@@ -3435,7 +3435,7 @@
#ifdef DEBUGMSG
printk(KERN_INFO "%s:%s goto next "
"frame from MoretoComeSkip \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
#endif
goto NextFrame;
}
@@ -3445,7 +3445,7 @@
#ifdef DEBUGMSG
printk(KERN_INFO "%s:%s goto next "
"frame from claw_process_control \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
#endif
CLAW_DBF_TEXT(4,trace,"UnpkCntl");
goto NextFrame;
@@ -3468,7 +3468,7 @@
if (privptr->mtc_logical_link<0) {
#ifdef DEBUGMSG
printk(KERN_INFO "%s: %s mtc_logical_link < 0 \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
#endif
/*
@@ -3487,7 +3487,7 @@
printk(KERN_INFO "%s: %s > goto next "
"frame from MoretoComeSkip \n",
dev->name,
- __FUNCTION__);
+ __func__);
printk(KERN_INFO " bytes_to_mov %d > (MAX_ENVELOPE_"
"SIZE-privptr->mtc_offset %d)\n",
bytes_to_mov,(MAX_ENVELOPE_SIZE- privptr->mtc_offset));
@@ -3505,13 +3505,13 @@
}
#ifdef DEBUGMSG
printk(KERN_INFO "%s: %s() received data \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
if (p_env->packing == DO_PACKED)
dumpit((char *)p_packd+sizeof(struct clawph),32);
else
dumpit((char *)p_this_ccw->p_buffer, 32);
printk(KERN_INFO "%s: %s() bytelength %d \n",
- dev->name,__FUNCTION__,bytes_to_mov);
+ dev->name,__func__,bytes_to_mov);
#endif
if (mtc_this_frm==0) {
len_of_data=privptr->mtc_offset+bytes_to_mov;
@@ -3530,13 +3530,13 @@
#ifdef DEBUGMSG
printk(KERN_INFO "%s: %s() netif_"
"rx(skb) completed \n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
#endif
}
else {
privptr->stats.rx_dropped++;
printk(KERN_WARNING "%s: %s() low on memory\n",
- dev->name,__FUNCTION__);
+ dev->name,__func__);
}
privptr->mtc_offset=0;
privptr->mtc_logical_link=-1;
@@ -3575,10 +3575,10 @@
#ifdef IOTRACE
printk(KERN_INFO "%s:%s processed frame is %d \n",
- dev->name,__FUNCTION__,i);
+ dev->name,__func__,i);
printk(KERN_INFO "%s:%s F:%lx L:%lx\n",
dev->name,
- __FUNCTION__,
+ __func__,
(unsigned long)p_first_ccw,
(unsigned long)p_last_ccw);
#endif
@@ -3588,7 +3588,7 @@
claw_strt_read(dev, LOCK_YES);
#ifdef FUNCTRACE
printk(KERN_INFO "%s: %s exit on line %d\n",
- dev->name, __FUNCTION__, __LINE__);
+ dev->name, __func__, __LINE__);
#endif
return;
} /* end of unpack_read */
@@ -3610,7 +3610,7 @@
p_ch=&privptr->channel[READ];
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
printk(KERN_INFO "%s: variable lock = %d, dev =\n",dev->name, lock);
dumpit((char *) dev, sizeof(struct net_device));
#endif
@@ -3626,7 +3626,7 @@
}
#ifdef DEBUGMSG
printk(KERN_INFO "%s:%s state-%02x\n" ,
- dev->name,__FUNCTION__, p_ch->claw_state);
+ dev->name,__func__, p_ch->claw_state);
#endif
if (lock==LOCK_YES) {
spin_lock_irqsave(get_ccwdev_lock(p_ch->cdev), saveflags);
@@ -3634,7 +3634,7 @@
if (test_and_set_bit(0, (void *)&p_ch->IO_active) == 0) {
#ifdef DEBUGMSG
printk(KERN_INFO "%s: HOT READ started in %s\n" ,
- dev->name,__FUNCTION__);
+ dev->name,__func__);
p_clawh=(struct clawh *)privptr->p_claw_signal_blk;
dumpit((char *)&p_clawh->flag , 1);
#endif
@@ -3650,7 +3650,7 @@
else {
#ifdef DEBUGMSG
printk(KERN_INFO "%s: No READ started by %s() In progress\n" ,
- dev->name,__FUNCTION__);
+ dev->name,__func__);
#endif
CLAW_DBF_TEXT(2,trace,"ReadAct");
}
@@ -3660,7 +3660,7 @@
}
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
CLAW_DBF_TEXT(4,trace,"StRdExit");
return;
@@ -3681,7 +3681,7 @@
struct ccwbk *p_first_ccw;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
#endif
if (!dev) {
return;
@@ -3691,7 +3691,7 @@
#ifdef DEBUGMSG
printk(KERN_INFO "%s:%s state-%02x\n" ,
- dev->name,__FUNCTION__,p_ch->claw_state);
+ dev->name,__func__,p_ch->claw_state);
#endif
CLAW_DBF_TEXT(4,trace,"strt_io");
p_first_ccw=privptr->p_write_active_first;
@@ -3701,14 +3701,14 @@
if (p_first_ccw == NULL) {
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
return;
}
if (test_and_set_bit(0, (void *)&p_ch->IO_active) == 0) {
parm = (unsigned long) p_ch;
#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s do_io \n" ,dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s do_io \n" ,dev->name,__func__);
dumpit((char *)p_first_ccw, sizeof(struct ccwbk));
#endif
CLAW_DBF_TEXT(2,trace,"StWrtIO");
@@ -3721,7 +3721,7 @@
dev->trans_start = jiffies;
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__FUNCTION__,__LINE__);
+ dev->name,__func__,__LINE__);
#endif
return;
@@ -3745,7 +3745,7 @@
struct ccwbk*p_buf;
#endif
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
printk(KERN_INFO "%s: free count = %d variable dev =\n",
dev->name,privptr->write_free_count);
#endif
@@ -3798,7 +3798,7 @@
privptr->p_write_active_last=NULL;
#ifdef DEBUGMSG
printk(KERN_INFO "%s:%s p_write_"
- "active_first==NULL\n",dev->name,__FUNCTION__);
+ "active_first==NULL\n",dev->name,__func__);
#endif
}
#ifdef IOTRACE
@@ -3819,7 +3819,7 @@
CLAW_DBF_TEXT_(4,trace,"FWC=%d",privptr->write_free_count);
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d free_count =%d\n",
- dev->name,__FUNCTION__, __LINE__,privptr->write_free_count);
+ dev->name,__func__, __LINE__,privptr->write_free_count);
#endif
return;
}
@@ -3833,7 +3833,7 @@
{
struct claw_privbk *privptr;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
#endif
CLAW_DBF_TEXT(2,setup,"free_dev");
@@ -3854,7 +3854,7 @@
#endif
CLAW_DBF_TEXT(2,setup,"feee_ok");
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit\n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Exit\n",dev->name,__func__);
#endif
}
@@ -3867,13 +3867,13 @@
claw_init_netdevice(struct net_device * dev)
{
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
#endif
CLAW_DBF_TEXT(2,setup,"init_dev");
CLAW_DBF_TEXT_(2,setup,"%s",dev->name);
if (!dev) {
printk(KERN_WARNING "claw:%s BAD Device exit line %d\n",
- __FUNCTION__,__LINE__);
+ __func__,__LINE__);
CLAW_DBF_TEXT(2,setup,"baddev");
return;
}
@@ -3889,7 +3889,7 @@
dev->tx_queue_len = 1300;
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit\n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Exit\n",dev->name,__func__);
#endif
CLAW_DBF_TEXT(2,setup,"initok");
return;
@@ -3909,7 +3909,7 @@
struct ccw_dev_id dev_id;
#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",cdev->dev.bus_id,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Enter\n",cdev->dev.bus_id,__func__);
#endif
CLAW_DBF_TEXT_(2,setup,"%s",cdev->dev.bus_id);
privptr->channel[i].flag = i+1; /* Read is 1 Write is 2 */
@@ -3920,16 +3920,16 @@
p_ch->devno = dev_id.devno;
if ((p_ch->irb = kzalloc(sizeof (struct irb),GFP_KERNEL)) == NULL) {
printk(KERN_WARNING "%s Out of memory in %s for irb\n",
- p_ch->id,__FUNCTION__);
+ p_ch->id,__func__);
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- p_ch->id,__FUNCTION__,__LINE__);
+ p_ch->id,__func__,__LINE__);
#endif
return -ENOMEM;
}
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Exit on line %d\n",
- cdev->dev.bus_id,__FUNCTION__,__LINE__);
+ cdev->dev.bus_id,__func__,__LINE__);
#endif
return 0;
}
@@ -3952,7 +3952,7 @@
int ret;
struct ccw_dev_id dev_id;
- pr_debug("%s() called\n", __FUNCTION__);
+ pr_debug("%s() called\n", __func__);
printk(KERN_INFO "claw: add for %s\n",cgdev->cdev[READ]->dev.bus_id);
CLAW_DBF_TEXT(2,setup,"new_dev");
privptr = cgdev->dev.driver_data;
@@ -3990,7 +3990,7 @@
}
dev = alloc_netdev(0,"claw%d",claw_init_netdevice);
if (!dev) {
- printk(KERN_WARNING "%s:alloc_netdev failed\n",__FUNCTION__);
+ printk(KERN_WARNING "%s:alloc_netdev failed\n",__func__);
goto out;
}
dev->priv = privptr;
@@ -4065,7 +4065,7 @@
struct net_device *ndev;
int ret;
- pr_debug("%s() called\n", __FUNCTION__);
+ pr_debug("%s() called\n", __func__);
CLAW_DBF_TEXT_(2,setup,"%s",cgdev->dev.bus_id);
priv = cgdev->dev.driver_data;
if (!priv)
@@ -4095,15 +4095,15 @@
{
struct claw_privbk *priv;
- pr_debug("%s() called\n", __FUNCTION__);
+ pr_debug("%s() called\n", __func__);
CLAW_DBF_TEXT_(2,setup,"%s",cgdev->dev.bus_id);
priv = cgdev->dev.driver_data;
if (!priv) {
- printk(KERN_WARNING "claw: %s() no Priv exiting\n",__FUNCTION__);
+ printk(KERN_WARNING "claw: %s() no Priv exiting\n",__func__);
return;
}
printk(KERN_INFO "claw: %s() called %s will be removed.\n",
- __FUNCTION__,cgdev->cdev[0]->dev.bus_id);
+ __func__,cgdev->cdev[0]->dev.bus_id);
if (cgdev->state == CCWGROUP_ONLINE)
claw_shutdown_device(cgdev);
claw_remove_files(&cgdev->dev);
@@ -4346,7 +4346,7 @@
static int
claw_add_files(struct device *dev)
{
- pr_debug("%s() called\n", __FUNCTION__);
+ pr_debug("%s() called\n", __func__);
CLAW_DBF_TEXT(2,setup,"add_file");
return sysfs_create_group(&dev->kobj, &claw_attr_group);
}
@@ -4354,7 +4354,7 @@
static void
claw_remove_files(struct device *dev)
{
- pr_debug("%s() called\n", __FUNCTION__);
+ pr_debug("%s() called\n", __func__);
CLAW_DBF_TEXT(2,setup,"rem_file");
sysfs_remove_group(&dev->kobj, &claw_attr_group);
}
@@ -4385,12 +4385,12 @@
printk(KERN_INFO "claw: starting driver\n");
#ifdef FUNCTRACE
- printk(KERN_INFO "claw: %s() enter \n",__FUNCTION__);
+ printk(KERN_INFO "claw: %s() enter \n",__func__);
#endif
ret = claw_register_debug_facility();
if (ret) {
printk(KERN_WARNING "claw: %s() debug_register failed %d\n",
- __FUNCTION__,ret);
+ __func__,ret);
return ret;
}
CLAW_DBF_TEXT(2,setup,"init_mod");
@@ -4398,10 +4398,10 @@
if (ret) {
claw_unregister_debug_facility();
printk(KERN_WARNING "claw; %s() cu3088 register failed %d\n",
- __FUNCTION__,ret);
+ __func__,ret);
}
#ifdef FUNCTRACE
- printk(KERN_INFO "claw: %s() exit \n",__FUNCTION__);
+ printk(KERN_INFO "claw: %s() exit \n",__func__);
#endif
return ret;
}
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 874a199..8f876f6 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -670,7 +670,7 @@
struct netiucv_priv *privptr = netdev_priv(conn->netdev);
int rc;
- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 4, __func__);
if (!conn->netdev) {
iucv_message_reject(conn->path, msg);
@@ -718,7 +718,7 @@
struct ll_header header;
int rc;
- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 4, __func__);
if (conn && conn->netdev)
privptr = netdev_priv(conn->netdev);
@@ -799,7 +799,7 @@
struct netiucv_priv *privptr = netdev_priv(netdev);
int rc;
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
conn->path = path;
path->msglim = NETIUCV_QUEUELEN_DEFAULT;
@@ -821,7 +821,7 @@
struct iucv_event *ev = arg;
struct iucv_path *path = ev->data;
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
iucv_path_sever(path, NULL);
}
@@ -831,7 +831,7 @@
struct net_device *netdev = conn->netdev;
struct netiucv_priv *privptr = netdev_priv(netdev);
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
fsm_deltimer(&conn->timer);
fsm_newstate(fi, CONN_STATE_IDLE);
netdev->tx_queue_len = conn->path->msglim;
@@ -842,7 +842,7 @@
{
struct iucv_connection *conn = arg;
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
fsm_deltimer(&conn->timer);
iucv_path_sever(conn->path, NULL);
fsm_newstate(fi, CONN_STATE_STARTWAIT);
@@ -854,7 +854,7 @@
struct net_device *netdev = conn->netdev;
struct netiucv_priv *privptr = netdev_priv(netdev);
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
fsm_deltimer(&conn->timer);
iucv_path_sever(conn->path, NULL);
@@ -870,7 +870,7 @@
struct iucv_connection *conn = arg;
int rc;
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
fsm_newstate(fi, CONN_STATE_STARTWAIT);
PRINT_DEBUG("%s('%s'): connecting ...\n",
@@ -948,7 +948,7 @@
struct net_device *netdev = conn->netdev;
struct netiucv_priv *privptr = netdev_priv(netdev);
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
fsm_deltimer(&conn->timer);
fsm_newstate(fi, CONN_STATE_STOPPED);
@@ -1024,7 +1024,7 @@
struct net_device *dev = arg;
struct netiucv_priv *privptr = netdev_priv(dev);
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
fsm_newstate(fi, DEV_STATE_STARTWAIT);
fsm_event(privptr->conn->fsm, CONN_EVENT_START, privptr->conn);
@@ -1044,7 +1044,7 @@
struct netiucv_priv *privptr = netdev_priv(dev);
struct iucv_event ev;
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
ev.conn = privptr->conn;
@@ -1066,7 +1066,7 @@
struct net_device *dev = arg;
struct netiucv_priv *privptr = netdev_priv(dev);
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
switch (fsm_getstate(fi)) {
case DEV_STATE_STARTWAIT:
@@ -1097,7 +1097,7 @@
static void
dev_action_conndown(fsm_instance *fi, int event, void *arg)
{
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
switch (fsm_getstate(fi)) {
case DEV_STATE_RUNNING:
@@ -1288,7 +1288,7 @@
struct netiucv_priv *privptr = netdev_priv(dev);
int rc;
- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 4, __func__);
/**
* Some sanity checks ...
*/
@@ -1344,7 +1344,7 @@
{
struct netiucv_priv *priv = netdev_priv(dev);
- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 5, __func__);
return &priv->stats;
}
@@ -1360,7 +1360,7 @@
*/
static int netiucv_change_mtu(struct net_device * dev, int new_mtu)
{
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
if (new_mtu < 576 || new_mtu > NETIUCV_MTU_MAX) {
IUCV_DBF_TEXT(setup, 2, "given MTU out of valid range\n");
return -EINVAL;
@@ -1378,7 +1378,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 5, __func__);
return sprintf(buf, "%s\n", netiucv_printname(priv->conn->userid));
}
@@ -1393,7 +1393,7 @@
int i;
struct iucv_connection *cp;
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
if (count > 9) {
PRINT_WARN("netiucv: username too long (%d)!\n", (int) count);
IUCV_DBF_TEXT_(setup, 2,
@@ -1449,7 +1449,7 @@
char *buf)
{ struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 5, __func__);
return sprintf(buf, "%d\n", priv->conn->max_buffsize);
}
@@ -1461,7 +1461,7 @@
char *e;
int bs1;
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
if (count >= 39)
return -EINVAL;
@@ -1513,7 +1513,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 5, __func__);
return sprintf(buf, "%s\n", fsm_getstate_str(priv->fsm));
}
@@ -1524,7 +1524,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 5, __func__);
return sprintf(buf, "%s\n", fsm_getstate_str(priv->conn->fsm));
}
@@ -1535,7 +1535,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 5, __func__);
return sprintf(buf, "%ld\n", priv->conn->prof.maxmulti);
}
@@ -1545,7 +1545,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 4, __func__);
priv->conn->prof.maxmulti = 0;
return count;
}
@@ -1557,7 +1557,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 5, __func__);
return sprintf(buf, "%ld\n", priv->conn->prof.maxcqueue);
}
@@ -1566,7 +1566,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 4, __func__);
priv->conn->prof.maxcqueue = 0;
return count;
}
@@ -1578,7 +1578,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 5, __func__);
return sprintf(buf, "%ld\n", priv->conn->prof.doios_single);
}
@@ -1587,7 +1587,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 4, __func__);
priv->conn->prof.doios_single = 0;
return count;
}
@@ -1599,7 +1599,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 5, __func__);
return sprintf(buf, "%ld\n", priv->conn->prof.doios_multi);
}
@@ -1608,7 +1608,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 5, __func__);
priv->conn->prof.doios_multi = 0;
return count;
}
@@ -1620,7 +1620,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 5, __func__);
return sprintf(buf, "%ld\n", priv->conn->prof.txlen);
}
@@ -1629,7 +1629,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 4, __func__);
priv->conn->prof.txlen = 0;
return count;
}
@@ -1641,7 +1641,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 5, __func__);
return sprintf(buf, "%ld\n", priv->conn->prof.tx_time);
}
@@ -1650,7 +1650,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 4, __func__);
priv->conn->prof.tx_time = 0;
return count;
}
@@ -1662,7 +1662,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 5, __func__);
return sprintf(buf, "%ld\n", priv->conn->prof.tx_pending);
}
@@ -1671,7 +1671,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 4, __func__);
priv->conn->prof.tx_pending = 0;
return count;
}
@@ -1683,7 +1683,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 5, __func__);
return sprintf(buf, "%ld\n", priv->conn->prof.tx_max_pending);
}
@@ -1692,7 +1692,7 @@
{
struct netiucv_priv *priv = dev->driver_data;
- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 4, __func__);
priv->conn->prof.tx_max_pending = 0;
return count;
}
@@ -1732,7 +1732,7 @@
{
int ret;
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
ret = sysfs_create_group(&dev->kobj, &netiucv_attr_group);
if (ret)
return ret;
@@ -1744,7 +1744,7 @@
static void netiucv_remove_files(struct device *dev)
{
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
sysfs_remove_group(&dev->kobj, &netiucv_stat_attr_group);
sysfs_remove_group(&dev->kobj, &netiucv_attr_group);
}
@@ -1756,7 +1756,7 @@
int ret;
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
if (dev) {
snprintf(dev->bus_id, BUS_ID_SIZE, "net%s", ndev->name);
@@ -1792,7 +1792,7 @@
static void netiucv_unregister_device(struct device *dev)
{
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
netiucv_remove_files(dev);
device_unregister(dev);
}
@@ -1857,7 +1857,7 @@
*/
static void netiucv_remove_connection(struct iucv_connection *conn)
{
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
write_lock_bh(&iucv_connection_rwlock);
list_del_init(&conn->list);
write_unlock_bh(&iucv_connection_rwlock);
@@ -1881,7 +1881,7 @@
{
struct netiucv_priv *privptr = netdev_priv(dev);
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
if (!dev)
return;
@@ -1963,7 +1963,7 @@
struct netiucv_priv *priv;
struct iucv_connection *cp;
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
if (count>9) {
PRINT_WARN("netiucv: username too long (%d)!\n", (int)count);
IUCV_DBF_TEXT(setup, 2, "conn_write: too long\n");
@@ -2048,7 +2048,7 @@
const char *p;
int i;
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
if (count >= IFNAMSIZ)
count = IFNAMSIZ - 1;;
@@ -2116,7 +2116,7 @@
struct netiucv_priv *priv;
struct device *dev;
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+ IUCV_DBF_TEXT(trace, 3, __func__);
while (!list_empty(&iucv_connection_list)) {
cp = list_entry(iucv_connection_list.next,
struct iucv_connection, list);
@@ -2146,8 +2146,7 @@
rc = iucv_register(&netiucv_handler, 1);
if (rc)
goto out_dbf;
- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
- netiucv_driver.groups = netiucv_drv_attr_groups;
+ IUCV_DBF_TEXT(trace, 3, __func__);
rc = driver_register(&netiucv_driver);
if (rc) {
PRINT_ERR("NETIUCV: failed to register driver.\n");
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index 644a06e..4d4b542 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -59,15 +59,15 @@
printk(KERN_WARNING"%s: Code does not support more "
"than two chained crws; please report to "
- "linux390@de.ibm.com!\n", __FUNCTION__);
+ "linux390@de.ibm.com!\n", __func__);
ccode = stcrw(&tmp_crw);
printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, "
"chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
- __FUNCTION__, tmp_crw.slct, tmp_crw.oflw,
+ __func__, tmp_crw.slct, tmp_crw.oflw,
tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc,
tmp_crw.erc, tmp_crw.rsid);
printk(KERN_WARNING"%s: This was crw number %x in the "
- "chain\n", __FUNCTION__, chain);
+ "chain\n", __func__, chain);
if (ccode != 0)
break;
chain = tmp_crw.chn ? chain + 1 : 0;
@@ -83,7 +83,7 @@
crw[chain].rsid);
/* Check for overflows. */
if (crw[chain].oflw) {
- pr_debug("%s: crw overflow detected!\n", __FUNCTION__);
+ pr_debug("%s: crw overflow detected!\n", __func__);
css_schedule_eval_all();
chain = 0;
continue;
diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h
index d3ca428..ca681f9 100644
--- a/drivers/s390/s390mach.h
+++ b/drivers/s390/s390mach.h
@@ -105,4 +105,8 @@
#define ED_ETR_SYNC 12 /* External damage ETR sync check */
#define ED_ETR_SWITCH 13 /* External damage ETR switch to local */
+struct pt_regs;
+
+void s390_handle_mcck(void);
+void s390_do_machine_check(struct pt_regs *regs);
#endif /* __s390mach */
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 9e9f6c1..45a7cd9 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -539,7 +539,7 @@
/* logging routine for zfcp */
#define _ZFCP_LOG(fmt, args...) \
- printk(KERN_ERR ZFCP_NAME": %s(%d): " fmt, __FUNCTION__, \
+ printk(KERN_ERR ZFCP_NAME": %s(%d): " fmt, __func__, \
__LINE__ , ##args)
#define ZFCP_LOG(level, fmt, args...) \
diff --git a/drivers/s390/sysinfo.c b/drivers/s390/sysinfo.c
index 291ff62..c3e4ab0 100644
--- a/drivers/s390/sysinfo.c
+++ b/drivers/s390/sysinfo.c
@@ -11,111 +11,13 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/ebcdic.h>
+#include <asm/sysinfo.h>
/* Sigh, math-emu. Don't ask. */
#include <asm/sfp-util.h>
#include <math-emu/soft-fp.h>
#include <math-emu/single.h>
-struct sysinfo_1_1_1 {
- char reserved_0[32];
- char manufacturer[16];
- char type[4];
- char reserved_1[12];
- char model_capacity[16];
- char sequence[16];
- char plant[4];
- char model[16];
-};
-
-struct sysinfo_1_2_1 {
- char reserved_0[80];
- char sequence[16];
- char plant[4];
- char reserved_1[2];
- unsigned short cpu_address;
-};
-
-struct sysinfo_1_2_2 {
- char format;
- char reserved_0[1];
- unsigned short acc_offset;
- char reserved_1[24];
- unsigned int secondary_capability;
- unsigned int capability;
- unsigned short cpus_total;
- unsigned short cpus_configured;
- unsigned short cpus_standby;
- unsigned short cpus_reserved;
- unsigned short adjustment[0];
-};
-
-struct sysinfo_1_2_2_extension {
- unsigned int alt_capability;
- unsigned short alt_adjustment[0];
-};
-
-struct sysinfo_2_2_1 {
- char reserved_0[80];
- char sequence[16];
- char plant[4];
- unsigned short cpu_id;
- unsigned short cpu_address;
-};
-
-struct sysinfo_2_2_2 {
- char reserved_0[32];
- unsigned short lpar_number;
- char reserved_1;
- unsigned char characteristics;
- unsigned short cpus_total;
- unsigned short cpus_configured;
- unsigned short cpus_standby;
- unsigned short cpus_reserved;
- char name[8];
- unsigned int caf;
- char reserved_2[16];
- unsigned short cpus_dedicated;
- unsigned short cpus_shared;
-};
-
-#define LPAR_CHAR_DEDICATED (1 << 7)
-#define LPAR_CHAR_SHARED (1 << 6)
-#define LPAR_CHAR_LIMITED (1 << 5)
-
-struct sysinfo_3_2_2 {
- char reserved_0[31];
- unsigned char count;
- struct {
- char reserved_0[4];
- unsigned short cpus_total;
- unsigned short cpus_configured;
- unsigned short cpus_standby;
- unsigned short cpus_reserved;
- char name[8];
- unsigned int caf;
- char cpi[16];
- char reserved_1[24];
-
- } vm[8];
-};
-
-static inline int stsi(void *sysinfo, int fc, int sel1, int sel2)
-{
- register int r0 asm("0") = (fc << 28) | sel1;
- register int r1 asm("1") = sel2;
-
- asm volatile(
- " stsi 0(%2)\n"
- "0: jz 2f\n"
- "1: lhi %0,%3\n"
- "2:\n"
- EX_TABLE(0b,1b)
- : "+d" (r0) : "d" (r1), "a" (sysinfo), "K" (-ENOSYS)
- : "cc", "memory" );
- return r0;
-}
-
static inline int stsi_0(void)
{
int rc = stsi (NULL, 0, 0, 0);
@@ -133,6 +35,8 @@
EBCASC(info->sequence, sizeof(info->sequence));
EBCASC(info->plant, sizeof(info->plant));
EBCASC(info->model_capacity, sizeof(info->model_capacity));
+ EBCASC(info->model_perm_cap, sizeof(info->model_perm_cap));
+ EBCASC(info->model_temp_cap, sizeof(info->model_temp_cap));
len += sprintf(page + len, "Manufacturer: %-16.16s\n",
info->manufacturer);
len += sprintf(page + len, "Type: %-4.4s\n",
@@ -155,8 +59,18 @@
info->sequence);
len += sprintf(page + len, "Plant: %-4.4s\n",
info->plant);
- len += sprintf(page + len, "Model Capacity: %-16.16s\n",
- info->model_capacity);
+ len += sprintf(page + len, "Model Capacity: %-16.16s %08u\n",
+ info->model_capacity, *(u32 *) info->model_cap_rating);
+ if (info->model_perm_cap[0] != '\0')
+ len += sprintf(page + len,
+ "Model Perm. Capacity: %-16.16s %08u\n",
+ info->model_perm_cap,
+ *(u32 *) info->model_perm_cap_rating);
+ if (info->model_temp_cap[0] != '\0')
+ len += sprintf(page + len,
+ "Model Temp. Capacity: %-16.16s %08u\n",
+ info->model_temp_cap,
+ *(u32 *) info->model_temp_cap_rating);
return len;
}
diff --git a/include/asm-s390/cio.h b/include/asm-s390/cio.h
index 123b557..0818ecd 100644
--- a/include/asm-s390/cio.h
+++ b/include/asm-s390/cio.h
@@ -397,6 +397,10 @@
extern int cio_get_iplinfo(struct cio_iplinfo *iplinfo);
+/* Function from drivers/s390/cio/chsc.c */
+int chsc_sstpc(void *page, unsigned int op, u16 ctrl);
+int chsc_sstpi(void *page, void *result, size_t size);
+
#endif
#endif
diff --git a/include/asm-s390/cpu.h b/include/asm-s390/cpu.h
index 352dde1..e5a6a9b 100644
--- a/include/asm-s390/cpu.h
+++ b/include/asm-s390/cpu.h
@@ -22,4 +22,12 @@
DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
+void s390_idle_leave(void);
+
+static inline void s390_idle_check(void)
+{
+ if ((&__get_cpu_var(s390_idle))->in_idle)
+ s390_idle_leave();
+}
+
#endif /* _ASM_S390_CPU_H_ */
diff --git a/include/asm-s390/debug.h b/include/asm-s390/debug.h
index c00dd2b..335baf4 100644
--- a/include/asm-s390/debug.h
+++ b/include/asm-s390/debug.h
@@ -73,6 +73,7 @@
struct dentry* debugfs_entries[DEBUG_MAX_VIEWS];
struct debug_view* views[DEBUG_MAX_VIEWS];
char name[DEBUG_MAX_NAME_LEN];
+ mode_t mode;
} debug_info_t;
typedef int (debug_header_proc_t) (debug_info_t* id,
@@ -122,6 +123,10 @@
debug_info_t* debug_register(char* name, int pages, int nr_areas,
int buf_size);
+debug_info_t *debug_register_mode(char *name, int pages, int nr_areas,
+ int buf_size, mode_t mode, uid_t uid,
+ gid_t gid);
+
void debug_unregister(debug_info_t* id);
void debug_set_level(debug_info_t* id, int new_level);
diff --git a/include/asm-s390/extmem.h b/include/asm-s390/extmem.h
index c8802c9..33837d7 100644
--- a/include/asm-s390/extmem.h
+++ b/include/asm-s390/extmem.h
@@ -22,11 +22,12 @@
#define SEGMENT_SHARED 0
#define SEGMENT_EXCLUSIVE 1
-extern int segment_load (char *name,int segtype,unsigned long *addr,unsigned long *length);
-extern void segment_unload(char *name);
-extern void segment_save(char *name);
-extern int segment_type (char* name);
-extern int segment_modify_shared (char *name, int do_nonshared);
+int segment_load (char *name, int segtype, unsigned long *addr, unsigned long *length);
+void segment_unload(char *name);
+void segment_save(char *name);
+int segment_type (char* name);
+int segment_modify_shared (char *name, int do_nonshared);
+void segment_warning(int rc, char *seg_name);
#endif
#endif
diff --git a/include/asm-s390/hardirq.h b/include/asm-s390/hardirq.h
index 31beb18..4b7cb96 100644
--- a/include/asm-s390/hardirq.h
+++ b/include/asm-s390/hardirq.h
@@ -32,6 +32,6 @@
#define HARDIRQ_BITS 8
-extern void account_ticks(u64 time);
+void clock_comparator_work(void);
#endif /* __ASM_HARDIRQ_H */
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
index 801a6fd..5de3efb 100644
--- a/include/asm-s390/lowcore.h
+++ b/include/asm-s390/lowcore.h
@@ -56,6 +56,8 @@
#define __LC_IO_INT_WORD 0x0C0
#define __LC_MCCK_CODE 0x0E8
+#define __LC_LAST_BREAK 0x110
+
#define __LC_RETURN_PSW 0x200
#define __LC_SAVE_AREA 0xC00
@@ -80,7 +82,6 @@
#define __LC_CPUID 0xC60
#define __LC_CPUADDR 0xC68
#define __LC_IPLDEV 0xC7C
-#define __LC_JIFFY_TIMER 0xC80
#define __LC_CURRENT 0xC90
#define __LC_INT_CLOCK 0xC98
#else /* __s390x__ */
@@ -103,7 +104,6 @@
#define __LC_CPUID 0xD80
#define __LC_CPUADDR 0xD88
#define __LC_IPLDEV 0xDB8
-#define __LC_JIFFY_TIMER 0xDC0
#define __LC_CURRENT 0xDD8
#define __LC_INT_CLOCK 0xDE8
#endif /* __s390x__ */
@@ -276,7 +276,7 @@
/* entry.S sensitive area end */
/* SMP info area: defined by DJB */
- __u64 jiffy_timer; /* 0xc80 */
+ __u64 clock_comparator; /* 0xc80 */
__u32 ext_call_fast; /* 0xc88 */
__u32 percpu_offset; /* 0xc8c */
__u32 current_task; /* 0xc90 */
@@ -368,11 +368,12 @@
/* entry.S sensitive area end */
/* SMP info area: defined by DJB */
- __u64 jiffy_timer; /* 0xdc0 */
+ __u64 clock_comparator; /* 0xdc0 */
__u64 ext_call_fast; /* 0xdc8 */
__u64 percpu_offset; /* 0xdd0 */
__u64 current_task; /* 0xdd8 */
- __u64 softirq_pending; /* 0xde0 */
+ __u32 softirq_pending; /* 0xde0 */
+ __u32 pad_0x0de4; /* 0xde4 */
__u64 int_clock; /* 0xde8 */
__u8 pad12[0xe00-0xdf0]; /* 0xdf0 */
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index 51d8891..8eaf343 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -175,6 +175,13 @@
extern void show_registers(struct pt_regs *regs);
extern void show_code(struct pt_regs *regs);
extern void show_trace(struct task_struct *task, unsigned long *sp);
+#ifdef CONFIG_64BIT
+extern void show_last_breaking_event(struct pt_regs *regs);
+#else
+static inline void show_last_breaking_event(struct pt_regs *regs)
+{
+}
+#endif
unsigned long get_wchan(struct task_struct *p);
#define task_pt_regs(tsk) ((struct pt_regs *) \
diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h
index c7b7432..6f3821a 100644
--- a/include/asm-s390/smp.h
+++ b/include/asm-s390/smp.h
@@ -90,6 +90,9 @@
extern void cpu_die (void) __attribute__ ((noreturn));
extern int __cpu_up (unsigned int cpu);
+extern struct mutex smp_cpu_state_mutex;
+extern int smp_cpu_polarization[];
+
extern int smp_call_function_mask(cpumask_t mask, void (*func)(void *),
void *info, int wait);
#endif
diff --git a/include/asm-s390/sysinfo.h b/include/asm-s390/sysinfo.h
new file mode 100644
index 0000000..abe10ae
--- /dev/null
+++ b/include/asm-s390/sysinfo.h
@@ -0,0 +1,116 @@
+/*
+ * definition for store system information stsi
+ *
+ * Copyright IBM Corp. 2001,2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ * Author(s): Ulrich Weigand <weigand@de.ibm.com>
+ * Christian Borntraeger <borntraeger@de.ibm.com>
+ */
+
+struct sysinfo_1_1_1 {
+ char reserved_0[32];
+ char manufacturer[16];
+ char type[4];
+ char reserved_1[12];
+ char model_capacity[16];
+ char sequence[16];
+ char plant[4];
+ char model[16];
+ char model_perm_cap[16];
+ char model_temp_cap[16];
+ char model_cap_rating[4];
+ char model_perm_cap_rating[4];
+ char model_temp_cap_rating[4];
+};
+
+struct sysinfo_1_2_1 {
+ char reserved_0[80];
+ char sequence[16];
+ char plant[4];
+ char reserved_1[2];
+ unsigned short cpu_address;
+};
+
+struct sysinfo_1_2_2 {
+ char format;
+ char reserved_0[1];
+ unsigned short acc_offset;
+ char reserved_1[24];
+ unsigned int secondary_capability;
+ unsigned int capability;
+ unsigned short cpus_total;
+ unsigned short cpus_configured;
+ unsigned short cpus_standby;
+ unsigned short cpus_reserved;
+ unsigned short adjustment[0];
+};
+
+struct sysinfo_1_2_2_extension {
+ unsigned int alt_capability;
+ unsigned short alt_adjustment[0];
+};
+
+struct sysinfo_2_2_1 {
+ char reserved_0[80];
+ char sequence[16];
+ char plant[4];
+ unsigned short cpu_id;
+ unsigned short cpu_address;
+};
+
+struct sysinfo_2_2_2 {
+ char reserved_0[32];
+ unsigned short lpar_number;
+ char reserved_1;
+ unsigned char characteristics;
+ unsigned short cpus_total;
+ unsigned short cpus_configured;
+ unsigned short cpus_standby;
+ unsigned short cpus_reserved;
+ char name[8];
+ unsigned int caf;
+ char reserved_2[16];
+ unsigned short cpus_dedicated;
+ unsigned short cpus_shared;
+};
+
+#define LPAR_CHAR_DEDICATED (1 << 7)
+#define LPAR_CHAR_SHARED (1 << 6)
+#define LPAR_CHAR_LIMITED (1 << 5)
+
+struct sysinfo_3_2_2 {
+ char reserved_0[31];
+ unsigned char count;
+ struct {
+ char reserved_0[4];
+ unsigned short cpus_total;
+ unsigned short cpus_configured;
+ unsigned short cpus_standby;
+ unsigned short cpus_reserved;
+ char name[8];
+ unsigned int caf;
+ char cpi[16];
+ char reserved_1[24];
+
+ } vm[8];
+};
+
+static inline int stsi(void *sysinfo, int fc, int sel1, int sel2)
+{
+ register int r0 asm("0") = (fc << 28) | sel1;
+ register int r1 asm("1") = sel2;
+
+ asm volatile(
+ " stsi 0(%2)\n"
+ "0: jz 2f\n"
+ "1: lhi %0,%3\n"
+ "2:\n"
+ EX_TABLE(0b, 1b)
+ : "+d" (r0) : "d" (r1), "a" (sysinfo), "K" (-ENOSYS)
+ : "cc", "memory");
+ return r0;
+}
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
index 15aba30..92098df 100644
--- a/include/asm-s390/system.h
+++ b/include/asm-s390/system.h
@@ -406,6 +406,8 @@
#define local_mcck_enable() __set_psw_mask(psw_kernel_bits)
#define local_mcck_disable() __set_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK)
+int stfle(unsigned long long *list, int doublewords);
+
#ifdef CONFIG_SMP
extern void smp_ctl_set_bit(int cr, int bit);
diff --git a/include/asm-s390/timex.h b/include/asm-s390/timex.h
index 98229db..d744c3d 100644
--- a/include/asm-s390/timex.h
+++ b/include/asm-s390/timex.h
@@ -62,16 +62,18 @@
return clk;
}
-static inline void get_clock_extended(void *dest)
+static inline unsigned long long get_clock_xt(void)
{
- typedef struct { unsigned long long clk[2]; } __clock_t;
+ unsigned char clk[16];
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
- asm volatile("stcke %0" : "=Q" (*((__clock_t *)dest)) : : "cc");
+ asm volatile("stcke %0" : "=Q" (clk) : : "cc");
#else /* __GNUC__ */
- asm volatile("stcke 0(%1)" : "=m" (*((__clock_t *)dest))
- : "a" ((__clock_t *)dest) : "cc");
+ asm volatile("stcke 0(%1)" : "=m" (clk)
+ : "a" (clk) : "cc");
#endif /* __GNUC__ */
+
+ return *((unsigned long long *)&clk[1]);
}
static inline cycles_t get_cycles(void)
@@ -81,5 +83,6 @@
int get_sync_clock(unsigned long long *clock);
void init_cpu_timer(void);
+unsigned long long monotonic_clock(void);
#endif
diff --git a/include/asm-s390/tlbflush.h b/include/asm-s390/tlbflush.h
index 35fb4f9..9e57a93 100644
--- a/include/asm-s390/tlbflush.h
+++ b/include/asm-s390/tlbflush.h
@@ -13,12 +13,14 @@
asm volatile("ptlb" : : : "memory");
}
+#ifdef CONFIG_SMP
/*
* Flush all tlb entries on all cpus.
*/
+void smp_ptlb_all(void);
+
static inline void __tlb_flush_global(void)
{
- extern void smp_ptlb_all(void);
register unsigned long reg2 asm("2");
register unsigned long reg3 asm("3");
register unsigned long reg4 asm("4");
@@ -39,6 +41,25 @@
: : "d" (reg2), "d" (reg3), "d" (reg4), "m" (dummy) : "cc" );
}
+static inline void __tlb_flush_full(struct mm_struct *mm)
+{
+ cpumask_t local_cpumask;
+
+ preempt_disable();
+ /*
+ * If the process only ran on the local cpu, do a local flush.
+ */
+ local_cpumask = cpumask_of_cpu(smp_processor_id());
+ if (cpus_equal(mm->cpu_vm_mask, local_cpumask))
+ __tlb_flush_local();
+ else
+ __tlb_flush_global();
+ preempt_enable();
+}
+#else
+#define __tlb_flush_full(mm) __tlb_flush_local()
+#endif
+
/*
* Flush all tlb entries of a page table on all cpus.
*/
@@ -51,8 +72,6 @@
static inline void __tlb_flush_mm(struct mm_struct * mm)
{
- cpumask_t local_cpumask;
-
if (unlikely(cpus_empty(mm->cpu_vm_mask)))
return;
/*
@@ -69,16 +88,7 @@
mm->context.asce_bits);
return;
}
- preempt_disable();
- /*
- * If the process only ran on the local cpu, do a local flush.
- */
- local_cpumask = cpumask_of_cpu(smp_processor_id());
- if (cpus_equal(mm->cpu_vm_mask, local_cpumask))
- __tlb_flush_local();
- else
- __tlb_flush_global();
- preempt_enable();
+ __tlb_flush_full(mm);
}
static inline void __tlb_flush_mm_cond(struct mm_struct * mm)
diff --git a/include/asm-s390/topology.h b/include/asm-s390/topology.h
index 613aa64..8e97b06 100644
--- a/include/asm-s390/topology.h
+++ b/include/asm-s390/topology.h
@@ -1,6 +1,29 @@
#ifndef _ASM_S390_TOPOLOGY_H
#define _ASM_S390_TOPOLOGY_H
+#include <linux/cpumask.h>
+
+#define mc_capable() (1)
+
+cpumask_t cpu_coregroup_map(unsigned int cpu);
+
+int topology_set_cpu_management(int fc);
+void topology_schedule_update(void);
+
+#define POLARIZATION_UNKNWN (-1)
+#define POLARIZATION_HRZ (0)
+#define POLARIZATION_VL (1)
+#define POLARIZATION_VM (2)
+#define POLARIZATION_VH (3)
+
+#ifdef CONFIG_SMP
+void s390_init_cpu_topology(void);
+#else
+static inline void s390_init_cpu_topology(void)
+{
+};
+#endif
+
#include <asm-generic/topology.h>
#endif /* _ASM_S390_TOPOLOGY_H */
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index f8ab4ce..b5fef13 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -102,6 +102,25 @@
extern void disable_irq(unsigned int irq);
extern void enable_irq(unsigned int irq);
+#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS)
+
+extern int irq_set_affinity(unsigned int irq, cpumask_t cpumask);
+extern int irq_can_set_affinity(unsigned int irq);
+
+#else /* CONFIG_SMP */
+
+static inline int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
+{
+ return -EINVAL;
+}
+
+static inline int irq_can_set_affinity(unsigned int irq)
+{
+ return 0;
+}
+
+#endif /* CONFIG_SMP && CONFIG_GENERIC_HARDIRQS */
+
#ifdef CONFIG_GENERIC_HARDIRQS
/*
* Special lockdep variants of irq disabling/enabling.
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 176e5e7..1883a85 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -228,21 +228,11 @@
#endif /* CONFIG_GENERIC_PENDING_IRQ */
-extern int irq_set_affinity(unsigned int irq, cpumask_t cpumask);
-extern int irq_can_set_affinity(unsigned int irq);
-
#else /* CONFIG_SMP */
#define move_native_irq(x)
#define move_masked_irq(x)
-static inline int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
-{
- return -EINVAL;
-}
-
-static inline int irq_can_set_affinity(unsigned int irq) { return 0; }
-
#endif /* CONFIG_SMP */
#ifdef CONFIG_IRQBALANCE
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index b00c1c7..79d59c9 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -45,9 +45,9 @@
struct kmem_cache_node {
spinlock_t list_lock; /* Protect partial list and nr_partial */
unsigned long nr_partial;
- atomic_long_t nr_slabs;
struct list_head partial;
#ifdef CONFIG_SLUB_DEBUG
+ atomic_long_t nr_slabs;
struct list_head full;
#endif
};
diff --git a/init/Kconfig b/init/Kconfig
index a97924b..7fccf09 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -763,7 +763,7 @@
config SLABINFO
bool
depends on PROC_FS
- depends on SLAB || SLUB
+ depends on SLAB || SLUB_DEBUG
default y
config RT_MUTEXES
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 2727f92..6d8de05 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1722,7 +1722,12 @@
use_task_css_set_links = 1;
do_each_thread(g, p) {
task_lock(p);
- if (list_empty(&p->cg_list))
+ /*
+ * We should check if the process is exiting, otherwise
+ * it will race with cgroup_exit() in that the list
+ * entry won't be deleted though the process has exited.
+ */
+ if (!(p->flags & PF_EXITING) && list_empty(&p->cg_list))
list_add(&p->cg_list, &p->cgroups->tasks);
task_unlock(p);
} while_each_thread(g, p);
diff --git a/kernel/signal.c b/kernel/signal.c
index 6af1210..cc8303c 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1757,6 +1757,45 @@
return 1;
}
+static int ptrace_signal(int signr, siginfo_t *info,
+ struct pt_regs *regs, void *cookie)
+{
+ if (!(current->ptrace & PT_PTRACED))
+ return signr;
+
+ ptrace_signal_deliver(regs, cookie);
+
+ /* Let the debugger run. */
+ ptrace_stop(signr, 0, info);
+
+ /* We're back. Did the debugger cancel the sig? */
+ signr = current->exit_code;
+ if (signr == 0)
+ return signr;
+
+ current->exit_code = 0;
+
+ /* Update the siginfo structure if the signal has
+ changed. If the debugger wanted something
+ specific in the siginfo structure then it should
+ have updated *info via PTRACE_SETSIGINFO. */
+ if (signr != info->si_signo) {
+ info->si_signo = signr;
+ info->si_errno = 0;
+ info->si_code = SI_USER;
+ info->si_pid = task_pid_vnr(current->parent);
+ info->si_uid = current->parent->uid;
+ }
+
+ /* If the (new) signal is now blocked, requeue it. */
+ if (sigismember(¤t->blocked, signr)) {
+ specific_send_sig_info(signr, info, current);
+ signr = 0;
+ }
+
+ return signr;
+}
+
int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
struct pt_regs *regs, void *cookie)
{
@@ -1785,36 +1824,10 @@
if (!signr)
break; /* will return 0 */
- if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
- ptrace_signal_deliver(regs, cookie);
-
- /* Let the debugger run. */
- ptrace_stop(signr, 0, info);
-
- /* We're back. Did the debugger cancel the sig? */
- signr = current->exit_code;
- if (signr == 0)
+ if (signr != SIGKILL) {
+ signr = ptrace_signal(signr, info, regs, cookie);
+ if (!signr)
continue;
-
- current->exit_code = 0;
-
- /* Update the siginfo structure if the signal has
- changed. If the debugger wanted something
- specific in the siginfo structure then it should
- have updated *info via PTRACE_SETSIGINFO. */
- if (signr != info->si_signo) {
- info->si_signo = signr;
- info->si_errno = 0;
- info->si_code = SI_USER;
- info->si_pid = task_pid_vnr(current->parent);
- info->si_uid = current->parent->uid;
- }
-
- /* If the (new) signal is now blocked, requeue it. */
- if (sigismember(¤t->blocked, signr)) {
- specific_send_sig_info(signr, info, current);
- continue;
- }
}
ka = ¤t->sighand->action[signr-1];
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index e1bd50cb..fdfa0c7 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -14,7 +14,7 @@
#include <linux/cpu.h>
#include <linux/err.h>
#include <linux/hrtimer.h>
-#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/percpu.h>
#include <linux/profile.h>
#include <linux/sched.h>
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index 1bea399..4f38865 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -14,12 +14,14 @@
#include <linux/cpu.h>
#include <linux/err.h>
#include <linux/hrtimer.h>
-#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/percpu.h>
#include <linux/profile.h>
#include <linux/sched.h>
#include <linux/tick.h>
+#include <asm/irq_regs.h>
+
#include "tick-internal.h"
/*
diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c
index 0258d31..450c049 100644
--- a/kernel/time/tick-oneshot.c
+++ b/kernel/time/tick-oneshot.c
@@ -14,7 +14,7 @@
#include <linux/cpu.h>
#include <linux/err.h>
#include <linux/hrtimer.h>
-#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/percpu.h>
#include <linux/profile.h>
#include <linux/sched.h>
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 0796c1a..eef557d 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -211,7 +211,7 @@
config SLUB_STATS
default n
bool "Enable SLUB performance statistics"
- depends on SLUB
+ depends on SLUB && SLUB_DEBUG && SYSFS
help
SLUB statistics are useful to debug SLUBs allocation behavior in
order find ways to optimize the allocator. This should never be
diff --git a/mm/slub.c b/mm/slub.c
index acc975f..7f8aaa2 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -837,6 +837,35 @@
spin_unlock(&n->list_lock);
}
+/* Tracking of the number of slabs for debugging purposes */
+static inline unsigned long slabs_node(struct kmem_cache *s, int node)
+{
+ struct kmem_cache_node *n = get_node(s, node);
+
+ return atomic_long_read(&n->nr_slabs);
+}
+
+static inline void inc_slabs_node(struct kmem_cache *s, int node)
+{
+ struct kmem_cache_node *n = get_node(s, node);
+
+ /*
+ * May be called early in order to allocate a slab for the
+ * kmem_cache_node structure. Solve the chicken-egg
+ * dilemma by deferring the increment of the count during
+ * bootstrap (see early_kmem_cache_node_alloc).
+ */
+ if (!NUMA_BUILD || n)
+ atomic_long_inc(&n->nr_slabs);
+}
+static inline void dec_slabs_node(struct kmem_cache *s, int node)
+{
+ struct kmem_cache_node *n = get_node(s, node);
+
+ atomic_long_dec(&n->nr_slabs);
+}
+
+/* Object debug checks for alloc/free paths */
static void setup_object_debug(struct kmem_cache *s, struct page *page,
void *object)
{
@@ -1028,6 +1057,11 @@
return flags;
}
#define slub_debug 0
+
+static inline unsigned long slabs_node(struct kmem_cache *s, int node)
+ { return 0; }
+static inline void inc_slabs_node(struct kmem_cache *s, int node) {}
+static inline void dec_slabs_node(struct kmem_cache *s, int node) {}
#endif
/*
* Slab allocation and freeing
@@ -1066,7 +1100,6 @@
static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
{
struct page *page;
- struct kmem_cache_node *n;
void *start;
void *last;
void *p;
@@ -1078,9 +1111,7 @@
if (!page)
goto out;
- n = get_node(s, page_to_nid(page));
- if (n)
- atomic_long_inc(&n->nr_slabs);
+ inc_slabs_node(s, page_to_nid(page));
page->slab = s;
page->flags |= 1 << PG_slab;
if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON |
@@ -1125,6 +1156,8 @@
NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,
-pages);
+ __ClearPageSlab(page);
+ reset_page_mapcount(page);
__free_pages(page, s->order);
}
@@ -1151,11 +1184,7 @@
static void discard_slab(struct kmem_cache *s, struct page *page)
{
- struct kmem_cache_node *n = get_node(s, page_to_nid(page));
-
- atomic_long_dec(&n->nr_slabs);
- reset_page_mapcount(page);
- __ClearPageSlab(page);
+ dec_slabs_node(s, page_to_nid(page));
free_slab(s, page);
}
@@ -1886,15 +1915,18 @@
c->node = 0;
c->offset = s->offset / sizeof(void *);
c->objsize = s->objsize;
+#ifdef CONFIG_SLUB_STATS
+ memset(c->stat, 0, NR_SLUB_STAT_ITEMS * sizeof(unsigned));
+#endif
}
static void init_kmem_cache_node(struct kmem_cache_node *n)
{
n->nr_partial = 0;
- atomic_long_set(&n->nr_slabs, 0);
spin_lock_init(&n->list_lock);
INIT_LIST_HEAD(&n->partial);
#ifdef CONFIG_SLUB_DEBUG
+ atomic_long_set(&n->nr_slabs, 0);
INIT_LIST_HEAD(&n->full);
#endif
}
@@ -2063,7 +2095,7 @@
init_tracking(kmalloc_caches, n);
#endif
init_kmem_cache_node(n);
- atomic_long_inc(&n->nr_slabs);
+ inc_slabs_node(kmalloc_caches, node);
/*
* lockdep requires consistent irq usage for each lock
@@ -2376,7 +2408,7 @@
struct kmem_cache_node *n = get_node(s, node);
n->nr_partial -= free_list(s, n, &n->partial);
- if (atomic_long_read(&n->nr_slabs))
+ if (slabs_node(s, node))
return 1;
}
free_kmem_cache_nodes(s);
@@ -2409,10 +2441,6 @@
struct kmem_cache kmalloc_caches[PAGE_SHIFT + 1] __cacheline_aligned;
EXPORT_SYMBOL(kmalloc_caches);
-#ifdef CONFIG_ZONE_DMA
-static struct kmem_cache *kmalloc_caches_dma[PAGE_SHIFT + 1];
-#endif
-
static int __init setup_slub_min_order(char *str)
{
get_option(&str, &slub_min_order);
@@ -2472,6 +2500,7 @@
}
#ifdef CONFIG_ZONE_DMA
+static struct kmem_cache *kmalloc_caches_dma[PAGE_SHIFT + 1];
static void sysfs_add_func(struct work_struct *w)
{
@@ -2688,21 +2717,6 @@
}
EXPORT_SYMBOL(kfree);
-#if defined(CONFIG_SLUB_DEBUG) || defined(CONFIG_SLABINFO)
-static unsigned long count_partial(struct kmem_cache_node *n)
-{
- unsigned long flags;
- unsigned long x = 0;
- struct page *page;
-
- spin_lock_irqsave(&n->list_lock, flags);
- list_for_each_entry(page, &n->partial, lru)
- x += page->inuse;
- spin_unlock_irqrestore(&n->list_lock, flags);
- return x;
-}
-#endif
-
/*
* kmem_cache_shrink removes empty slabs from the partial lists and sorts
* the remaining slabs by the number of items in use. The slabs with the
@@ -2816,7 +2830,7 @@
* and offline_pages() function shoudn't call this
* callback. So, we must fail.
*/
- BUG_ON(atomic_long_read(&n->nr_slabs));
+ BUG_ON(slabs_node(s, offline_node));
s->node[offline_node] = NULL;
kmem_cache_free(kmalloc_caches, n);
@@ -3181,6 +3195,21 @@
return slab_alloc(s, gfpflags, node, caller);
}
+#if (defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG)) || defined(CONFIG_SLABINFO)
+static unsigned long count_partial(struct kmem_cache_node *n)
+{
+ unsigned long flags;
+ unsigned long x = 0;
+ struct page *page;
+
+ spin_lock_irqsave(&n->list_lock, flags);
+ list_for_each_entry(page, &n->partial, lru)
+ x += page->inuse;
+ spin_unlock_irqrestore(&n->list_lock, flags);
+ return x;
+}
+#endif
+
#if defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG)
static int validate_slab(struct kmem_cache *s, struct page *page,
unsigned long *map)
@@ -3979,10 +4008,12 @@
len = sprintf(buf, "%lu", sum);
+#ifdef CONFIG_SMP
for_each_online_cpu(cpu) {
if (data[cpu] && len < PAGE_SIZE - 20)
- len += sprintf(buf + len, " c%d=%u", cpu, data[cpu]);
+ len += sprintf(buf + len, " C%d=%u", cpu, data[cpu]);
}
+#endif
kfree(data);
return len + sprintf(buf + len, "\n");
}
diff --git a/security/Kconfig b/security/Kconfig
index 5dfc206..49b51f9 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -113,10 +113,12 @@
from userspace allocation. Keeping a user from writing to low pages
can help reduce the impact of kernel NULL pointer bugs.
- For most users with lots of address space a value of 65536 is
- reasonable and should cause no problems. Programs which use vm86
- functionality would either need additional permissions from either
- the LSM or the capabilities module or have this protection disabled.
+ For most ia64, ppc64 and x86 users with lots of address space
+ a value of 65536 is reasonable and should cause no problems.
+ On arm and other archs it should not be higher than 32768.
+ Programs which use vm86 functionality would either need additional
+ permissions from either the LSM or the capabilities module or have
+ this protection disabled.
This value can be changed after boot using the
/proc/sys/vm/mmap_min_addr tunable.
diff --git a/security/commoncap.c b/security/commoncap.c
index 06d5c94..8529057 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -267,7 +267,7 @@
rc = cap_from_disk(&vcaps, bprm, rc);
if (rc)
printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
- __FUNCTION__, rc, bprm->filename);
+ __func__, rc, bprm->filename);
out:
dput(dentry);
@@ -302,7 +302,7 @@
ret = get_file_caps(bprm);
if (ret)
printk(KERN_NOTICE "%s: get_file_caps returned %d for %s\n",
- __FUNCTION__, ret, bprm->filename);
+ __func__, ret, bprm->filename);
/* To support inheritance of root-permissions and suid-root
* executables under compatibility mode, we raise all three
diff --git a/security/keys/internal.h b/security/keys/internal.h
index d36d693..7d894ef 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -22,16 +22,16 @@
#ifdef __KDEBUG
#define kenter(FMT, ...) \
- printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__)
+ printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__)
#define kleave(FMT, ...) \
- printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__)
+ printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
#define kdebug(FMT, ...) \
printk(KERN_DEBUG "xxx" FMT"yyy\n", ##__VA_ARGS__)
#else
#define kenter(FMT, ...) \
- no_printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__)
+ no_printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__)
#define kleave(FMT, ...) \
- no_printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__)
+ no_printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
#define kdebug(FMT, ...) \
no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__)
#endif
diff --git a/security/root_plug.c b/security/root_plug.c
index 870f130..6112d14 100644
--- a/security/root_plug.c
+++ b/security/root_plug.c
@@ -49,7 +49,7 @@
do { \
if (debug) \
printk(KERN_DEBUG "%s: %s: " fmt , \
- MY_NAME , __FUNCTION__ , \
+ MY_NAME , __func__ , \
## arg); \
} while (0)
diff --git a/security/security.c b/security/security.c
index b1387a6..9beecac 100644
--- a/security/security.c
+++ b/security/security.c
@@ -57,7 +57,7 @@
if (verify(&dummy_security_ops)) {
printk(KERN_ERR "%s could not verify "
- "dummy_security_ops structure.\n", __FUNCTION__);
+ "dummy_security_ops structure.\n", __func__);
return -EIO;
}
@@ -82,7 +82,7 @@
{
if (verify(ops)) {
printk(KERN_DEBUG "%s could not verify "
- "security_operations structure.\n", __FUNCTION__);
+ "security_operations structure.\n", __func__);
return -EINVAL;
}
@@ -110,13 +110,13 @@
{
if (verify(ops)) {
printk(KERN_INFO "%s could not verify "
- "security operations.\n", __FUNCTION__);
+ "security operations.\n", __func__);
return -EINVAL;
}
if (ops == security_ops) {
printk(KERN_INFO "%s security operations "
- "already registered.\n", __FUNCTION__);
+ "already registered.\n", __func__);
return -EINVAL;
}
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index 2b517d6..a436d1c 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -145,7 +145,7 @@
config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
int "NSA SELinux maximum supported policy format version value"
depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX
- range 15 22
+ range 15 23
default 19
help
This option sets the value for the maximum policy format version
diff --git a/security/selinux/Makefile b/security/selinux/Makefile
index 00afd85..d47fc5e 100644
--- a/security/selinux/Makefile
+++ b/security/selinux/Makefile
@@ -11,6 +11,7 @@
nlmsgtab.o \
netif.o \
netnode.o \
+ netport.o \
exports.o
selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 187964e..a4fc6e6 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -871,6 +871,8 @@
int rc = 0;
u32 denied;
+ BUG_ON(!requested);
+
rcu_read_lock();
node = avc_lookup(ssid, tsid, tclass, requested);
@@ -890,13 +892,14 @@
denied = requested & ~(p_ae->avd.allowed);
- if (!requested || denied) {
- if (selinux_enforcing || (flags & AVC_STRICT))
+ if (denied) {
+ if (flags & AVC_STRICT)
rc = -EACCES;
+ else if (!selinux_enforcing || security_permissive_sid(ssid))
+ avc_update_node(AVC_CALLBACK_GRANT, requested, ssid,
+ tsid, tclass);
else
- if (node)
- avc_update_node(AVC_CALLBACK_GRANT,requested,
- ssid,tsid,tclass);
+ rc = -EACCES;
}
rcu_read_unlock();
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index d39b59c..34f2d46 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -80,6 +80,7 @@
#include "objsec.h"
#include "netif.h"
#include "netnode.h"
+#include "netport.h"
#include "xfrm.h"
#include "netlabel.h"
@@ -161,8 +162,7 @@
if (!tsec)
return -ENOMEM;
- tsec->task = task;
- tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
+ tsec->osid = tsec->sid = SECINITSID_UNLABELED;
task->security = tsec;
return 0;
@@ -218,7 +218,6 @@
if (!fsec)
return -ENOMEM;
- fsec->file = file;
fsec->sid = tsec->sid;
fsec->fown_sid = tsec->sid;
file->f_security = fsec;
@@ -275,12 +274,11 @@
if (!ssec)
return -ENOMEM;
- ssec->sk = sk;
ssec->peer_sid = SECINITSID_UNLABELED;
ssec->sid = SECINITSID_UNLABELED;
sk->sk_security = ssec;
- selinux_netlbl_sk_security_init(ssec, family);
+ selinux_netlbl_sk_security_reset(ssec, family);
return 0;
}
@@ -324,10 +322,10 @@
};
static match_table_t tokens = {
- {Opt_context, "context=%s"},
- {Opt_fscontext, "fscontext=%s"},
- {Opt_defcontext, "defcontext=%s"},
- {Opt_rootcontext, "rootcontext=%s"},
+ {Opt_context, CONTEXT_STR "%s"},
+ {Opt_fscontext, FSCONTEXT_STR "%s"},
+ {Opt_defcontext, DEFCONTEXT_STR "%s"},
+ {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
{Opt_error, NULL},
};
@@ -671,7 +669,7 @@
rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
if (rc) {
printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
- __FUNCTION__, sb->s_type->name, rc);
+ __func__, sb->s_type->name, rc);
goto out;
}
@@ -1137,7 +1135,7 @@
}
if (!dentry) {
printk(KERN_WARNING "%s: no dentry for dev=%s "
- "ino=%ld\n", __FUNCTION__, inode->i_sb->s_id,
+ "ino=%ld\n", __func__, inode->i_sb->s_id,
inode->i_ino);
goto out_unlock;
}
@@ -1175,7 +1173,7 @@
if (rc < 0) {
if (rc != -ENODATA) {
printk(KERN_WARNING "%s: getxattr returned "
- "%d for dev=%s ino=%ld\n", __FUNCTION__,
+ "%d for dev=%s ino=%ld\n", __func__,
-rc, inode->i_sb->s_id, inode->i_ino);
kfree(context);
goto out_unlock;
@@ -1190,7 +1188,7 @@
if (rc) {
printk(KERN_WARNING "%s: context_to_sid(%s) "
"returned %d for dev=%s ino=%ld\n",
- __FUNCTION__, context, -rc,
+ __func__, context, -rc,
inode->i_sb->s_id, inode->i_ino);
kfree(context);
/* Leave with the unlabeled SID */
@@ -1618,6 +1616,35 @@
return av;
}
+/*
+ * Convert a file mask to an access vector and include the correct open
+ * open permission.
+ */
+static inline u32 open_file_mask_to_av(int mode, int mask)
+{
+ u32 av = file_mask_to_av(mode, mask);
+
+ if (selinux_policycap_openperm) {
+ /*
+ * lnk files and socks do not really have an 'open'
+ */
+ if (S_ISREG(mode))
+ av |= FILE__OPEN;
+ else if (S_ISCHR(mode))
+ av |= CHR_FILE__OPEN;
+ else if (S_ISBLK(mode))
+ av |= BLK_FILE__OPEN;
+ else if (S_ISFIFO(mode))
+ av |= FIFO_FILE__OPEN;
+ else if (S_ISDIR(mode))
+ av |= DIR__OPEN;
+ else
+ printk(KERN_ERR "SELinux: WARNING: inside open_file_to_av "
+ "with unknown mode:%x\n", mode);
+ }
+ return av;
+}
+
/* Convert a Linux file to an access vector. */
static inline u32 file_to_av(struct file *file)
{
@@ -1645,19 +1672,13 @@
static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
{
- struct task_security_struct *psec = parent->security;
- struct task_security_struct *csec = child->security;
int rc;
rc = secondary_ops->ptrace(parent,child);
if (rc)
return rc;
- rc = task_has_perm(parent, child, PROCESS__PTRACE);
- /* Save the SID of the tracing process for later use in apply_creds. */
- if (!(child->ptrace & PT_PTRACED) && !rc)
- csec->ptrace_sid = psec->sid;
- return rc;
+ return task_has_perm(parent, child, PROCESS__PTRACE);
}
static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
@@ -1879,6 +1900,22 @@
return __vm_enough_memory(mm, pages, cap_sys_admin);
}
+/**
+ * task_tracer_task - return the task that is tracing the given task
+ * @task: task to consider
+ *
+ * Returns NULL if noone is tracing @task, or the &struct task_struct
+ * pointer to its tracer.
+ *
+ * Must be called under rcu_read_lock().
+ */
+static struct task_struct *task_tracer_task(struct task_struct *task)
+{
+ if (task->ptrace & PT_PTRACED)
+ return rcu_dereference(task->parent);
+ return NULL;
+}
+
/* binprm security operations */
static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
@@ -1889,7 +1926,6 @@
if (!bsec)
return -ENOMEM;
- bsec->bprm = bprm;
bsec->sid = SECINITSID_UNLABELED;
bsec->set = 0;
@@ -2126,12 +2162,25 @@
/* Check for ptracing, and update the task SID if ok.
Otherwise, leave SID unchanged and kill. */
if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
- rc = avc_has_perm(tsec->ptrace_sid, sid,
- SECCLASS_PROCESS, PROCESS__PTRACE,
- NULL);
- if (rc) {
- bsec->unsafe = 1;
- return;
+ struct task_struct *tracer;
+ struct task_security_struct *sec;
+ u32 ptsid = 0;
+
+ rcu_read_lock();
+ tracer = task_tracer_task(current);
+ if (likely(tracer != NULL)) {
+ sec = tracer->security;
+ ptsid = sec->sid;
+ }
+ rcu_read_unlock();
+
+ if (ptsid != 0) {
+ rc = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
+ PROCESS__PTRACE, NULL);
+ if (rc) {
+ bsec->unsafe = 1;
+ return;
+ }
}
}
tsec->sid = sid;
@@ -2239,10 +2288,10 @@
static inline int selinux_option(char *option, int len)
{
- return (match_prefix("context=", sizeof("context=")-1, option, len) ||
- match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
- match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) ||
- match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len));
+ return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
+ match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
+ match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
+ match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len));
}
static inline void take_option(char **to, char *from, int *first, int len)
@@ -2412,7 +2461,7 @@
printk(KERN_WARNING "%s: "
"security_transition_sid failed, rc=%d (dev=%s "
"ino=%ld)\n",
- __FUNCTION__,
+ __func__,
-rc, inode->i_sb->s_id, inode->i_ino);
return rc;
}
@@ -2536,7 +2585,7 @@
}
return inode_has_perm(current, inode,
- file_mask_to_av(inode->i_mode, mask), NULL);
+ open_file_mask_to_av(inode->i_mode, mask), NULL);
}
static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
@@ -2646,7 +2695,7 @@
rc = security_context_to_sid(value, size, &newsid);
if (rc) {
printk(KERN_WARNING "%s: unable to obtain SID for context "
- "%s, rc=%d\n", __FUNCTION__, (char*)value, -rc);
+ "%s, rc=%d\n", __func__, (char *)value, -rc);
return;
}
@@ -3087,11 +3136,6 @@
tsec2->keycreate_sid = tsec1->keycreate_sid;
tsec2->sockcreate_sid = tsec1->sockcreate_sid;
- /* Retain ptracer SID across fork, if any.
- This will be reset by the ptrace hook upon any
- subsequent ptrace_attach operations. */
- tsec2->ptrace_sid = tsec1->ptrace_sid;
-
return 0;
}
@@ -3627,10 +3671,8 @@
inet_get_local_port_range(&low, &high);
if (snum < max(PROT_SOCK, low) || snum > high) {
- err = security_port_sid(sk->sk_family,
- sk->sk_type,
- sk->sk_protocol, snum,
- &sid);
+ err = sel_netport_sid(sk->sk_protocol,
+ snum, &sid);
if (err)
goto out;
AVC_AUDIT_DATA_INIT(&ad,NET);
@@ -3718,8 +3760,7 @@
snum = ntohs(addr6->sin6_port);
}
- err = security_port_sid(sk->sk_family, sk->sk_type,
- sk->sk_protocol, snum, &sid);
+ err = sel_netport_sid(sk->sk_protocol, snum, &sid);
if (err)
goto out;
@@ -3950,9 +3991,8 @@
if (!recv_perm)
return 0;
- err = security_port_sid(sk->sk_family, sk->sk_type,
- sk->sk_protocol, ntohs(ad->u.net.sport),
- &port_sid);
+ err = sel_netport_sid(sk->sk_protocol,
+ ntohs(ad->u.net.sport), &port_sid);
if (unlikely(err)) {
printk(KERN_WARNING
"SELinux: failure in"
@@ -4139,7 +4179,7 @@
newssec->peer_sid = ssec->peer_sid;
newssec->sclass = ssec->sclass;
- selinux_netlbl_sk_security_clone(ssec, newssec);
+ selinux_netlbl_sk_security_reset(newssec, newsk->sk_family);
}
static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
@@ -4373,9 +4413,8 @@
if (send_perm != 0)
return 0;
- err = security_port_sid(sk->sk_family, sk->sk_type,
- sk->sk_protocol, ntohs(ad->u.net.dport),
- &port_sid);
+ err = sel_netport_sid(sk->sk_protocol,
+ ntohs(ad->u.net.dport), &port_sid);
if (unlikely(err)) {
printk(KERN_WARNING
"SELinux: failure in"
@@ -4561,7 +4600,6 @@
return -ENOMEM;
isec->sclass = sclass;
- isec->ipc_perm = perm;
isec->sid = tsec->sid;
perm->security = isec;
@@ -4583,7 +4621,6 @@
if (!msec)
return -ENOMEM;
- msec->msg = msg;
msec->sid = SECINITSID_UNLABELED;
msg->security = msec;
@@ -4994,14 +5031,14 @@
{
if (secondary_ops != original_ops) {
printk(KERN_ERR "%s: There is already a secondary security "
- "module registered.\n", __FUNCTION__);
+ "module registered.\n", __func__);
return -EINVAL;
}
secondary_ops = ops;
printk(KERN_INFO "%s: Registering secondary module %s\n",
- __FUNCTION__,
+ __func__,
name);
return 0;
@@ -5057,6 +5094,7 @@
char *name, void *value, size_t size)
{
struct task_security_struct *tsec;
+ struct task_struct *tracer;
u32 sid = 0;
int error;
char *str = value;
@@ -5145,18 +5183,24 @@
/* Check for ptracing, and update the task SID if ok.
Otherwise, leave SID unchanged and fail. */
task_lock(p);
- if (p->ptrace & PT_PTRACED) {
- error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
+ rcu_read_lock();
+ tracer = task_tracer_task(p);
+ if (tracer != NULL) {
+ struct task_security_struct *ptsec = tracer->security;
+ u32 ptsid = ptsec->sid;
+ rcu_read_unlock();
+ error = avc_has_perm_noaudit(ptsid, sid,
SECCLASS_PROCESS,
PROCESS__PTRACE, 0, &avd);
if (!error)
tsec->sid = sid;
task_unlock(p);
- avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS,
+ avc_audit(ptsid, sid, SECCLASS_PROCESS,
PROCESS__PTRACE, &avd, error, NULL);
if (error)
return error;
} else {
+ rcu_read_unlock();
tsec->sid = sid;
task_unlock(p);
}
@@ -5194,7 +5238,6 @@
if (!ksec)
return -ENOMEM;
- ksec->obj = k;
if (tsec->keycreate_sid)
ksec->sid = tsec->keycreate_sid;
else
@@ -5631,5 +5674,3 @@
return 0;
}
#endif
-
-
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index d569669..1223b4f 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -14,12 +14,17 @@
S_(SECCLASS_DIR, DIR__REPARENT, "reparent")
S_(SECCLASS_DIR, DIR__SEARCH, "search")
S_(SECCLASS_DIR, DIR__RMDIR, "rmdir")
+ S_(SECCLASS_DIR, DIR__OPEN, "open")
S_(SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans")
S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
+ S_(SECCLASS_FILE, FILE__OPEN, "open")
S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans")
S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")
S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
+ S_(SECCLASS_CHR_FILE, CHR_FILE__OPEN, "open")
+ S_(SECCLASS_BLK_FILE, BLK_FILE__OPEN, "open")
+ S_(SECCLASS_FIFO_FILE, FIFO_FILE__OPEN, "open")
S_(SECCLASS_FD, FD__USE, "use")
S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto")
S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index 75b4131..c4c5116 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -79,6 +79,7 @@
#define DIR__REPARENT 0x00080000UL
#define DIR__SEARCH 0x00100000UL
#define DIR__RMDIR 0x00200000UL
+#define DIR__OPEN 0x00400000UL
#define FILE__IOCTL 0x00000001UL
#define FILE__READ 0x00000002UL
#define FILE__WRITE 0x00000004UL
@@ -99,6 +100,7 @@
#define FILE__EXECUTE_NO_TRANS 0x00020000UL
#define FILE__ENTRYPOINT 0x00040000UL
#define FILE__EXECMOD 0x00080000UL
+#define FILE__OPEN 0x00100000UL
#define LNK_FILE__IOCTL 0x00000001UL
#define LNK_FILE__READ 0x00000002UL
#define LNK_FILE__WRITE 0x00000004UL
@@ -136,6 +138,7 @@
#define CHR_FILE__EXECUTE_NO_TRANS 0x00020000UL
#define CHR_FILE__ENTRYPOINT 0x00040000UL
#define CHR_FILE__EXECMOD 0x00080000UL
+#define CHR_FILE__OPEN 0x00100000UL
#define BLK_FILE__IOCTL 0x00000001UL
#define BLK_FILE__READ 0x00000002UL
#define BLK_FILE__WRITE 0x00000004UL
@@ -153,6 +156,7 @@
#define BLK_FILE__SWAPON 0x00004000UL
#define BLK_FILE__QUOTAON 0x00008000UL
#define BLK_FILE__MOUNTON 0x00010000UL
+#define BLK_FILE__OPEN 0x00020000UL
#define SOCK_FILE__IOCTL 0x00000001UL
#define SOCK_FILE__READ 0x00000002UL
#define SOCK_FILE__WRITE 0x00000004UL
@@ -187,6 +191,7 @@
#define FIFO_FILE__SWAPON 0x00004000UL
#define FIFO_FILE__QUOTAON 0x00008000UL
#define FIFO_FILE__MOUNTON 0x00010000UL
+#define FIFO_FILE__OPEN 0x00020000UL
#define FD__USE 0x00000001UL
#define SOCKET__IOCTL 0x00000001UL
#define SOCKET__READ 0x00000002UL
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
index 00a2809..9a9e7cd 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -41,10 +41,6 @@
void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
int family);
-void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
- int family);
-void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
- struct sk_security_struct *newssec);
int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
u16 family,
@@ -73,18 +69,6 @@
{
return;
}
-static inline void selinux_netlbl_sk_security_init(
- struct sk_security_struct *ssec,
- int family)
-{
- return;
-}
-static inline void selinux_netlbl_sk_security_clone(
- struct sk_security_struct *ssec,
- struct sk_security_struct *newssec)
-{
- return;
-}
static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
u16 family,
diff --git a/security/selinux/include/netport.h b/security/selinux/include/netport.h
new file mode 100644
index 0000000..8991752
--- /dev/null
+++ b/security/selinux/include/netport.h
@@ -0,0 +1,31 @@
+/*
+ * Network port table
+ *
+ * SELinux must keep a mapping of network ports to labels/SIDs. This
+ * mapping is maintained as part of the normal policy but a fast cache is
+ * needed to reduce the lookup overhead.
+ *
+ * Author: Paul Moore <paul.moore@hp.com>
+ *
+ */
+
+/*
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2008
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _SELINUX_NETPORT_H
+#define _SELINUX_NETPORT_H
+
+int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid);
+
+#endif
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index c6c2bb4..300b61b 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -28,14 +28,12 @@
#include "avc.h"
struct task_security_struct {
- struct task_struct *task; /* back pointer to task object */
u32 osid; /* SID prior to last execve */
u32 sid; /* current SID */
u32 exec_sid; /* exec SID */
u32 create_sid; /* fscreate SID */
u32 keycreate_sid; /* keycreate SID */
u32 sockcreate_sid; /* fscreate SID */
- u32 ptrace_sid; /* SID of ptrace parent */
};
struct inode_security_struct {
@@ -50,7 +48,6 @@
};
struct file_security_struct {
- struct file *file; /* back pointer to file object */
u32 sid; /* SID of open file description */
u32 fown_sid; /* SID of file owner (for SIGIO) */
u32 isid; /* SID of inode at the time of file open */
@@ -73,18 +70,15 @@
};
struct msg_security_struct {
- struct msg_msg *msg; /* back pointer */
u32 sid; /* SID of message */
};
struct ipc_security_struct {
- struct kern_ipc_perm *ipc_perm; /* back pointer */
u16 sclass; /* security class of this object */
u32 sid; /* SID of IPC resource */
};
struct bprm_security_struct {
- struct linux_binprm *bprm; /* back pointer to bprm object */
u32 sid; /* SID for transformed process */
unsigned char set;
@@ -109,8 +103,13 @@
u16 family; /* address family */
};
+struct netport_security_struct {
+ u32 sid; /* SID for this node */
+ u16 port; /* port number */
+ u8 protocol; /* transport protocol */
+};
+
struct sk_security_struct {
- struct sock *sk; /* back pointer to sk object */
u32 sid; /* SID of this object */
u32 peer_sid; /* SID of peer */
u16 sclass; /* sock security class */
@@ -120,12 +119,10 @@
NLBL_REQUIRE,
NLBL_LABELED,
} nlbl_state;
- spinlock_t nlbl_lock; /* protects nlbl_state */
#endif
};
struct key_security_struct {
- struct key *obj; /* back pointer */
u32 sid; /* SID of key */
};
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 44e12ec..1904c46 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -26,13 +26,14 @@
#define POLICYDB_VERSION_AVTAB 20
#define POLICYDB_VERSION_RANGETRANS 21
#define POLICYDB_VERSION_POLCAP 22
+#define POLICYDB_VERSION_PERMISSIVE 23
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
#else
-#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP
+#define POLICYDB_VERSION_MAX POLICYDB_VERSION_PERMISSIVE
#endif
#define CONTEXT_MNT 0x01
@@ -40,6 +41,11 @@
#define ROOTCONTEXT_MNT 0x04
#define DEFCONTEXT_MNT 0x08
+#define CONTEXT_STR "context="
+#define FSCONTEXT_STR "fscontext="
+#define ROOTCONTEXT_STR "rootcontext="
+#define DEFCONTEXT_STR "defcontext="
+
struct netlbl_lsm_secattr;
extern int selinux_enabled;
@@ -48,11 +54,13 @@
/* Policy capabilities */
enum {
POLICYDB_CAPABILITY_NETPEER,
+ POLICYDB_CAPABILITY_OPENPERM,
__POLICYDB_CAPABILITY_MAX
};
#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
extern int selinux_policycap_netpeer;
+extern int selinux_policycap_openperm;
int security_load_policy(void * data, size_t len);
@@ -67,6 +75,8 @@
u32 seqno;
};
+int security_permissive_sid(u32 sid);
+
int security_compute_av(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct av_decision *avd);
@@ -92,8 +102,7 @@
int security_get_user_sids(u32 callsid, char *username,
u32 **sids, u32 *nel);
-int security_port_sid(u16 domain, u16 type, u8 protocol, u16 port,
- u32 *out_sid);
+int security_port_sid(u8 protocol, u16 port, u32 *out_sid);
int security_netif_sid(char *name, u32 *if_sid);
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 0fa2be4..e8ee91a 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -34,6 +34,7 @@
#include "objsec.h"
#include "security.h"
+#include "netlabel.h"
/**
* selinux_netlbl_sidlookup_cached - Cache a SID lookup
@@ -69,9 +70,7 @@
*
* Description:
* Attempt to label a socket using the NetLabel mechanism using the given
- * SID. Returns zero values on success, negative values on failure. The
- * caller is responsibile for calling rcu_read_lock() before calling this
- * this function and rcu_read_unlock() after this function returns.
+ * SID. Returns zero values on success, negative values on failure.
*
*/
static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
@@ -86,11 +85,8 @@
if (rc != 0)
goto sock_setsid_return;
rc = netlbl_sock_setattr(sk, &secattr);
- if (rc == 0) {
- spin_lock_bh(&sksec->nlbl_lock);
+ if (rc == 0)
sksec->nlbl_state = NLBL_LABELED;
- spin_unlock_bh(&sksec->nlbl_lock);
- }
sock_setsid_return:
netlbl_secattr_destroy(&secattr);
@@ -129,45 +125,6 @@
}
/**
- * selinux_netlbl_sk_security_init - Setup the NetLabel fields
- * @ssec: the sk_security_struct
- * @family: the socket family
- *
- * Description:
- * Called when a new sk_security_struct is allocated to initialize the NetLabel
- * fields.
- *
- */
-void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
- int family)
-{
- /* No locking needed, we are the only one who has access to ssec */
- selinux_netlbl_sk_security_reset(ssec, family);
- spin_lock_init(&ssec->nlbl_lock);
-}
-
-/**
- * selinux_netlbl_sk_security_clone - Copy the NetLabel fields
- * @ssec: the original sk_security_struct
- * @newssec: the cloned sk_security_struct
- *
- * Description:
- * Clone the NetLabel specific sk_security_struct fields from @ssec to
- * @newssec.
- *
- */
-void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
- struct sk_security_struct *newssec)
-{
- /* We don't need to take newssec->nlbl_lock because we are the only
- * thread with access to newssec, but we do need to take the RCU read
- * lock as other threads could have access to ssec */
- rcu_read_lock();
- selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family);
- rcu_read_unlock();
-}
-
-/**
* selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
* @skb: the packet
* @family: protocol family
@@ -221,12 +178,8 @@
struct netlbl_lsm_secattr secattr;
u32 nlbl_peer_sid;
- rcu_read_lock();
-
- if (sksec->nlbl_state != NLBL_REQUIRE) {
- rcu_read_unlock();
+ if (sksec->nlbl_state != NLBL_REQUIRE)
return;
- }
netlbl_secattr_init(&secattr);
if (netlbl_sock_getattr(sk, &secattr) == 0 &&
@@ -239,8 +192,6 @@
* here we will pick up the pieces in later calls to
* selinux_netlbl_inode_permission(). */
selinux_netlbl_sock_setsid(sk, sksec->sid);
-
- rcu_read_unlock();
}
/**
@@ -254,16 +205,13 @@
*/
int selinux_netlbl_socket_post_create(struct socket *sock)
{
- int rc = 0;
struct sock *sk = sock->sk;
struct sk_security_struct *sksec = sk->sk_security;
- rcu_read_lock();
- if (sksec->nlbl_state == NLBL_REQUIRE)
- rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
- rcu_read_unlock();
+ if (sksec->nlbl_state != NLBL_REQUIRE)
+ return 0;
- return rc;
+ return selinux_netlbl_sock_setsid(sk, sksec->sid);
}
/**
@@ -288,21 +236,21 @@
if (!S_ISSOCK(inode->i_mode) ||
((mask & (MAY_WRITE | MAY_APPEND)) == 0))
return 0;
+
sock = SOCKET_I(inode);
sk = sock->sk;
sksec = sk->sk_security;
-
- rcu_read_lock();
- if (sksec->nlbl_state != NLBL_REQUIRE) {
- rcu_read_unlock();
+ if (sksec->nlbl_state != NLBL_REQUIRE)
return 0;
- }
+
local_bh_disable();
bh_lock_sock_nested(sk);
- rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
+ if (likely(sksec->nlbl_state == NLBL_REQUIRE))
+ rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
+ else
+ rc = 0;
bh_unlock_sock(sk);
local_bh_enable();
- rcu_read_unlock();
return rc;
}
@@ -385,7 +333,6 @@
struct sk_security_struct *sksec = sk->sk_security;
struct netlbl_lsm_secattr secattr;
- rcu_read_lock();
if (level == IPPROTO_IP && optname == IP_OPTIONS &&
sksec->nlbl_state == NLBL_LABELED) {
netlbl_secattr_init(&secattr);
@@ -396,7 +343,6 @@
rc = -EACCES;
netlbl_secattr_destroy(&secattr);
}
- rcu_read_unlock();
return rc;
}
diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c
index b59871d..6214a7a 100644
--- a/security/selinux/netlink.c
+++ b/security/selinux/netlink.c
@@ -89,7 +89,7 @@
nlmsg_failure:
kfree_skb(skb);
oom:
- printk(KERN_ERR "SELinux: OOM in %s\n", __FUNCTION__);
+ printk(KERN_ERR "SELinux: OOM in %s\n", __func__);
goto out;
}
diff --git a/security/selinux/netport.c b/security/selinux/netport.c
new file mode 100644
index 0000000..68ede3c
--- /dev/null
+++ b/security/selinux/netport.c
@@ -0,0 +1,286 @@
+/*
+ * Network port table
+ *
+ * SELinux must keep a mapping of network ports to labels/SIDs. This
+ * mapping is maintained as part of the normal policy but a fast cache is
+ * needed to reduce the lookup overhead.
+ *
+ * Author: Paul Moore <paul.moore@hp.com>
+ *
+ * This code is heavily based on the "netif" concept originally developed by
+ * James Morris <jmorris@redhat.com>
+ * (see security/selinux/netif.c for more information)
+ *
+ */
+
+/*
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2008
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/rcupdate.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <asm/bug.h>
+
+#include "netport.h"
+#include "objsec.h"
+
+#define SEL_NETPORT_HASH_SIZE 256
+#define SEL_NETPORT_HASH_BKT_LIMIT 16
+
+struct sel_netport_bkt {
+ int size;
+ struct list_head list;
+};
+
+struct sel_netport {
+ struct netport_security_struct psec;
+
+ struct list_head list;
+ struct rcu_head rcu;
+};
+
+/* NOTE: we are using a combined hash table for both IPv4 and IPv6, the reason
+ * for this is that I suspect most users will not make heavy use of both
+ * address families at the same time so one table will usually end up wasted,
+ * if this becomes a problem we can always add a hash table for each address
+ * family later */
+
+static LIST_HEAD(sel_netport_list);
+static DEFINE_SPINLOCK(sel_netport_lock);
+static struct sel_netport_bkt sel_netport_hash[SEL_NETPORT_HASH_SIZE];
+
+/**
+ * sel_netport_free - Frees a port entry
+ * @p: the entry's RCU field
+ *
+ * Description:
+ * This function is designed to be used as a callback to the call_rcu()
+ * function so that memory allocated to a hash table port entry can be
+ * released safely.
+ *
+ */
+static void sel_netport_free(struct rcu_head *p)
+{
+ struct sel_netport *port = container_of(p, struct sel_netport, rcu);
+ kfree(port);
+}
+
+/**
+ * sel_netport_hashfn - Hashing function for the port table
+ * @pnum: port number
+ *
+ * Description:
+ * This is the hashing function for the port table, it returns the bucket
+ * number for the given port.
+ *
+ */
+static unsigned int sel_netport_hashfn(u16 pnum)
+{
+ return (pnum & (SEL_NETPORT_HASH_SIZE - 1));
+}
+
+/**
+ * sel_netport_find - Search for a port record
+ * @protocol: protocol
+ * @port: pnum
+ *
+ * Description:
+ * Search the network port table and return the matching record. If an entry
+ * can not be found in the table return NULL.
+ *
+ */
+static struct sel_netport *sel_netport_find(u8 protocol, u16 pnum)
+{
+ unsigned int idx;
+ struct sel_netport *port;
+
+ idx = sel_netport_hashfn(pnum);
+ list_for_each_entry_rcu(port, &sel_netport_hash[idx].list, list)
+ if (port->psec.port == pnum &&
+ port->psec.protocol == protocol)
+ return port;
+
+ return NULL;
+}
+
+/**
+ * sel_netport_insert - Insert a new port into the table
+ * @port: the new port record
+ *
+ * Description:
+ * Add a new port record to the network address hash table. Returns zero on
+ * success, negative values on failure.
+ *
+ */
+static int sel_netport_insert(struct sel_netport *port)
+{
+ unsigned int idx;
+
+ /* we need to impose a limit on the growth of the hash table so check
+ * this bucket to make sure it is within the specified bounds */
+ idx = sel_netport_hashfn(port->psec.port);
+ list_add_rcu(&port->list, &sel_netport_hash[idx].list);
+ if (sel_netport_hash[idx].size == SEL_NETPORT_HASH_BKT_LIMIT) {
+ struct sel_netport *tail;
+ tail = list_entry(port->list.prev, struct sel_netport, list);
+ list_del_rcu(port->list.prev);
+ call_rcu(&tail->rcu, sel_netport_free);
+ } else
+ sel_netport_hash[idx].size++;
+
+ return 0;
+}
+
+/**
+ * sel_netport_sid_slow - Lookup the SID of a network address using the policy
+ * @protocol: protocol
+ * @pnum: port
+ * @sid: port SID
+ *
+ * Description:
+ * This function determines the SID of a network port by quering the security
+ * policy. The result is added to the network port table to speedup future
+ * queries. Returns zero on success, negative values on failure.
+ *
+ */
+static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid)
+{
+ int ret;
+ struct sel_netport *port;
+ struct sel_netport *new = NULL;
+
+ spin_lock_bh(&sel_netport_lock);
+ port = sel_netport_find(protocol, pnum);
+ if (port != NULL) {
+ *sid = port->psec.sid;
+ ret = 0;
+ goto out;
+ }
+ new = kzalloc(sizeof(*new), GFP_ATOMIC);
+ if (new == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ ret = security_port_sid(protocol, pnum, &new->psec.sid);
+ if (ret != 0)
+ goto out;
+ new->psec.port = pnum;
+ new->psec.protocol = protocol;
+ ret = sel_netport_insert(new);
+ if (ret != 0)
+ goto out;
+ *sid = new->psec.sid;
+
+out:
+ spin_unlock_bh(&sel_netport_lock);
+ if (unlikely(ret)) {
+ printk(KERN_WARNING
+ "SELinux: failure in sel_netport_sid_slow(),"
+ " unable to determine network port label\n");
+ kfree(new);
+ }
+ return ret;
+}
+
+/**
+ * sel_netport_sid - Lookup the SID of a network port
+ * @protocol: protocol
+ * @pnum: port
+ * @sid: port SID
+ *
+ * Description:
+ * This function determines the SID of a network port using the fastest method
+ * possible. First the port table is queried, but if an entry can't be found
+ * then the policy is queried and the result is added to the table to speedup
+ * future queries. Returns zero on success, negative values on failure.
+ *
+ */
+int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid)
+{
+ struct sel_netport *port;
+
+ rcu_read_lock();
+ port = sel_netport_find(protocol, pnum);
+ if (port != NULL) {
+ *sid = port->psec.sid;
+ rcu_read_unlock();
+ return 0;
+ }
+ rcu_read_unlock();
+
+ return sel_netport_sid_slow(protocol, pnum, sid);
+}
+
+/**
+ * sel_netport_flush - Flush the entire network port table
+ *
+ * Description:
+ * Remove all entries from the network address table.
+ *
+ */
+static void sel_netport_flush(void)
+{
+ unsigned int idx;
+ struct sel_netport *port;
+
+ spin_lock_bh(&sel_netport_lock);
+ for (idx = 0; idx < SEL_NETPORT_HASH_SIZE; idx++) {
+ list_for_each_entry(port, &sel_netport_hash[idx].list, list) {
+ list_del_rcu(&port->list);
+ call_rcu(&port->rcu, sel_netport_free);
+ }
+ sel_netport_hash[idx].size = 0;
+ }
+ spin_unlock_bh(&sel_netport_lock);
+}
+
+static int sel_netport_avc_callback(u32 event, u32 ssid, u32 tsid,
+ u16 class, u32 perms, u32 *retained)
+{
+ if (event == AVC_CALLBACK_RESET) {
+ sel_netport_flush();
+ synchronize_net();
+ }
+ return 0;
+}
+
+static __init int sel_netport_init(void)
+{
+ int iter;
+ int ret;
+
+ if (!selinux_enabled)
+ return 0;
+
+ for (iter = 0; iter < SEL_NETPORT_HASH_SIZE; iter++) {
+ INIT_LIST_HEAD(&sel_netport_hash[iter].list);
+ sel_netport_hash[iter].size = 0;
+ }
+
+ ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET,
+ SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
+ if (ret != 0)
+ panic("avc_add_callback() failed, error %d\n", ret);
+
+ return ret;
+}
+
+__initcall(sel_netport_init);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 0341567..26fabad 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -42,7 +42,8 @@
/* Policy capability filenames */
static char *policycap_names[] = {
- "network_peer_controls"
+ "network_peer_controls",
+ "open_perms"
};
unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
@@ -391,7 +392,7 @@
if (len > SIMPLE_TRANSACTION_LIMIT) {
printk(KERN_ERR "%s: context size (%u) exceeds payload "
- "max\n", __FUNCTION__, len);
+ "max\n", __func__, len);
length = -ERANGE;
goto out;
}
@@ -644,7 +645,7 @@
if (len > SIMPLE_TRANSACTION_LIMIT) {
printk(KERN_ERR "%s: context size (%u) exceeds payload "
- "max\n", __FUNCTION__, len);
+ "max\n", __func__, len);
length = -ERANGE;
goto out3;
}
@@ -821,7 +822,7 @@
if (len > SIMPLE_TRANSACTION_LIMIT) {
printk(KERN_ERR "%s: context size (%u) exceeds payload "
- "max\n", __FUNCTION__, len);
+ "max\n", __func__, len);
length = -ERANGE;
goto out3;
}
@@ -1760,7 +1761,7 @@
out:
return ret;
err:
- printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__);
+ printk(KERN_ERR "%s: failed while creating inodes\n", __func__);
goto out;
}
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index cd10e27..916e73a 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -280,8 +280,8 @@
h->nel = 0;
h->nslot = nslot;
h->mask = mask;
- printk(KERN_DEBUG "SELinux:%d avtab hash slots allocated. "
- "Num of rules:%d\n", h->nslot, nrules);
+ printk(KERN_DEBUG "SELinux: %d avtab hash slots, %d rules.\n",
+ h->nslot, nrules);
return 0;
}
@@ -345,18 +345,18 @@
if (vers < POLICYDB_VERSION_AVTAB) {
rc = next_entry(buf32, fp, sizeof(u32));
if (rc < 0) {
- printk(KERN_ERR "security: avtab: truncated entry\n");
+ printk(KERN_ERR "SELinux: avtab: truncated entry\n");
return -1;
}
items2 = le32_to_cpu(buf32[0]);
if (items2 > ARRAY_SIZE(buf32)) {
- printk(KERN_ERR "security: avtab: entry overflow\n");
+ printk(KERN_ERR "SELinux: avtab: entry overflow\n");
return -1;
}
rc = next_entry(buf32, fp, sizeof(u32)*items2);
if (rc < 0) {
- printk(KERN_ERR "security: avtab: truncated entry\n");
+ printk(KERN_ERR "SELinux: avtab: truncated entry\n");
return -1;
}
items = 0;
@@ -364,19 +364,19 @@
val = le32_to_cpu(buf32[items++]);
key.source_type = (u16)val;
if (key.source_type != val) {
- printk("security: avtab: truncated source type\n");
+ printk("SELinux: avtab: truncated source type\n");
return -1;
}
val = le32_to_cpu(buf32[items++]);
key.target_type = (u16)val;
if (key.target_type != val) {
- printk("security: avtab: truncated target type\n");
+ printk("SELinux: avtab: truncated target type\n");
return -1;
}
val = le32_to_cpu(buf32[items++]);
key.target_class = (u16)val;
if (key.target_class != val) {
- printk("security: avtab: truncated target class\n");
+ printk("SELinux: avtab: truncated target class\n");
return -1;
}
@@ -384,12 +384,12 @@
enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0;
if (!(val & (AVTAB_AV | AVTAB_TYPE))) {
- printk("security: avtab: null entry\n");
+ printk("SELinux: avtab: null entry\n");
return -1;
}
if ((val & AVTAB_AV) &&
(val & AVTAB_TYPE)) {
- printk("security: avtab: entry has both access vectors and types\n");
+ printk("SELinux: avtab: entry has both access vectors and types\n");
return -1;
}
@@ -403,7 +403,7 @@
}
if (items != items2) {
- printk("security: avtab: entry only had %d items, expected %d\n", items2, items);
+ printk("SELinux: avtab: entry only had %d items, expected %d\n", items2, items);
return -1;
}
return 0;
@@ -411,7 +411,7 @@
rc = next_entry(buf16, fp, sizeof(u16)*4);
if (rc < 0) {
- printk("security: avtab: truncated entry\n");
+ printk("SELinux: avtab: truncated entry\n");
return -1;
}
@@ -424,7 +424,7 @@
if (!policydb_type_isvalid(pol, key.source_type) ||
!policydb_type_isvalid(pol, key.target_type) ||
!policydb_class_isvalid(pol, key.target_class)) {
- printk(KERN_WARNING "security: avtab: invalid type or class\n");
+ printk(KERN_WARNING "SELinux: avtab: invalid type or class\n");
return -1;
}
@@ -435,19 +435,19 @@
}
if (!set || set > 1) {
printk(KERN_WARNING
- "security: avtab: more than one specifier\n");
+ "SELinux: avtab: more than one specifier\n");
return -1;
}
rc = next_entry(buf32, fp, sizeof(u32));
if (rc < 0) {
- printk("security: avtab: truncated entry\n");
+ printk("SELinux: avtab: truncated entry\n");
return -1;
}
datum.data = le32_to_cpu(*buf32);
if ((key.specified & AVTAB_TYPE) &&
!policydb_type_isvalid(pol, datum.data)) {
- printk(KERN_WARNING "security: avtab: invalid type\n");
+ printk(KERN_WARNING "SELinux: avtab: invalid type\n");
return -1;
}
return insertf(a, &key, &datum, p);
@@ -468,12 +468,12 @@
rc = next_entry(buf, fp, sizeof(u32));
if (rc < 0) {
- printk(KERN_ERR "security: avtab: truncated table\n");
+ printk(KERN_ERR "SELinux: avtab: truncated table\n");
goto bad;
}
nel = le32_to_cpu(buf[0]);
if (!nel) {
- printk(KERN_ERR "security: avtab: table is empty\n");
+ printk(KERN_ERR "SELinux: avtab: table is empty\n");
rc = -EINVAL;
goto bad;
}
@@ -486,9 +486,9 @@
rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL);
if (rc) {
if (rc == -ENOMEM)
- printk(KERN_ERR "security: avtab: out of memory\n");
+ printk(KERN_ERR "SELinux: avtab: out of memory\n");
else if (rc == -EEXIST)
- printk(KERN_ERR "security: avtab: duplicate entry\n");
+ printk(KERN_ERR "SELinux: avtab: duplicate entry\n");
else
rc = -EINVAL;
goto bad;
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index 50ad85d..a996cf1 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -96,7 +96,7 @@
if (new_state != node->cur_state) {
node->cur_state = new_state;
if (new_state == -1)
- printk(KERN_ERR "security: expression result was undefined - disabling all rules.\n");
+ printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n");
/* turn the rules on or off */
for (cur = node->true_list; cur != NULL; cur = cur->next) {
if (new_state <= 0) {
@@ -276,7 +276,7 @@
*/
if (k->specified & AVTAB_TYPE) {
if (avtab_search(&p->te_avtab, k)) {
- printk("security: type rule already exists outside of a conditional.");
+ printk("SELinux: type rule already exists outside of a conditional.");
goto err;
}
/*
@@ -291,7 +291,7 @@
node_ptr = avtab_search_node(&p->te_cond_avtab, k);
if (node_ptr) {
if (avtab_search_node_next(node_ptr, k->specified)) {
- printk("security: too many conflicting type rules.");
+ printk("SELinux: too many conflicting type rules.");
goto err;
}
found = 0;
@@ -302,13 +302,13 @@
}
}
if (!found) {
- printk("security: conflicting type rules.\n");
+ printk("SELinux: conflicting type rules.\n");
goto err;
}
}
} else {
if (avtab_search(&p->te_cond_avtab, k)) {
- printk("security: conflicting type rules when adding type rule for true.\n");
+ printk("SELinux: conflicting type rules when adding type rule for true.\n");
goto err;
}
}
@@ -316,7 +316,7 @@
node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
if (!node_ptr) {
- printk("security: could not insert rule.");
+ printk("SELinux: could not insert rule.");
goto err;
}
@@ -376,12 +376,12 @@
static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
{
if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
- printk("security: conditional expressions uses unknown operator.\n");
+ printk("SELinux: conditional expressions uses unknown operator.\n");
return 0;
}
if (expr->bool > p->p_bools.nprim) {
- printk("security: conditional expressions uses unknown bool.\n");
+ printk("SELinux: conditional expressions uses unknown bool.\n");
return 0;
}
return 1;
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index 920b5e3..e499af4 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -364,7 +364,7 @@
count = le32_to_cpu(buf[2]);
if (mapunit != sizeof(u64) * 8) {
- printk(KERN_ERR "security: ebitmap: map size %u does not "
+ printk(KERN_ERR "SELinux: ebitmap: map size %u does not "
"match my size %Zd (high bit was %d)\n",
mapunit, sizeof(u64) * 8, e->highbit);
goto bad;
@@ -382,19 +382,19 @@
for (i = 0; i < count; i++) {
rc = next_entry(&startbit, fp, sizeof(u32));
if (rc < 0) {
- printk(KERN_ERR "security: ebitmap: truncated map\n");
+ printk(KERN_ERR "SELinux: ebitmap: truncated map\n");
goto bad;
}
startbit = le32_to_cpu(startbit);
if (startbit & (mapunit - 1)) {
- printk(KERN_ERR "security: ebitmap start bit (%d) is "
+ printk(KERN_ERR "SELinux: ebitmap start bit (%d) is "
"not a multiple of the map unit size (%u)\n",
startbit, mapunit);
goto bad;
}
if (startbit > e->highbit - mapunit) {
- printk(KERN_ERR "security: ebitmap start bit (%d) is "
+ printk(KERN_ERR "SELinux: ebitmap start bit (%d) is "
"beyond the end of the bitmap (%u)\n",
startbit, (e->highbit - mapunit));
goto bad;
@@ -405,7 +405,7 @@
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
if (!tmp) {
printk(KERN_ERR
- "security: ebitmap: out of memory\n");
+ "SELinux: ebitmap: out of memory\n");
rc = -ENOMEM;
goto bad;
}
@@ -418,7 +418,7 @@
}
n = tmp;
} else if (startbit <= n->startbit) {
- printk(KERN_ERR "security: ebitmap: start bit %d"
+ printk(KERN_ERR "SELinux: ebitmap: start bit %d"
" comes after start bit %d\n",
startbit, n->startbit);
goto bad;
@@ -426,7 +426,7 @@
rc = next_entry(&map, fp, sizeof(u64));
if (rc < 0) {
- printk(KERN_ERR "security: ebitmap: truncated map\n");
+ printk(KERN_ERR "SELinux: ebitmap: truncated map\n");
goto bad;
}
map = le64_to_cpu(map);
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index bd7d6a0..6bdb0ff 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -111,6 +111,11 @@
.version = POLICYDB_VERSION_POLCAP,
.sym_num = SYM_NUM,
.ocon_num = OCON_NUM,
+ },
+ {
+ .version = POLICYDB_VERSION_PERMISSIVE,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_NUM,
}
};
@@ -194,6 +199,7 @@
goto out_free_symtab;
ebitmap_init(&p->policycaps);
+ ebitmap_init(&p->permissive_map);
out:
return rc;
@@ -401,14 +407,14 @@
{
int i, rc = 0;
- printk(KERN_DEBUG "security: %d users, %d roles, %d types, %d bools",
+ printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools",
p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
if (selinux_mls_enabled)
printk(", %d sens, %d cats", p->p_levels.nprim,
p->p_cats.nprim);
printk("\n");
- printk(KERN_DEBUG "security: %d classes, %d rules\n",
+ printk(KERN_DEBUG "SELinux: %d classes, %d rules\n",
p->p_classes.nprim, p->te_avtab.nel);
#ifdef DEBUG_HASHES
@@ -687,6 +693,7 @@
kfree(p->type_attr_map);
kfree(p->undefined_perms);
ebitmap_destroy(&p->policycaps);
+ ebitmap_destroy(&p->permissive_map);
return;
}
@@ -702,20 +709,20 @@
rc = sidtab_init(s);
if (rc) {
- printk(KERN_ERR "security: out of memory on SID table init\n");
+ printk(KERN_ERR "SELinux: out of memory on SID table init\n");
goto out;
}
head = p->ocontexts[OCON_ISID];
for (c = head; c; c = c->next) {
if (!c->context[0].user) {
- printk(KERN_ERR "security: SID %s was never "
+ printk(KERN_ERR "SELinux: SID %s was never "
"defined.\n", c->u.name);
rc = -EINVAL;
goto out;
}
if (sidtab_insert(s, c->sid[0], &c->context[0])) {
- printk(KERN_ERR "security: unable to load initial "
+ printk(KERN_ERR "SELinux: unable to load initial "
"SID %s.\n", c->u.name);
rc = -EINVAL;
goto out;
@@ -809,13 +816,13 @@
items = le32_to_cpu(buf[0]);
if (items > ARRAY_SIZE(buf)) {
- printk(KERN_ERR "security: mls: range overflow\n");
+ printk(KERN_ERR "SELinux: mls: range overflow\n");
rc = -EINVAL;
goto out;
}
rc = next_entry(buf, fp, sizeof(u32) * items);
if (rc < 0) {
- printk(KERN_ERR "security: mls: truncated range\n");
+ printk(KERN_ERR "SELinux: mls: truncated range\n");
goto out;
}
r->level[0].sens = le32_to_cpu(buf[0]);
@@ -826,21 +833,21 @@
rc = ebitmap_read(&r->level[0].cat, fp);
if (rc) {
- printk(KERN_ERR "security: mls: error reading low "
+ printk(KERN_ERR "SELinux: mls: error reading low "
"categories\n");
goto out;
}
if (items > 1) {
rc = ebitmap_read(&r->level[1].cat, fp);
if (rc) {
- printk(KERN_ERR "security: mls: error reading high "
+ printk(KERN_ERR "SELinux: mls: error reading high "
"categories\n");
goto bad_high;
}
} else {
rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
if (rc) {
- printk(KERN_ERR "security: mls: out of memory\n");
+ printk(KERN_ERR "SELinux: mls: out of memory\n");
goto bad_high;
}
}
@@ -866,7 +873,7 @@
rc = next_entry(buf, fp, sizeof buf);
if (rc < 0) {
- printk(KERN_ERR "security: context truncated\n");
+ printk(KERN_ERR "SELinux: context truncated\n");
goto out;
}
c->user = le32_to_cpu(buf[0]);
@@ -874,7 +881,7 @@
c->type = le32_to_cpu(buf[2]);
if (p->policyvers >= POLICYDB_VERSION_MLS) {
if (mls_read_range_helper(&c->range, fp)) {
- printk(KERN_ERR "security: error reading MLS range of "
+ printk(KERN_ERR "SELinux: error reading MLS range of "
"context\n");
rc = -EINVAL;
goto out;
@@ -882,7 +889,7 @@
}
if (!policydb_context_isvalid(p, c)) {
- printk(KERN_ERR "security: invalid security context\n");
+ printk(KERN_ERR "SELinux: invalid security context\n");
context_destroy(c);
rc = -EINVAL;
}
@@ -1128,7 +1135,7 @@
cladatum->comdatum = hashtab_search(p->p_commons.table,
cladatum->comkey);
if (!cladatum->comdatum) {
- printk(KERN_ERR "security: unknown common %s\n",
+ printk(KERN_ERR "SELinux: unknown common %s\n",
cladatum->comkey);
rc = -EINVAL;
goto bad;
@@ -1283,13 +1290,13 @@
rc = next_entry(buf, fp, sizeof buf);
if (rc < 0) {
- printk(KERN_ERR "security: mls: truncated level\n");
+ printk(KERN_ERR "SELinux: mls: truncated level\n");
goto bad;
}
lp->sens = le32_to_cpu(buf[0]);
if (ebitmap_read(&lp->cat, fp)) {
- printk(KERN_ERR "security: mls: error reading level "
+ printk(KERN_ERR "SELinux: mls: error reading level "
"categories\n");
goto bad;
}
@@ -1491,7 +1498,7 @@
goto bad;
if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) {
- printk(KERN_ERR "security: policydb magic number 0x%x does "
+ printk(KERN_ERR "SELinux: policydb magic number 0x%x does "
"not match expected magic number 0x%x\n",
le32_to_cpu(buf[0]), POLICYDB_MAGIC);
goto bad;
@@ -1499,27 +1506,27 @@
len = le32_to_cpu(buf[1]);
if (len != strlen(POLICYDB_STRING)) {
- printk(KERN_ERR "security: policydb string length %d does not "
+ printk(KERN_ERR "SELinux: policydb string length %d does not "
"match expected length %Zu\n",
len, strlen(POLICYDB_STRING));
goto bad;
}
policydb_str = kmalloc(len + 1,GFP_KERNEL);
if (!policydb_str) {
- printk(KERN_ERR "security: unable to allocate memory for policydb "
+ printk(KERN_ERR "SELinux: unable to allocate memory for policydb "
"string of length %d\n", len);
rc = -ENOMEM;
goto bad;
}
rc = next_entry(policydb_str, fp, len);
if (rc < 0) {
- printk(KERN_ERR "security: truncated policydb string identifier\n");
+ printk(KERN_ERR "SELinux: truncated policydb string identifier\n");
kfree(policydb_str);
goto bad;
}
policydb_str[len] = 0;
if (strcmp(policydb_str, POLICYDB_STRING)) {
- printk(KERN_ERR "security: policydb string %s does not match "
+ printk(KERN_ERR "SELinux: policydb string %s does not match "
"my string %s\n", policydb_str, POLICYDB_STRING);
kfree(policydb_str);
goto bad;
@@ -1536,7 +1543,7 @@
p->policyvers = le32_to_cpu(buf[0]);
if (p->policyvers < POLICYDB_VERSION_MIN ||
p->policyvers > POLICYDB_VERSION_MAX) {
- printk(KERN_ERR "security: policydb version %d does not match "
+ printk(KERN_ERR "SELinux: policydb version %d does not match "
"my version range %d-%d\n",
le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
goto bad;
@@ -1570,16 +1577,20 @@
ebitmap_read(&p->policycaps, fp) != 0)
goto bad;
+ if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
+ ebitmap_read(&p->permissive_map, fp) != 0)
+ goto bad;
+
info = policydb_lookup_compat(p->policyvers);
if (!info) {
- printk(KERN_ERR "security: unable to find policy compat info "
+ printk(KERN_ERR "SELinux: unable to find policy compat info "
"for version %d\n", p->policyvers);
goto bad;
}
if (le32_to_cpu(buf[2]) != info->sym_num ||
le32_to_cpu(buf[3]) != info->ocon_num) {
- printk(KERN_ERR "security: policydb table sizes (%d,%d) do "
+ printk(KERN_ERR "SELinux: policydb table sizes (%d,%d) do "
"not match mine (%d,%d)\n", le32_to_cpu(buf[2]),
le32_to_cpu(buf[3]),
info->sym_num, info->ocon_num);
@@ -1823,7 +1834,7 @@
for (genfs_p = NULL, genfs = p->genfs; genfs;
genfs_p = genfs, genfs = genfs->next) {
if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
- printk(KERN_ERR "security: dup genfs "
+ printk(KERN_ERR "SELinux: dup genfs "
"fstype %s\n", newgenfs->fstype);
kfree(newgenfs->fstype);
kfree(newgenfs);
@@ -1873,7 +1884,7 @@
if (!strcmp(newc->u.name, c->u.name) &&
(!c->v.sclass || !newc->v.sclass ||
newc->v.sclass == c->v.sclass)) {
- printk(KERN_ERR "security: dup genfs "
+ printk(KERN_ERR "SELinux: dup genfs "
"entry (%s,%s)\n",
newgenfs->fstype, c->u.name);
goto bad_newc;
@@ -1931,7 +1942,7 @@
if (rc)
goto bad;
if (!mls_range_isvalid(p, &rt->target_range)) {
- printk(KERN_WARNING "security: rangetrans: invalid range\n");
+ printk(KERN_WARNING "SELinux: rangetrans: invalid range\n");
goto bad;
}
lrt = rt;
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index c4ce996..ba593a3 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -243,6 +243,8 @@
struct ebitmap policycaps;
+ struct ebitmap permissive_map;
+
unsigned int policyvers;
unsigned int reject_unknown : 1;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 3f2bad2..d750508 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -40,6 +40,7 @@
#include <linux/sched.h>
#include <linux/audit.h>
#include <linux/mutex.h>
+#include <linux/selinux.h>
#include <net/netlabel.h>
#include "flask.h"
@@ -61,6 +62,7 @@
unsigned int policydb_loaded_version;
int selinux_policycap_netpeer;
+int selinux_policycap_openperm;
/*
* This is declared in avc.c
@@ -412,10 +414,35 @@
return 0;
inval_class:
- printk(KERN_ERR "%s: unrecognized class %d\n", __FUNCTION__, tclass);
+ printk(KERN_ERR "%s: unrecognized class %d\n", __func__, tclass);
return -EINVAL;
}
+/*
+ * Given a sid find if the type has the permissive flag set
+ */
+int security_permissive_sid(u32 sid)
+{
+ struct context *context;
+ u32 type;
+ int rc;
+
+ POLICY_RDLOCK;
+
+ context = sidtab_search(&sidtab, sid);
+ BUG_ON(!context);
+
+ type = context->type;
+ /*
+ * we are intentionally using type here, not type-1, the 0th bit may
+ * someday indicate that we are globally setting permissive in policy.
+ */
+ rc = ebitmap_get_bit(&policydb.permissive_map, type);
+
+ POLICY_RDUNLOCK;
+ return rc;
+}
+
static int security_validtrans_handle_fail(struct context *ocontext,
struct context *ncontext,
struct context *tcontext,
@@ -1096,7 +1123,7 @@
continue;
if (i > p->p_classes.nprim) {
printk(KERN_INFO
- "security: class %s not defined in policy\n",
+ "SELinux: class %s not defined in policy\n",
def_class);
if (p->reject_unknown)
return -EINVAL;
@@ -1107,7 +1134,7 @@
pol_class = p->p_class_val_to_name[i-1];
if (strcmp(pol_class, def_class)) {
printk(KERN_ERR
- "security: class %d is incorrect, found %s but should be %s\n",
+ "SELinux: class %d is incorrect, found %s but should be %s\n",
i, pol_class, def_class);
return -EINVAL;
}
@@ -1125,7 +1152,7 @@
nprim = 1 << (perms->nprim - 1);
if (perm_val > nprim) {
printk(KERN_INFO
- "security: permission %s in class %s not defined in policy\n",
+ "SELinux: permission %s in class %s not defined in policy\n",
def_perm, pol_class);
if (p->reject_unknown)
return -EINVAL;
@@ -1136,14 +1163,14 @@
perdatum = hashtab_search(perms->table, def_perm);
if (perdatum == NULL) {
printk(KERN_ERR
- "security: permission %s in class %s not found in policy, bad policy\n",
+ "SELinux: permission %s in class %s not found in policy, bad policy\n",
def_perm, pol_class);
return -EINVAL;
}
pol_val = 1 << (perdatum->value - 1);
if (pol_val != perm_val) {
printk(KERN_ERR
- "security: permission %s in class %s has incorrect value\n",
+ "SELinux: permission %s in class %s has incorrect value\n",
def_perm, pol_class);
return -EINVAL;
}
@@ -1157,7 +1184,7 @@
BUG_ON(!cladatum);
if (!cladatum->comdatum) {
printk(KERN_ERR
- "security: class %s should have an inherits clause but does not\n",
+ "SELinux: class %s should have an inherits clause but does not\n",
pol_class);
return -EINVAL;
}
@@ -1172,7 +1199,7 @@
def_perm = kdefs->av_inherit[i].common_pts[j];
if (j >= perms->nprim) {
printk(KERN_INFO
- "security: permission %s in class %s not defined in policy\n",
+ "SELinux: permission %s in class %s not defined in policy\n",
def_perm, pol_class);
if (p->reject_unknown)
return -EINVAL;
@@ -1183,13 +1210,13 @@
perdatum = hashtab_search(perms->table, def_perm);
if (perdatum == NULL) {
printk(KERN_ERR
- "security: permission %s in class %s not found in policy, bad policy\n",
+ "SELinux: permission %s in class %s not found in policy, bad policy\n",
def_perm, pol_class);
return -EINVAL;
}
if (perdatum->value != j + 1) {
printk(KERN_ERR
- "security: permission %s in class %s has incorrect value\n",
+ "SELinux: permission %s in class %s has incorrect value\n",
def_perm, pol_class);
return -EINVAL;
}
@@ -1219,7 +1246,7 @@
u32 len;
context_struct_to_string(context, &s, &len);
- printk(KERN_ERR "security: context %s is invalid\n", s);
+ printk(KERN_ERR "SELinux: context %s is invalid\n", s);
kfree(s);
}
return rc;
@@ -1299,7 +1326,7 @@
bad:
context_struct_to_string(&oldc, &s, &len);
context_destroy(&oldc);
- printk(KERN_ERR "security: invalidating context %s\n", s);
+ printk(KERN_ERR "SELinux: invalidating context %s\n", s);
kfree(s);
goto out;
}
@@ -1308,6 +1335,8 @@
{
selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps,
POLICYDB_CAPABILITY_NETPEER);
+ selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
+ POLICYDB_CAPABILITY_OPENPERM);
}
extern void selinux_complete_init(void);
@@ -1350,7 +1379,7 @@
/* Verify that the kernel defined classes are correct. */
if (validate_classes(&policydb)) {
printk(KERN_ERR
- "security: the definition of a class is incorrect\n");
+ "SELinux: the definition of a class is incorrect\n");
LOAD_UNLOCK;
sidtab_destroy(&sidtab);
policydb_destroy(&policydb);
@@ -1384,14 +1413,14 @@
/* Verify that the kernel defined classes are correct. */
if (validate_classes(&newpolicydb)) {
printk(KERN_ERR
- "security: the definition of a class is incorrect\n");
+ "SELinux: the definition of a class is incorrect\n");
rc = -EINVAL;
goto err;
}
rc = security_preserve_bools(&newpolicydb);
if (rc) {
- printk(KERN_ERR "security: unable to preserve booleans\n");
+ printk(KERN_ERR "SELinux: unable to preserve booleans\n");
goto err;
}
@@ -1443,17 +1472,11 @@
/**
* security_port_sid - Obtain the SID for a port.
- * @domain: communication domain aka address family
- * @type: socket type
* @protocol: protocol number
* @port: port number
* @out_sid: security identifier
*/
-int security_port_sid(u16 domain,
- u16 type,
- u8 protocol,
- u16 port,
- u32 *out_sid)
+int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
{
struct ocontext *c;
int rc = 0;
@@ -2203,7 +2226,7 @@
match = hashtab_search(policydb.p_classes.table, class);
if (!match) {
printk(KERN_ERR "%s: unrecognized class %s\n",
- __FUNCTION__, class);
+ __func__, class);
rc = -EINVAL;
goto out;
}