From 69ac43b05eef4b8555e84ad51ceb6c58b5a3bc75 Mon Sep 17 00:00:00 2001 From: Chen Liu Date: Wed, 23 Mar 2011 10:14:58 +0100 Subject: [S390] early: Fix possible overlapping data buffer This patch fixed bugzilla #12965: https://bugzilla.kernel.org/show_bug.cgi?id=12965 The original code contains some inproper use of sprintf function where a buffer is used both as input string as well as output string. It should remember the written bytes in the previous and use that as the offset for later writing. Also replace sprintf with snprintf. Signed-off-by: Chen Liu Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/early.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 3b7e7dddc324..668138ee85d9 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -94,6 +94,7 @@ static noinline __init void create_kernel_nss(void) unsigned int sinitrd_pfn, einitrd_pfn; #endif int response; + int hlen; size_t len; char *savesys_ptr; char defsys_cmd[DEFSYS_CMD_SIZE]; @@ -124,22 +125,24 @@ static noinline __init void create_kernel_nss(void) end_pfn = PFN_UP(__pa(&_end)); min_size = end_pfn << 2; - sprintf(defsys_cmd, "DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X", - kernel_nss_name, stext_pfn - 1, stext_pfn, eshared_pfn - 1, - eshared_pfn, end_pfn); + hlen = snprintf(defsys_cmd, DEFSYS_CMD_SIZE, + "DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X", + kernel_nss_name, stext_pfn - 1, stext_pfn, + eshared_pfn - 1, eshared_pfn, end_pfn); #ifdef CONFIG_BLK_DEV_INITRD if (INITRD_START && INITRD_SIZE) { sinitrd_pfn = PFN_DOWN(__pa(INITRD_START)); einitrd_pfn = PFN_UP(__pa(INITRD_START + INITRD_SIZE)); min_size = einitrd_pfn << 2; - sprintf(defsys_cmd, "%s EW %.5X-%.5X", defsys_cmd, - sinitrd_pfn, einitrd_pfn); + hlen += snprintf(defsys_cmd + hlen, DEFSYS_CMD_SIZE - hlen, + " EW %.5X-%.5X", sinitrd_pfn, einitrd_pfn); } #endif - sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK PARMREGS=0-13", - defsys_cmd, min_size); + snprintf(defsys_cmd + hlen, DEFSYS_CMD_SIZE - hlen, + " EW MINSIZE=%.7iK PARMREGS=0-13", min_size); + defsys_cmd[DEFSYS_CMD_SIZE - 1] = '\0'; sprintf(savesys_cmd, "SAVESYS %s \n IPL %s", kernel_nss_name, kernel_nss_name); -- cgit v1.2.3 From 894e491e427ae40af62b871e05f9a3f80bbddb6c Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 23 Mar 2011 10:14:59 +0100 Subject: [S390] early: limit savesys cmd string handling Use snprintf() here as well so we won't have to deal with this again. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/early.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 668138ee85d9..068f8465c4ee 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -143,8 +143,9 @@ static noinline __init void create_kernel_nss(void) snprintf(defsys_cmd + hlen, DEFSYS_CMD_SIZE - hlen, " EW MINSIZE=%.7iK PARMREGS=0-13", min_size); defsys_cmd[DEFSYS_CMD_SIZE - 1] = '\0'; - sprintf(savesys_cmd, "SAVESYS %s \n IPL %s", - kernel_nss_name, kernel_nss_name); + snprintf(savesys_cmd, SAVESYS_CMD_SIZE, "SAVESYS %s \n IPL %s", + kernel_nss_name, kernel_nss_name); + savesys_cmd[SAVESYS_CMD_SIZE - 1] = '\0'; __cpcmd(defsys_cmd, NULL, 0, &response); -- cgit v1.2.3 From 984e8486c155cf53c255e2b501de91b39a049613 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 23 Mar 2011 10:15:00 +0100 Subject: [S390] oprofile: disable hw sampling for CONFIG_32BIT Doesn't work and build for CONFIG_32BIT. So disable it. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/oprofile/Makefile | 3 ++- arch/s390/oprofile/init.c | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/arch/s390/oprofile/Makefile b/arch/s390/oprofile/Makefile index d698cddcfbdd..524c4b615821 100644 --- a/arch/s390/oprofile/Makefile +++ b/arch/s390/oprofile/Makefile @@ -6,4 +6,5 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ oprofilefs.o oprofile_stats.o \ timer_int.o ) -oprofile-y := $(DRIVER_OBJS) init.o backtrace.o hwsampler.o +oprofile-y := $(DRIVER_OBJS) init.o backtrace.o +oprofile-$(CONFIG_64BIT) += hwsampler.o diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c index 16c76def4a9d..c63d7e58352b 100644 --- a/arch/s390/oprofile/init.c +++ b/arch/s390/oprofile/init.c @@ -18,6 +18,11 @@ #include #include "../../../drivers/oprofile/oprof.h" + +extern void s390_backtrace(struct pt_regs * const regs, unsigned int depth); + +#ifdef CONFIG_64BIT + #include "hwsampler.h" #define DEFAULT_INTERVAL 4096 @@ -37,8 +42,6 @@ static int hwsampler_running; /* start_mutex must be held to change */ static struct oprofile_operations timer_ops; -extern void s390_backtrace(struct pt_regs * const regs, unsigned int depth); - static int oprofile_hwsampler_start(void) { int retval; @@ -172,14 +175,22 @@ static void oprofile_hwsampler_exit(void) hwsampler_shutdown(); } +#endif /* CONFIG_64BIT */ + int __init oprofile_arch_init(struct oprofile_operations *ops) { ops->backtrace = s390_backtrace; +#ifdef CONFIG_64BIT return oprofile_hwsampler_init(ops); +#else + return -ENODEV; +#endif } void oprofile_arch_exit(void) { +#ifdef CONFIG_64BIT oprofile_hwsampler_exit(); +#endif } -- cgit v1.2.3 From 737fd5f1f64271999b791cbe76f1f720f10e8bb8 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 23 Mar 2011 10:15:55 +0100 Subject: [S390] wire up sys_name_to_handle_at Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/unistd.h | 3 ++- arch/s390/kernel/compat_wrapper.S | 9 +++++++++ arch/s390/kernel/syscalls.S | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index 1049ef27c15e..80f27c9f7202 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h @@ -272,7 +272,8 @@ #define __NR_fanotify_init 332 #define __NR_fanotify_mark 333 #define __NR_prlimit64 334 -#define NR_syscalls 335 +#define __NR_name_to_handle_at 335 +#define NR_syscalls 336 /* * There are some system calls that are not present on 64 bit, some diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 8e60fb23b90d..364ed14406bb 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1877,3 +1877,12 @@ sys_prlimit64_wrapper: llgtr %r4,%r4 # const struct rlimit64 __user * llgtr %r5,%r5 # struct rlimit64 __user * jg sys_prlimit64 # branch to system call + + .globl sys_name_to_handle_at_wrapper +sys_name_to_handle_at_wrapper: + lgfr %r2,%r2 # int + llgtr %r3,%r3 # const char __user * + llgtr %r4,%r4 # struct file_handle __user * + llgtr %r5,%r5 # int __user * + lgfr %r6,%r6 # int + jg sys_name_to_handle_at diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index a8fee1b14395..1230c6e75a84 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -343,3 +343,4 @@ SYSCALL(sys_perf_event_open,sys_perf_event_open,sys_perf_event_open_wrapper) SYSCALL(sys_fanotify_init,sys_fanotify_init,sys_fanotify_init_wrapper) SYSCALL(sys_fanotify_mark,sys_fanotify_mark,sys_fanotify_mark_wrapper) SYSCALL(sys_prlimit64,sys_prlimit64,sys_prlimit64_wrapper) +SYSCALL(sys_name_to_handle_at,sys_name_to_handle_at,sys_name_to_handle_at_wrapper) /* 335 */ -- cgit v1.2.3 From 5069496ec40946da413646f9cd5dcb28d9b3324f Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 23 Mar 2011 10:15:56 +0100 Subject: [S390] wire up sys_open_by_handle_at Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/unistd.h | 3 ++- arch/s390/kernel/compat_wrapper.S | 7 +++++++ arch/s390/kernel/syscalls.S | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index 80f27c9f7202..65f11efdd94c 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h @@ -273,7 +273,8 @@ #define __NR_fanotify_mark 333 #define __NR_prlimit64 334 #define __NR_name_to_handle_at 335 -#define NR_syscalls 336 +#define __NR_open_by_handle_at 336 +#define NR_syscalls 337 /* * There are some system calls that are not present on 64 bit, some diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 364ed14406bb..03918128bb45 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1886,3 +1886,10 @@ sys_name_to_handle_at_wrapper: llgtr %r5,%r5 # int __user * lgfr %r6,%r6 # int jg sys_name_to_handle_at + + .globl compat_sys_open_by_handle_at_wrapper +compat_sys_open_by_handle_at_wrapper: + lgfr %r2,%r2 # int + llgtr %r3,%r3 # struct file_handle __user * + lgfr %r4,%r4 # int + jg compat_sys_open_by_handle_at diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index 1230c6e75a84..958744cdcaba 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -344,3 +344,4 @@ SYSCALL(sys_fanotify_init,sys_fanotify_init,sys_fanotify_init_wrapper) SYSCALL(sys_fanotify_mark,sys_fanotify_mark,sys_fanotify_mark_wrapper) SYSCALL(sys_prlimit64,sys_prlimit64,sys_prlimit64_wrapper) SYSCALL(sys_name_to_handle_at,sys_name_to_handle_at,sys_name_to_handle_at_wrapper) /* 335 */ +SYSCALL(sys_open_by_handle_at,sys_open_by_handle_at,compat_sys_open_by_handle_at_wrapper) -- cgit v1.2.3 From 26e8a33989183e81d6692aec1a77dffa266b91a2 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 23 Mar 2011 10:15:57 +0100 Subject: [S390] wire up sys_clock_adjtime Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/unistd.h | 3 ++- arch/s390/kernel/compat_wrapper.S | 6 ++++++ arch/s390/kernel/syscalls.S | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index 65f11efdd94c..e00373061fc9 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h @@ -274,7 +274,8 @@ #define __NR_prlimit64 334 #define __NR_name_to_handle_at 335 #define __NR_open_by_handle_at 336 -#define NR_syscalls 337 +#define __NR_clock_adjtime 337 +#define NR_syscalls 338 /* * There are some system calls that are not present on 64 bit, some diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 03918128bb45..494db7f7c23c 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1893,3 +1893,9 @@ compat_sys_open_by_handle_at_wrapper: llgtr %r3,%r3 # struct file_handle __user * lgfr %r4,%r4 # int jg compat_sys_open_by_handle_at + + .globl compat_sys_clock_adjtime_wrapper +compat_sys_clock_adjtime_wrapper: + lgfr %r2,%r2 # clockid_t (int) + llgtr %r3,%r3 # struct compat_timex __user * + jg compat_sys_clock_adjtime diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index 958744cdcaba..8ff300208d2d 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -345,3 +345,4 @@ SYSCALL(sys_fanotify_mark,sys_fanotify_mark,sys_fanotify_mark_wrapper) SYSCALL(sys_prlimit64,sys_prlimit64,sys_prlimit64_wrapper) SYSCALL(sys_name_to_handle_at,sys_name_to_handle_at,sys_name_to_handle_at_wrapper) /* 335 */ SYSCALL(sys_open_by_handle_at,sys_open_by_handle_at,compat_sys_open_by_handle_at_wrapper) +SYSCALL(sys_clock_adjtime,sys_clock_adjtime,compat_sys_clock_adjtime_wrapper) -- cgit v1.2.3 From d0d2e31af691ed3dbb4e556bf939b86ef745e6a3 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 23 Mar 2011 10:15:58 +0100 Subject: [S390] wire up sys_syncfs Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/unistd.h | 3 ++- arch/s390/kernel/compat_wrapper.S | 5 +++++ arch/s390/kernel/syscalls.S | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index e00373061fc9..e82152572377 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h @@ -275,7 +275,8 @@ #define __NR_name_to_handle_at 335 #define __NR_open_by_handle_at 336 #define __NR_clock_adjtime 337 -#define NR_syscalls 338 +#define __NR_syncfs 338 +#define NR_syscalls 339 /* * There are some system calls that are not present on 64 bit, some diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 494db7f7c23c..1dc96ea08fa8 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1899,3 +1899,8 @@ compat_sys_clock_adjtime_wrapper: lgfr %r2,%r2 # clockid_t (int) llgtr %r3,%r3 # struct compat_timex __user * jg compat_sys_clock_adjtime + + .globl sys_syncfs_wrapper +sys_syncfs_wrapper: + lgfr %r2,%r2 # int + jg sys_syncfs diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index 8ff300208d2d..9c65fd4ddce0 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -346,3 +346,4 @@ SYSCALL(sys_prlimit64,sys_prlimit64,sys_prlimit64_wrapper) SYSCALL(sys_name_to_handle_at,sys_name_to_handle_at,sys_name_to_handle_at_wrapper) /* 335 */ SYSCALL(sys_open_by_handle_at,sys_open_by_handle_at,compat_sys_open_by_handle_at_wrapper) SYSCALL(sys_clock_adjtime,sys_clock_adjtime,compat_sys_clock_adjtime_wrapper) +SYSCALL(sys_syncfs,sys_syncfs,sys_syncfs_wrapper) -- cgit v1.2.3 From 71189284e61fd818547430186f524c1db54fb7c7 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 23 Mar 2011 10:15:59 +0100 Subject: [S390] setup: simplify setup_resources() Simplify setup_resources() and make it more generic. That way it is easier to add additional resources. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/setup.c | 80 ++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 46 deletions(-) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 6f6350826c81..455345104c8c 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -102,16 +102,6 @@ EXPORT_SYMBOL(lowcore_ptr); #include -static struct resource code_resource = { - .name = "Kernel code", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM, -}; - -static struct resource data_resource = { - .name = "Kernel data", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM, -}; - /* * condev= and conmode= setup parameter. */ @@ -436,11 +426,25 @@ setup_lowcore(void) lowcore_ptr[0] = lc; } -static void __init -setup_resources(void) +static struct resource code_resource = { + .name = "Kernel code", + .flags = IORESOURCE_BUSY | IORESOURCE_MEM, +}; + +static struct resource data_resource = { + .name = "Kernel data", + .flags = IORESOURCE_BUSY | IORESOURCE_MEM, +}; + +static struct resource __initdata *standard_resources[] = { + &code_resource, + &data_resource, +}; + +static void __init setup_resources(void) { - struct resource *res, *sub_res; - int i; + struct resource *res, *std_res, *sub_res; + int i, j; code_resource.start = (unsigned long) &_text; code_resource.end = (unsigned long) &_etext - 1; @@ -450,7 +454,7 @@ setup_resources(void) for (i = 0; i < MEMORY_CHUNKS; i++) { if (!memory_chunk[i].size) continue; - res = alloc_bootmem_low(sizeof(struct resource)); + res = alloc_bootmem_low(sizeof(*res)); res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; switch (memory_chunk[i].type) { case CHUNK_READ_WRITE: @@ -464,40 +468,24 @@ setup_resources(void) res->name = "reserved"; } res->start = memory_chunk[i].addr; - res->end = memory_chunk[i].addr + memory_chunk[i].size - 1; + res->end = res->start + memory_chunk[i].size - 1; request_resource(&iomem_resource, res); - if (code_resource.start >= res->start && - code_resource.start <= res->end && - code_resource.end > res->end) { - sub_res = alloc_bootmem_low(sizeof(struct resource)); - memcpy(sub_res, &code_resource, - sizeof(struct resource)); - sub_res->end = res->end; - code_resource.start = res->end + 1; - request_resource(res, sub_res); - } - - if (code_resource.start >= res->start && - code_resource.start <= res->end && - code_resource.end <= res->end) - request_resource(res, &code_resource); - - if (data_resource.start >= res->start && - data_resource.start <= res->end && - data_resource.end > res->end) { - sub_res = alloc_bootmem_low(sizeof(struct resource)); - memcpy(sub_res, &data_resource, - sizeof(struct resource)); - sub_res->end = res->end; - data_resource.start = res->end + 1; - request_resource(res, sub_res); + for (j = 0; j < ARRAY_SIZE(standard_resources); j++) { + std_res = standard_resources[j]; + if (std_res->start < res->start || + std_res->start > res->end) + continue; + if (std_res->end > res->end) { + sub_res = alloc_bootmem_low(sizeof(*sub_res)); + *sub_res = *std_res; + sub_res->end = res->end; + std_res->start = res->end + 1; + request_resource(res, sub_res); + } else { + request_resource(res, std_res); + } } - - if (data_resource.start >= res->start && - data_resource.start <= res->end && - data_resource.end <= res->end) - request_resource(res, &data_resource); } } -- cgit v1.2.3 From 4cc69531f91dfa1668af5e9d8efe9e3bc7b64548 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 23 Mar 2011 10:16:00 +0100 Subject: [S390] setup: register bss section as resource Make kernel bss section visible via /proc/iomem like on other architectures. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/setup.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 455345104c8c..ed183c2c6168 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -436,9 +436,15 @@ static struct resource data_resource = { .flags = IORESOURCE_BUSY | IORESOURCE_MEM, }; +static struct resource bss_resource = { + .name = "Kernel bss", + .flags = IORESOURCE_BUSY | IORESOURCE_MEM, +}; + static struct resource __initdata *standard_resources[] = { &code_resource, &data_resource, + &bss_resource, }; static void __init setup_resources(void) @@ -450,6 +456,8 @@ static void __init setup_resources(void) code_resource.end = (unsigned long) &_etext - 1; data_resource.start = (unsigned long) &_etext; data_resource.end = (unsigned long) &_edata - 1; + bss_resource.start = (unsigned long) &__bss_start; + bss_resource.end = (unsigned long) &__bss_stop - 1; for (i = 0; i < MEMORY_CHUNKS; i++) { if (!memory_chunk[i].size) -- cgit v1.2.3 From 9a26513eb67ec4b2cb1744834076afad21b68aac Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Wed, 23 Mar 2011 10:16:01 +0100 Subject: [S390] qdio: prevent handling of buffers if count is zero Exit do_QDIO early if the buffer count is zero to prevent side effects in the following functions. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 5640c89cd9de..479c665e9e7c 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -1508,7 +1508,8 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags, if (irq_ptr->state != QDIO_IRQ_STATE_ACTIVE) return -EBUSY; - + if (!count) + return 0; if (callflags & QDIO_FLAG_SYNC_INPUT) return handle_inbound(irq_ptr->input_qs[q_nr], callflags, bufnr, count); -- cgit v1.2.3 From 3bda058b0c39fc72188116d2fd71af08dd0fe5b0 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Wed, 23 Mar 2011 10:16:02 +0100 Subject: [S390] ccw_driver: remove duplicate members Remove the owner and name members of struct ccw_driver and convert all drivers to store this data in the embedded struct device_driver. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/ccwdev.h | 4 ---- drivers/s390/block/dasd_eckd.c | 6 ++++-- drivers/s390/block/dasd_fba.c | 6 ++++-- drivers/s390/char/con3215.c | 6 ++++-- drivers/s390/char/raw3270.c | 6 ++++-- drivers/s390/char/tape_34xx.c | 6 ++++-- drivers/s390/char/tape_3590.c | 6 ++++-- drivers/s390/char/vmur.c | 6 ++++-- drivers/s390/cio/device.c | 6 ++---- drivers/s390/net/claw.c | 6 ++++-- drivers/s390/net/ctcm_main.c | 6 ++++-- drivers/s390/net/lcs.c | 6 ++++-- drivers/s390/net/qeth_core_main.c | 4 +++- drivers/s390/scsi/zfcp_ccw.c | 6 ++++-- 14 files changed, 49 insertions(+), 31 deletions(-) diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h index ff6f62e0ec3e..623f2fb71774 100644 --- a/arch/s390/include/asm/ccwdev.h +++ b/arch/s390/include/asm/ccwdev.h @@ -112,7 +112,6 @@ enum uc_todo { /** * struct ccw driver - device driver for channel attached devices - * @owner: owning module * @ids: ids supported by this driver * @probe: function called on probe * @remove: function called on remove @@ -128,10 +127,8 @@ enum uc_todo { * @restore: callback for restoring after hibernation * @uc_handler: callback for unit check handler * @driver: embedded device driver structure - * @name: device driver name */ struct ccw_driver { - struct module *owner; struct ccw_device_id *ids; int (*probe) (struct ccw_device *); void (*remove) (struct ccw_device *); @@ -147,7 +144,6 @@ struct ccw_driver { int (*restore)(struct ccw_device *); enum uc_todo (*uc_handler) (struct ccw_device *, struct irb *); struct device_driver driver; - char *name; }; extern struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv, diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 379d8592bc6e..459f2cbe80fc 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -3982,8 +3982,10 @@ out_err: } static struct ccw_driver dasd_eckd_driver = { - .name = "dasd-eckd", - .owner = THIS_MODULE, + .driver = { + .name = "dasd-eckd", + .owner = THIS_MODULE, + }, .ids = dasd_eckd_ids, .probe = dasd_eckd_probe, .remove = dasd_generic_remove, diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index be89b3a893da..4b71b1164868 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -65,8 +65,10 @@ dasd_fba_set_online(struct ccw_device *cdev) } static struct ccw_driver dasd_fba_driver = { - .name = "dasd-fba", - .owner = THIS_MODULE, + .driver = { + .name = "dasd-fba", + .owner = THIS_MODULE, + }, .ids = dasd_fba_ids, .probe = dasd_fba_probe, .remove = dasd_generic_remove, diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 3fb4335d491d..694464c65fcd 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -764,8 +764,10 @@ static struct ccw_device_id raw3215_id[] = { }; static struct ccw_driver raw3215_ccw_driver = { - .name = "3215", - .owner = THIS_MODULE, + .driver = { + .name = "3215", + .owner = THIS_MODULE, + }, .ids = raw3215_id, .probe = &raw3215_probe, .remove = &raw3215_remove, diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 96ba2fd1c8ad..4c023761946f 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -1388,8 +1388,10 @@ static struct ccw_device_id raw3270_id[] = { }; static struct ccw_driver raw3270_ccw_driver = { - .name = "3270", - .owner = THIS_MODULE, + .driver = { + .name = "3270", + .owner = THIS_MODULE, + }, .ids = raw3270_id, .probe = &raw3270_probe, .remove = &raw3270_remove, diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index c26511171ffe..9eff2df70ddb 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c @@ -1320,8 +1320,10 @@ tape_34xx_online(struct ccw_device *cdev) } static struct ccw_driver tape_34xx_driver = { - .name = "tape_34xx", - .owner = THIS_MODULE, + .driver = { + .name = "tape_34xx", + .owner = THIS_MODULE, + }, .ids = tape_34xx_ids, .probe = tape_generic_probe, .remove = tape_generic_remove, diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index de2e99e0a71b..b98dcbd16711 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c @@ -1761,8 +1761,10 @@ tape_3590_online(struct ccw_device *cdev) } static struct ccw_driver tape_3590_driver = { - .name = "tape_3590", - .owner = THIS_MODULE, + .driver = { + .name = "tape_3590", + .owner = THIS_MODULE, + }, .ids = tape_3590_ids, .probe = tape_generic_probe, .remove = tape_generic_remove, diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index caef1757341d..f6b00c3df425 100644 --- a/drivers/s390/char/vmur.c +++ b/drivers/s390/char/vmur.c @@ -64,8 +64,10 @@ static int ur_set_offline(struct ccw_device *cdev); static int ur_pm_suspend(struct ccw_device *cdev); static struct ccw_driver ur_driver = { - .name = "vmur", - .owner = THIS_MODULE, + .driver = { + .name = "vmur", + .owner = THIS_MODULE, + }, .ids = ur_ids, .probe = ur_probe, .remove = ur_remove, diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index e50b12163afe..334459eb23c8 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -547,7 +547,7 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0) return -EAGAIN; - if (cdev->drv && !try_module_get(cdev->drv->owner)) { + if (cdev->drv && !try_module_get(cdev->drv->driver.owner)) { atomic_set(&cdev->private->onoff, 0); return -EINVAL; } @@ -573,7 +573,7 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, } out: if (cdev->drv) - module_put(cdev->drv->owner); + module_put(cdev->drv->driver.owner); atomic_set(&cdev->private->onoff, 0); return (ret < 0) ? ret : count; } @@ -1993,8 +1993,6 @@ int ccw_driver_register(struct ccw_driver *cdriver) struct device_driver *drv = &cdriver->driver; drv->bus = &ccw_bus_type; - drv->name = cdriver->name; - drv->owner = cdriver->owner; return driver_register(drv); } diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index ce3a5c13ce0b..2e2d2dfe78db 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -282,8 +282,10 @@ static struct ccw_device_id claw_ids[] = { MODULE_DEVICE_TABLE(ccw, claw_ids); static struct ccw_driver claw_ccw_driver = { - .owner = THIS_MODULE, - .name = "claw", + .driver = { + .owner = THIS_MODULE, + .name = "claw", + }, .ids = claw_ids, .probe = ccwgroup_probe_ccwdev, .remove = ccwgroup_remove_ccwdev, diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 4c2845985927..97fd4800ab12 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -1764,8 +1764,10 @@ static struct ccw_device_id ctcm_ids[] = { MODULE_DEVICE_TABLE(ccw, ctcm_ids); static struct ccw_driver ctcm_ccw_driver = { - .owner = THIS_MODULE, - .name = "ctcm", + .driver = { + .owner = THIS_MODULE, + .name = "ctcm", + }, .ids = ctcm_ids, .probe = ccwgroup_probe_ccwdev, .remove = ccwgroup_remove_ccwdev, diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 30b2a820e670..f59429c3bc30 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -2396,8 +2396,10 @@ static struct ccw_device_id lcs_ids[] = { MODULE_DEVICE_TABLE(ccw, lcs_ids); static struct ccw_driver lcs_ccw_driver = { - .owner = THIS_MODULE, - .name = "lcs", + .driver = { + .owner = THIS_MODULE, + .name = "lcs", + }, .ids = lcs_ids, .probe = ccwgroup_probe_ccwdev, .remove = ccwgroup_remove_ccwdev, diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 25eef304bd47..150b2cd99ba8 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -3902,7 +3902,9 @@ static struct ccw_device_id qeth_ids[] = { MODULE_DEVICE_TABLE(ccw, qeth_ids); static struct ccw_driver qeth_ccw_driver = { - .name = "qeth", + .driver = { + .name = "qeth", + }, .ids = qeth_ids, .probe = ccwgroup_probe_ccwdev, .remove = ccwgroup_remove_ccwdev, diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 4f7852dd30c7..e8b7cee62046 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -251,8 +251,10 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev) } struct ccw_driver zfcp_ccw_driver = { - .owner = THIS_MODULE, - .name = "zfcp", + .driver = { + .owner = THIS_MODULE, + .name = "zfcp", + }, .ids = zfcp_ccw_device_id, .probe = zfcp_ccw_probe, .remove = zfcp_ccw_remove, -- cgit v1.2.3 From d5ab5276baf9fd8b581cfbf41b10b6d4eae55960 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Wed, 23 Mar 2011 10:16:03 +0100 Subject: [S390] ccw_bus_type: make it static Make ccw_bus_type static. ccw_device drivers have to use ccw_driver_register. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device.c | 5 ++--- drivers/s390/cio/device.h | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 334459eb23c8..df14c51f6532 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -127,7 +127,7 @@ static int ccw_uevent(struct device *dev, struct kobj_uevent_env *env) return ret; } -struct bus_type ccw_bus_type; +static struct bus_type ccw_bus_type; static void io_subchannel_irq(struct subchannel *); static int io_subchannel_probe(struct subchannel *); @@ -1970,7 +1970,7 @@ static const struct dev_pm_ops ccw_pm_ops = { .restore = ccw_device_pm_restore, }; -struct bus_type ccw_bus_type = { +static struct bus_type ccw_bus_type = { .name = "ccw", .match = ccw_bus_match, .uevent = ccw_uevent, @@ -2110,5 +2110,4 @@ EXPORT_SYMBOL(ccw_device_set_offline); EXPORT_SYMBOL(ccw_driver_register); EXPORT_SYMBOL(ccw_driver_unregister); EXPORT_SYMBOL(get_ccwdev_by_busid); -EXPORT_SYMBOL(ccw_bus_type); EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id); diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 379de2d1ec49..7e297c7bb5ff 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h @@ -133,7 +133,6 @@ void ccw_device_set_notoper(struct ccw_device *cdev); /* qdio needs this. */ void ccw_device_set_timeout(struct ccw_device *, int); extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *); -extern struct bus_type ccw_bus_type; /* Channel measurement facility related */ void retry_set_schib(struct ccw_device *cdev); -- cgit v1.2.3 From 3c190c51f55eab691e5d096747262d2653e67de1 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Wed, 23 Mar 2011 10:16:04 +0100 Subject: [S390] ccwgroup_driver: remove duplicate members Remove the owner and name members of struct ccwgroup_driver and convert all drivers to store this data in the embedded struct device_driver. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/ccwgroup.h | 4 ---- drivers/s390/cio/ccwgroup.c | 6 ++---- drivers/s390/net/claw.c | 6 ++++-- drivers/s390/net/ctcm_main.c | 6 ++++-- drivers/s390/net/lcs.c | 6 ++++-- drivers/s390/net/qeth_core_main.c | 6 ++++-- 6 files changed, 18 insertions(+), 16 deletions(-) diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h index c79c1e787b86..f2ea2c56a7e1 100644 --- a/arch/s390/include/asm/ccwgroup.h +++ b/arch/s390/include/asm/ccwgroup.h @@ -29,8 +29,6 @@ struct ccwgroup_device { /** * struct ccwgroup_driver - driver for ccw group devices - * @owner: driver owner - * @name: driver name * @max_slaves: maximum number of slave devices * @driver_id: unique id * @probe: function called on probe @@ -46,8 +44,6 @@ struct ccwgroup_device { * @driver: embedded driver structure */ struct ccwgroup_driver { - struct module *owner; - char *name; int max_slaves; unsigned long driver_id; diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 2864581d8ecb..5c567414c4bb 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -428,7 +428,7 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const gdev = to_ccwgroupdev(dev); gdrv = to_ccwgroupdrv(dev->driver); - if (!try_module_get(gdrv->owner)) + if (!try_module_get(gdrv->driver.owner)) return -EINVAL; ret = strict_strtoul(buf, 0, &value); @@ -442,7 +442,7 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const else ret = -EINVAL; out: - module_put(gdrv->owner); + module_put(gdrv->driver.owner); return (ret == 0) ? count : ret; } @@ -616,8 +616,6 @@ int ccwgroup_driver_register(struct ccwgroup_driver *cdriver) { /* register our new driver with the core */ cdriver->driver.bus = &ccwgroup_bus_type; - cdriver->driver.name = cdriver->name; - cdriver->driver.owner = cdriver->owner; return driver_register(&cdriver->driver); } diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 2e2d2dfe78db..9feb62febb3d 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -264,8 +264,10 @@ static struct device *claw_root_dev; /* ccwgroup table */ static struct ccwgroup_driver claw_group_driver = { - .owner = THIS_MODULE, - .name = "claw", + .driver = { + .owner = THIS_MODULE, + .name = "claw", + }, .max_slaves = 2, .driver_id = 0xC3D3C1E6, .probe = claw_probe, diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 97fd4800ab12..c189296763a4 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -1774,8 +1774,10 @@ static struct ccw_driver ctcm_ccw_driver = { }; static struct ccwgroup_driver ctcm_group_driver = { - .owner = THIS_MODULE, - .name = CTC_DRIVER_NAME, + .driver = { + .owner = THIS_MODULE, + .name = CTC_DRIVER_NAME, + }, .max_slaves = 2, .driver_id = 0xC3E3C3D4, /* CTCM */ .probe = ctcm_probe_device, diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index f59429c3bc30..7fbc4adbb6d5 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -2409,8 +2409,10 @@ static struct ccw_driver lcs_ccw_driver = { * LCS ccwgroup driver registration */ static struct ccwgroup_driver lcs_group_driver = { - .owner = THIS_MODULE, - .name = "lcs", + .driver = { + .owner = THIS_MODULE, + .name = "lcs", + }, .max_slaves = 2, .driver_id = 0xD3C3E2, .probe = lcs_probe_device, diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 150b2cd99ba8..10a3a3b4dd3e 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -4430,8 +4430,10 @@ static int qeth_core_restore(struct ccwgroup_device *gdev) } static struct ccwgroup_driver qeth_core_ccwgroup_driver = { - .owner = THIS_MODULE, - .name = "qeth", + .driver = { + .owner = THIS_MODULE, + .name = "qeth", + }, .driver_id = 0xD8C5E3C8, .probe = qeth_core_probe_device, .remove = qeth_core_remove_device, -- cgit v1.2.3 From a2c9dbe8dbb8591ae6fd142e562813cd95d06609 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 23 Mar 2011 10:16:05 +0100 Subject: [S390] xchg/cmpxchg: move to own header file Move xchg() and cmpxchg() functions to own header file like some other architectures have done. With this we make sure that system.h now really looks like a place where everything is gathered that doesn't fit anywhere else. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/cmpxchg.h | 205 ++++++++++++++++++++++++++++++++++++++++ arch/s390/include/asm/system.h | 196 +------------------------------------- 2 files changed, 206 insertions(+), 195 deletions(-) create mode 100644 arch/s390/include/asm/cmpxchg.h diff --git a/arch/s390/include/asm/cmpxchg.h b/arch/s390/include/asm/cmpxchg.h new file mode 100644 index 000000000000..4052df9030cb --- /dev/null +++ b/arch/s390/include/asm/cmpxchg.h @@ -0,0 +1,205 @@ +/* + * Copyright IBM Corp. 1999, 2011 + * + * Author(s): Martin Schwidefsky , + */ + +#ifndef __ASM_CMPXCHG_H +#define __ASM_CMPXCHG_H + +#include + +extern void __xchg_called_with_bad_pointer(void); + +static inline unsigned long __xchg(unsigned long x, void *ptr, int size) +{ + unsigned long addr, old; + int shift; + + switch (size) { + case 1: + addr = (unsigned long) ptr; + shift = (3 ^ (addr & 3)) << 3; + addr ^= addr & 3; + asm volatile( + " l %0,%4\n" + "0: lr 0,%0\n" + " nr 0,%3\n" + " or 0,%2\n" + " cs %0,0,%4\n" + " jl 0b\n" + : "=&d" (old), "=Q" (*(int *) addr) + : "d" (x << shift), "d" (~(255 << shift)), + "Q" (*(int *) addr) : "memory", "cc", "0"); + return old >> shift; + case 2: + addr = (unsigned long) ptr; + shift = (2 ^ (addr & 2)) << 3; + addr ^= addr & 2; + asm volatile( + " l %0,%4\n" + "0: lr 0,%0\n" + " nr 0,%3\n" + " or 0,%2\n" + " cs %0,0,%4\n" + " jl 0b\n" + : "=&d" (old), "=Q" (*(int *) addr) + : "d" (x << shift), "d" (~(65535 << shift)), + "Q" (*(int *) addr) : "memory", "cc", "0"); + return old >> shift; + case 4: + asm volatile( + " l %0,%3\n" + "0: cs %0,%2,%3\n" + " jl 0b\n" + : "=&d" (old), "=Q" (*(int *) ptr) + : "d" (x), "Q" (*(int *) ptr) + : "memory", "cc"); + return old; +#ifdef CONFIG_64BIT + case 8: + asm volatile( + " lg %0,%3\n" + "0: csg %0,%2,%3\n" + " jl 0b\n" + : "=&d" (old), "=m" (*(long *) ptr) + : "d" (x), "Q" (*(long *) ptr) + : "memory", "cc"); + return old; +#endif /* CONFIG_64BIT */ + } + __xchg_called_with_bad_pointer(); + return x; +} + +#define xchg(ptr, x) \ +({ \ + __typeof__(*(ptr)) __ret; \ + __ret = (__typeof__(*(ptr))) \ + __xchg((unsigned long)(x), (void *)(ptr), sizeof(*(ptr)));\ + __ret; \ +}) + +/* + * Atomic compare and exchange. Compare OLD with MEM, if identical, + * store NEW in MEM. Return the initial value in MEM. Success is + * indicated by comparing RETURN with OLD. + */ + +#define __HAVE_ARCH_CMPXCHG + +extern void __cmpxchg_called_with_bad_pointer(void); + +static inline unsigned long __cmpxchg(void *ptr, unsigned long old, + unsigned long new, int size) +{ + unsigned long addr, prev, tmp; + int shift; + + switch (size) { + case 1: + addr = (unsigned long) ptr; + shift = (3 ^ (addr & 3)) << 3; + addr ^= addr & 3; + asm volatile( + " l %0,%2\n" + "0: nr %0,%5\n" + " lr %1,%0\n" + " or %0,%3\n" + " or %1,%4\n" + " cs %0,%1,%2\n" + " jnl 1f\n" + " xr %1,%0\n" + " nr %1,%5\n" + " jnz 0b\n" + "1:" + : "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr) + : "d" (old << shift), "d" (new << shift), + "d" (~(255 << shift)), "Q" (*(int *) ptr) + : "memory", "cc"); + return prev >> shift; + case 2: + addr = (unsigned long) ptr; + shift = (2 ^ (addr & 2)) << 3; + addr ^= addr & 2; + asm volatile( + " l %0,%2\n" + "0: nr %0,%5\n" + " lr %1,%0\n" + " or %0,%3\n" + " or %1,%4\n" + " cs %0,%1,%2\n" + " jnl 1f\n" + " xr %1,%0\n" + " nr %1,%5\n" + " jnz 0b\n" + "1:" + : "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr) + : "d" (old << shift), "d" (new << shift), + "d" (~(65535 << shift)), "Q" (*(int *) ptr) + : "memory", "cc"); + return prev >> shift; + case 4: + asm volatile( + " cs %0,%3,%1\n" + : "=&d" (prev), "=Q" (*(int *) ptr) + : "0" (old), "d" (new), "Q" (*(int *) ptr) + : "memory", "cc"); + return prev; +#ifdef CONFIG_64BIT + case 8: + asm volatile( + " csg %0,%3,%1\n" + : "=&d" (prev), "=Q" (*(long *) ptr) + : "0" (old), "d" (new), "Q" (*(long *) ptr) + : "memory", "cc"); + return prev; +#endif /* CONFIG_64BIT */ + } + __cmpxchg_called_with_bad_pointer(); + return old; +} + +#define cmpxchg(ptr, o, n) \ + ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \ + (unsigned long)(n), sizeof(*(ptr)))) + +#include + +static inline unsigned long __cmpxchg_local(void *ptr, + unsigned long old, + unsigned long new, int size) +{ + switch (size) { + case 1: + case 2: + case 4: +#ifdef CONFIG_64BIT + case 8: +#endif + return __cmpxchg(ptr, old, new, size); + default: + return __cmpxchg_local_generic(ptr, old, new, size); + } + + return old; +} + +/* + * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make + * them available. + */ +#define cmpxchg_local(ptr, o, n) \ + ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \ + (unsigned long)(n), sizeof(*(ptr)))) +#ifdef CONFIG_64BIT +#define cmpxchg64_local(ptr, o, n) \ +({ \ + BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ + cmpxchg_local((ptr), (o), (n)); \ +}) +#else +#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) +#endif + +#endif /* __ASM_CMPXCHG_H */ diff --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h index 8f8d759f6a7b..d382629a0172 100644 --- a/arch/s390/include/asm/system.h +++ b/arch/s390/include/asm/system.h @@ -14,6 +14,7 @@ #include #include #include +#include #ifdef __KERNEL__ @@ -120,161 +121,6 @@ extern int memcpy_real(void *, void *, size_t); #define nop() asm volatile("nop") -#define xchg(ptr,x) \ -({ \ - __typeof__(*(ptr)) __ret; \ - __ret = (__typeof__(*(ptr))) \ - __xchg((unsigned long)(x), (void *)(ptr),sizeof(*(ptr))); \ - __ret; \ -}) - -extern void __xchg_called_with_bad_pointer(void); - -static inline unsigned long __xchg(unsigned long x, void * ptr, int size) -{ - unsigned long addr, old; - int shift; - - switch (size) { - case 1: - addr = (unsigned long) ptr; - shift = (3 ^ (addr & 3)) << 3; - addr ^= addr & 3; - asm volatile( - " l %0,%4\n" - "0: lr 0,%0\n" - " nr 0,%3\n" - " or 0,%2\n" - " cs %0,0,%4\n" - " jl 0b\n" - : "=&d" (old), "=Q" (*(int *) addr) - : "d" (x << shift), "d" (~(255 << shift)), - "Q" (*(int *) addr) : "memory", "cc", "0"); - return old >> shift; - case 2: - addr = (unsigned long) ptr; - shift = (2 ^ (addr & 2)) << 3; - addr ^= addr & 2; - asm volatile( - " l %0,%4\n" - "0: lr 0,%0\n" - " nr 0,%3\n" - " or 0,%2\n" - " cs %0,0,%4\n" - " jl 0b\n" - : "=&d" (old), "=Q" (*(int *) addr) - : "d" (x << shift), "d" (~(65535 << shift)), - "Q" (*(int *) addr) : "memory", "cc", "0"); - return old >> shift; - case 4: - asm volatile( - " l %0,%3\n" - "0: cs %0,%2,%3\n" - " jl 0b\n" - : "=&d" (old), "=Q" (*(int *) ptr) - : "d" (x), "Q" (*(int *) ptr) - : "memory", "cc"); - return old; -#ifdef __s390x__ - case 8: - asm volatile( - " lg %0,%3\n" - "0: csg %0,%2,%3\n" - " jl 0b\n" - : "=&d" (old), "=m" (*(long *) ptr) - : "d" (x), "Q" (*(long *) ptr) - : "memory", "cc"); - return old; -#endif /* __s390x__ */ - } - __xchg_called_with_bad_pointer(); - return x; -} - -/* - * Atomic compare and exchange. Compare OLD with MEM, if identical, - * store NEW in MEM. Return the initial value in MEM. Success is - * indicated by comparing RETURN with OLD. - */ - -#define __HAVE_ARCH_CMPXCHG 1 - -#define cmpxchg(ptr, o, n) \ - ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \ - (unsigned long)(n), sizeof(*(ptr)))) - -extern void __cmpxchg_called_with_bad_pointer(void); - -static inline unsigned long -__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) -{ - unsigned long addr, prev, tmp; - int shift; - - switch (size) { - case 1: - addr = (unsigned long) ptr; - shift = (3 ^ (addr & 3)) << 3; - addr ^= addr & 3; - asm volatile( - " l %0,%2\n" - "0: nr %0,%5\n" - " lr %1,%0\n" - " or %0,%3\n" - " or %1,%4\n" - " cs %0,%1,%2\n" - " jnl 1f\n" - " xr %1,%0\n" - " nr %1,%5\n" - " jnz 0b\n" - "1:" - : "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr) - : "d" (old << shift), "d" (new << shift), - "d" (~(255 << shift)), "Q" (*(int *) ptr) - : "memory", "cc"); - return prev >> shift; - case 2: - addr = (unsigned long) ptr; - shift = (2 ^ (addr & 2)) << 3; - addr ^= addr & 2; - asm volatile( - " l %0,%2\n" - "0: nr %0,%5\n" - " lr %1,%0\n" - " or %0,%3\n" - " or %1,%4\n" - " cs %0,%1,%2\n" - " jnl 1f\n" - " xr %1,%0\n" - " nr %1,%5\n" - " jnz 0b\n" - "1:" - : "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr) - : "d" (old << shift), "d" (new << shift), - "d" (~(65535 << shift)), "Q" (*(int *) ptr) - : "memory", "cc"); - return prev >> shift; - case 4: - asm volatile( - " cs %0,%3,%1\n" - : "=&d" (prev), "=Q" (*(int *) ptr) - : "0" (old), "d" (new), "Q" (*(int *) ptr) - : "memory", "cc"); - return prev; -#ifdef __s390x__ - case 8: - asm volatile( - " csg %0,%3,%1\n" - : "=&d" (prev), "=Q" (*(long *) ptr) - : "0" (old), "d" (new), "Q" (*(long *) ptr) - : "memory", "cc"); - return prev; -#endif /* __s390x__ */ - } - __cmpxchg_called_with_bad_pointer(); - return old; -} - /* * Force strict CPU ordering. * And yes, this is required on UP too when we're talking @@ -353,46 +199,6 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) __ctl_load(__dummy, cr, cr); \ }) -#include - -#include - -static inline unsigned long __cmpxchg_local(volatile void *ptr, - unsigned long old, - unsigned long new, int size) -{ - switch (size) { - case 1: - case 2: - case 4: -#ifdef __s390x__ - case 8: -#endif - return __cmpxchg(ptr, old, new, size); - default: - return __cmpxchg_local_generic(ptr, old, new, size); - } - - return old; -} - -/* - * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make - * them available. - */ -#define cmpxchg_local(ptr, o, n) \ - ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \ - (unsigned long)(n), sizeof(*(ptr)))) -#ifdef __s390x__ -#define cmpxchg64_local(ptr, o, n) \ - ({ \ - BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ - cmpxchg_local((ptr), (o), (n)); \ - }) -#else -#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) -#endif - /* * Use to set psw mask except for the first byte which * won't be changed by this function. -- cgit v1.2.3 From 54eaae3028e6b09de0bd2232a8176fc0d0a2397a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 23 Mar 2011 10:16:06 +0100 Subject: [S390] cmpxchg: implement cmpxchg64() We have a cmpxchg64_local() implementation but strange enough the SMP capable variant cmpxchg64() is missing. So implement it. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/cmpxchg.h | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/arch/s390/include/asm/cmpxchg.h b/arch/s390/include/asm/cmpxchg.h index 4052df9030cb..7488e52efa97 100644 --- a/arch/s390/include/asm/cmpxchg.h +++ b/arch/s390/include/asm/cmpxchg.h @@ -164,6 +164,33 @@ static inline unsigned long __cmpxchg(void *ptr, unsigned long old, ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \ (unsigned long)(n), sizeof(*(ptr)))) +#ifdef CONFIG_64BIT +#define cmpxchg64(ptr, o, n) \ +({ \ + BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ + cmpxchg((ptr), (o), (n)); \ +}) +#else /* CONFIG_64BIT */ +static inline unsigned long long __cmpxchg64(void *ptr, + unsigned long long old, + unsigned long long new) +{ + register_pair rp_old = {.pair = old}; + register_pair rp_new = {.pair = new}; + + asm volatile( + " cds %0,%2,%1" + : "+&d" (rp_old), "=Q" (ptr) + : "d" (rp_new), "Q" (ptr) + : "cc"); + return rp_old.pair; +} +#define cmpxchg64(ptr, o, n) \ + ((__typeof__(*(ptr)))__cmpxchg64((ptr), \ + (unsigned long long)(o), \ + (unsigned long long)(n))) +#endif /* CONFIG_64BIT */ + #include static inline unsigned long __cmpxchg_local(void *ptr, @@ -192,14 +219,7 @@ static inline unsigned long __cmpxchg_local(void *ptr, #define cmpxchg_local(ptr, o, n) \ ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \ (unsigned long)(n), sizeof(*(ptr)))) -#ifdef CONFIG_64BIT -#define cmpxchg64_local(ptr, o, n) \ -({ \ - BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ - cmpxchg_local((ptr), (o), (n)); \ -}) -#else -#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) -#endif + +#define cmpxchg64_local(ptr, o, n) cmpxchg64((ptr), (o), (n)) #endif /* __ASM_CMPXCHG_H */ -- cgit v1.2.3