From 019d6bec6d2842729c477f433b2330e9f52c0f1a Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 12 Oct 2015 10:51:54 +0200 Subject: [PATCH] s390/zcore: simplify memcpy_hsa Replace the three part copy logic int memcpy_hsa with a single loop around sclp_sdias_copy with appropriate offset and size calculations, and inline memcpy_hsa into memcpy_hsa_user and memcpy_hsa_kernel. Acked-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- drivers/s390/char/zcore.c | 101 +++++++++++++++------------------------------- 1 file changed, 33 insertions(+), 68 deletions(-) diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 4fa4557..7d94c69 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -34,8 +34,6 @@ #define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x) -#define TO_USER 1 -#define TO_KERNEL 0 #define CHUNK_INFO_SIZE 34 /* 2 16-byte char, each followed by blank */ enum arch_id { @@ -56,89 +54,39 @@ static struct dentry *zcore_reipl_file; static struct dentry *zcore_hsa_file; static struct ipl_parameter_block *ipl_block; +static char hsa_buf[PAGE_SIZE] __aligned(PAGE_SIZE); + /* - * Copy memory from HSA to kernel or user memory (not reentrant): + * Copy memory from HSA to user memory (not reentrant): * - * @dest: Kernel or user buffer where memory should be copied to + * @dest: User buffer where memory should be copied to * @src: Start address within HSA where data should be copied * @count: Size of buffer, which should be copied - * @mode: Either TO_KERNEL or TO_USER */ -static int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode) +int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count) { - int offs, blk_num; - static char buf[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); + unsigned long offset, bytes; if (!hsa_available) return -ENODATA; - if (count == 0) - return 0; - - /* copy first block */ - offs = 0; - if ((src % PAGE_SIZE) != 0) { - blk_num = src / PAGE_SIZE + 2; - if (sclp_sdias_copy(buf, blk_num, 1)) { - TRACE("sclp_sdias_copy() failed\n"); - return -EIO; - } - offs = min((PAGE_SIZE - (src % PAGE_SIZE)), count); - if (mode == TO_USER) { - if (copy_to_user((__force __user void*) dest, - buf + (src % PAGE_SIZE), offs)) - return -EFAULT; - } else - memcpy(dest, buf + (src % PAGE_SIZE), offs); - } - if (offs == count) - goto out; - /* copy middle */ - for (; (offs + PAGE_SIZE) <= count; offs += PAGE_SIZE) { - blk_num = (src + offs) / PAGE_SIZE + 2; - if (sclp_sdias_copy(buf, blk_num, 1)) { + while (count) { + if (sclp_sdias_copy(hsa_buf, src / PAGE_SIZE + 2, 1)) { TRACE("sclp_sdias_copy() failed\n"); return -EIO; } - if (mode == TO_USER) { - if (copy_to_user((__force __user void*) dest + offs, - buf, PAGE_SIZE)) - return -EFAULT; - } else - memcpy(dest + offs, buf, PAGE_SIZE); - } - if (offs == count) - goto out; - - /* copy last block */ - blk_num = (src + offs) / PAGE_SIZE + 2; - if (sclp_sdias_copy(buf, blk_num, 1)) { - TRACE("sclp_sdias_copy() failed\n"); - return -EIO; - } - if (mode == TO_USER) { - if (copy_to_user((__force __user void*) dest + offs, buf, - count - offs)) + offset = src % PAGE_SIZE; + bytes = min(PAGE_SIZE - offset, count); + if (copy_to_user(dest, hsa_buf + offset, bytes)) return -EFAULT; - } else - memcpy(dest + offs, buf, count - offs); -out: + src += bytes; + dest += bytes; + count -= bytes; + } return 0; } /* - * Copy memory from HSA to user memory (not reentrant): - * - * @dest: Kernel or user buffer where memory should be copied to - * @src: Start address within HSA where data should be copied - * @count: Size of buffer, which should be copied - */ -int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count) -{ - return memcpy_hsa((void __force *) dest, src, count, TO_USER); -} - -/* * Copy memory from HSA to kernel memory (not reentrant): * * @dest: Kernel or user buffer where memory should be copied to @@ -147,7 +95,24 @@ int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count) */ int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count) { - return memcpy_hsa(dest, src, count, TO_KERNEL); + unsigned long offset, bytes; + + if (!hsa_available) + return -ENODATA; + + while (count) { + if (sclp_sdias_copy(hsa_buf, src / PAGE_SIZE + 2, 1)) { + TRACE("sclp_sdias_copy() failed\n"); + return -EIO; + } + offset = src % PAGE_SIZE; + bytes = min(PAGE_SIZE - offset, count); + memcpy(dest, hsa_buf + offset, bytes); + src += bytes; + dest += bytes; + count -= bytes; + } + return 0; } static int __init init_cpu_info(void) -- 2.7.4