powerpc: Add 64bit csum_and_copy_to_user
This adds the equivalent of csum_and_copy_from_user for the receive side so we can copy and checksum in one pass. It is modelled on the generic checksum routine. Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
fdd374b62c
commit
8c77391475
@ -57,6 +57,9 @@ extern __wsum csum_partial_copy_generic(const void *src, void *dst,
|
|||||||
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
|
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
|
||||||
extern __wsum csum_and_copy_from_user(const void __user *src, void *dst,
|
extern __wsum csum_and_copy_from_user(const void __user *src, void *dst,
|
||||||
int len, __wsum sum, int *err_ptr);
|
int len, __wsum sum, int *err_ptr);
|
||||||
|
#define HAVE_CSUM_COPY_USER
|
||||||
|
extern __wsum csum_and_copy_to_user(const void *src, void __user *dst,
|
||||||
|
int len, __wsum sum, int *err_ptr);
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
* the same as csum_partial, but copies from src to dst while it
|
* the same as csum_partial, but copies from src to dst while it
|
||||||
|
@ -63,3 +63,40 @@ __wsum csum_and_copy_from_user(const void __user *src, void *dst,
|
|||||||
return (__force __wsum)csum;
|
return (__force __wsum)csum;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(csum_and_copy_from_user);
|
EXPORT_SYMBOL(csum_and_copy_from_user);
|
||||||
|
|
||||||
|
__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
|
||||||
|
__wsum sum, int *err_ptr)
|
||||||
|
{
|
||||||
|
unsigned int csum;
|
||||||
|
|
||||||
|
might_sleep();
|
||||||
|
|
||||||
|
*err_ptr = 0;
|
||||||
|
|
||||||
|
if (!len) {
|
||||||
|
csum = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely((len < 0) || !access_ok(VERIFY_WRITE, dst, len))) {
|
||||||
|
*err_ptr = -EFAULT;
|
||||||
|
csum = -1; /* invalid checksum */
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
csum = csum_partial_copy_generic(src, (void __force *)dst,
|
||||||
|
len, sum, NULL, err_ptr);
|
||||||
|
|
||||||
|
if (unlikely(*err_ptr)) {
|
||||||
|
csum = csum_partial(src, len, sum);
|
||||||
|
|
||||||
|
if (copy_to_user(dst, src, len)) {
|
||||||
|
*err_ptr = -EFAULT;
|
||||||
|
csum = -1; /* invalid checksum */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return (__force __wsum)csum;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(csum_and_copy_to_user);
|
||||||
|
Loading…
Reference in New Issue
Block a user