diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2020-07-20 03:56:07 +0200 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2020-08-20 21:45:22 +0200 |
commit | daf52375c19feb4397cfd883302a7c907de2d6ad (patch) | |
tree | d8b45999cca84afbc0065cc2fc16aa7abddd035d /arch/x86/lib/csum-wrappers_64.c | |
parent | sparc64: propagate the calling convention changes down to __csum_partial_copy... (diff) | |
download | linux-daf52375c19feb4397cfd883302a7c907de2d6ad.tar.xz linux-daf52375c19feb4397cfd883302a7c907de2d6ad.zip |
amd64: switch csum_partial_copy_generic() to new calling conventions
... and fold handling of misaligned case into it.
Implementation note: we stash the "will we need to rol8 the sum in the end"
flag into the MSB of %rcx (the lower 32 bits are used for length); the rest
is pretty straightforward.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/x86/lib/csum-wrappers_64.c')
-rw-r--r-- | arch/x86/lib/csum-wrappers_64.c | 72 |
1 files changed, 9 insertions, 63 deletions
diff --git a/arch/x86/lib/csum-wrappers_64.c b/arch/x86/lib/csum-wrappers_64.c index ae2fb87e2274..189344924a2b 100644 --- a/arch/x86/lib/csum-wrappers_64.c +++ b/arch/x86/lib/csum-wrappers_64.c @@ -21,49 +21,16 @@ * src and dst are best aligned to 64bits. */ __wsum -csum_and_copy_from_user(const void __user *src, void *dst, - int len) +csum_and_copy_from_user(const void __user *src, void *dst, int len) { - int err = 0; - __wsum isum = ~0U; + __wsum sum; might_sleep(); - if (!user_access_begin(src, len)) return 0; - - /* - * Why 6, not 7? To handle odd addresses aligned we - * would need to do considerable complications to fix the - * checksum which is defined as an 16bit accumulator. The - * fix alignment code is primarily for performance - * compatibility with 32bit and that will handle odd - * addresses slowly too. - */ - if (unlikely((unsigned long)src & 6)) { - while (((unsigned long)src & 6) && len >= 2) { - __u16 val16; - - unsafe_get_user(val16, (const __u16 __user *)src, out); - - *(__u16 *)dst = val16; - isum = (__force __wsum)add32_with_carry( - (__force unsigned)isum, val16); - src += 2; - dst += 2; - len -= 2; - } - } - isum = csum_partial_copy_generic((__force const void *)src, - dst, len, isum, &err, NULL); - user_access_end(); - if (unlikely(err)) - isum = 0; - return isum; - -out: + sum = csum_partial_copy_generic((__force const void *)src, dst, len); user_access_end(); - return 0; + return sum; } EXPORT_SYMBOL(csum_and_copy_from_user); @@ -79,37 +46,16 @@ EXPORT_SYMBOL(csum_and_copy_from_user); * src and dst are best aligned to 64bits. */ __wsum -csum_and_copy_to_user(const void *src, void __user *dst, - int len) +csum_and_copy_to_user(const void *src, void __user *dst, int len) { - __wsum ret, isum = ~0U; - int err = 0; + __wsum sum; might_sleep(); - if (!user_access_begin(dst, len)) return 0; - - if (unlikely((unsigned long)dst & 6)) { - while (((unsigned long)dst & 6) && len >= 2) { - __u16 val16 = *(__u16 *)src; - - isum = (__force __wsum)add32_with_carry( - (__force unsigned)isum, val16); - unsafe_put_user(val16, (__u16 __user *)dst, out); - src += 2; - dst += 2; - len -= 2; - } - } - - ret = csum_partial_copy_generic(src, (void __force *)dst, - len, isum, NULL, &err); - user_access_end(); - return err ? 0 : ret; -out: + sum = csum_partial_copy_generic(src, (void __force *)dst, len); user_access_end(); - return 0; + return sum; } EXPORT_SYMBOL(csum_and_copy_to_user); @@ -125,7 +71,7 @@ EXPORT_SYMBOL(csum_and_copy_to_user); __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len) { - return csum_partial_copy_generic(src, dst, len, 0, NULL, NULL); + return csum_partial_copy_generic(src, dst, len); } EXPORT_SYMBOL(csum_partial_copy_nocheck); |