diff options
| author | Anton Blanchard <anton@samba.org> | 2010-08-02 16:11:36 -0400 |
|---|---|---|
| committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-09-02 00:07:30 -0400 |
| commit | 8c77391475bc3284a380fc46aaf0bcf26bde3ae6 (patch) | |
| tree | 0948ebdf02ce03948faf8dc41af8414f84652239 /arch/powerpc/lib | |
| parent | fdd374b62ca4df144c0138359dcffa83df7a0ea8 (diff) | |
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>
Diffstat (limited to 'arch/powerpc/lib')
| -rw-r--r-- | arch/powerpc/lib/checksum_wrappers_64.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/arch/powerpc/lib/checksum_wrappers_64.c b/arch/powerpc/lib/checksum_wrappers_64.c index 614cff1a8e0..769b817fbb3 100644 --- a/arch/powerpc/lib/checksum_wrappers_64.c +++ b/arch/powerpc/lib/checksum_wrappers_64.c | |||
| @@ -63,3 +63,40 @@ out: | |||
| 63 | return (__force __wsum)csum; | 63 | return (__force __wsum)csum; |
| 64 | } | 64 | } |
| 65 | EXPORT_SYMBOL(csum_and_copy_from_user); | 65 | EXPORT_SYMBOL(csum_and_copy_from_user); |
| 66 | |||
| 67 | __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len, | ||
| 68 | __wsum sum, int *err_ptr) | ||
| 69 | { | ||
| 70 | unsigned int csum; | ||
| 71 | |||
| 72 | might_sleep(); | ||
| 73 | |||
| 74 | *err_ptr = 0; | ||
| 75 | |||
| 76 | if (!len) { | ||
| 77 | csum = 0; | ||
| 78 | goto out; | ||
| 79 | } | ||
| 80 | |||
| 81 | if (unlikely((len < 0) || !access_ok(VERIFY_WRITE, dst, len))) { | ||
| 82 | *err_ptr = -EFAULT; | ||
| 83 | csum = -1; /* invalid checksum */ | ||
| 84 | goto out; | ||
| 85 | } | ||
| 86 | |||
| 87 | csum = csum_partial_copy_generic(src, (void __force *)dst, | ||
| 88 | len, sum, NULL, err_ptr); | ||
| 89 | |||
| 90 | if (unlikely(*err_ptr)) { | ||
| 91 | csum = csum_partial(src, len, sum); | ||
| 92 | |||
| 93 | if (copy_to_user(dst, src, len)) { | ||
| 94 | *err_ptr = -EFAULT; | ||
| 95 | csum = -1; /* invalid checksum */ | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 99 | out: | ||
| 100 | return (__force __wsum)csum; | ||
| 101 | } | ||
| 102 | EXPORT_SYMBOL(csum_and_copy_to_user); | ||
