diff options
Diffstat (limited to 'arch/mn10300/lib/checksum.c')
-rw-r--r-- | arch/mn10300/lib/checksum.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/arch/mn10300/lib/checksum.c b/arch/mn10300/lib/checksum.c new file mode 100644 index 000000000000..274f29ec33c1 --- /dev/null +++ b/arch/mn10300/lib/checksum.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* MN10300 Optimised checksumming wrappers | ||
2 | * | ||
3 | * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd. | ||
4 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
5 | * Written by David Howells (dhowells@redhat.com) | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public Licence | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the Licence, or (at your option) any later version. | ||
11 | */ | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/errno.h> | ||
14 | #include <asm/byteorder.h> | ||
15 | #include <asm/uaccess.h> | ||
16 | #include <asm/checksum.h> | ||
17 | #include "internal.h" | ||
18 | |||
19 | static inline unsigned short from32to16(__wsum sum) | ||
20 | { | ||
21 | asm(" add %1,%0 \n" | ||
22 | " addc 0xffff,%0 \n" | ||
23 | : "=r" (sum) | ||
24 | : "r" (sum << 16), "0" (sum & 0xffff0000) | ||
25 | ); | ||
26 | return sum >> 16; | ||
27 | } | ||
28 | |||
29 | __sum16 ip_fast_csum(const void *iph, unsigned int ihl) | ||
30 | { | ||
31 | return ~do_csum(iph, ihl * 4); | ||
32 | } | ||
33 | EXPORT_SYMBOL(ip_fast_csum); | ||
34 | |||
35 | __wsum csum_partial(const void *buff, int len, __wsum sum) | ||
36 | { | ||
37 | __wsum result; | ||
38 | |||
39 | result = do_csum(buff, len); | ||
40 | result += sum; | ||
41 | if (sum > result) | ||
42 | result++; | ||
43 | return result; | ||
44 | } | ||
45 | EXPORT_SYMBOL(csum_partial); | ||
46 | |||
47 | __sum16 ip_compute_csum(const void *buff, int len) | ||
48 | { | ||
49 | return ~from32to16(do_csum(buff, len)); | ||
50 | } | ||
51 | EXPORT_SYMBOL(ip_compute_csum); | ||
52 | |||
53 | __wsum csum_partial_copy(const void *src, void *dst, int len, __wsum sum) | ||
54 | { | ||
55 | copy_from_user(dst, src, len); | ||
56 | return csum_partial(dst, len, sum); | ||
57 | } | ||
58 | EXPORT_SYMBOL(csum_partial_copy); | ||
59 | |||
60 | __wsum csum_partial_copy_nocheck(const void *src, void *dst, | ||
61 | int len, __wsum sum) | ||
62 | { | ||
63 | sum = csum_partial(src, len, sum); | ||
64 | memcpy(dst, src, len); | ||
65 | return sum; | ||
66 | } | ||
67 | EXPORT_SYMBOL(csum_partial_copy_nocheck); | ||
68 | |||
69 | __wsum csum_partial_copy_from_user(const void *src, void *dst, | ||
70 | int len, __wsum sum, | ||
71 | int *err_ptr) | ||
72 | { | ||
73 | int missing; | ||
74 | |||
75 | missing = copy_from_user(dst, src, len); | ||
76 | if (missing) { | ||
77 | memset(dst + len - missing, 0, missing); | ||
78 | *err_ptr = -EFAULT; | ||
79 | } | ||
80 | |||
81 | return csum_partial(dst, len, sum); | ||
82 | } | ||
83 | EXPORT_SYMBOL(csum_partial_copy_from_user); | ||
84 | |||
85 | __wsum csum_and_copy_to_user(const void *src, void *dst, | ||
86 | int len, __wsum sum, | ||
87 | int *err_ptr) | ||
88 | { | ||
89 | int missing; | ||
90 | |||
91 | missing = copy_to_user(dst, src, len); | ||
92 | if (missing) { | ||
93 | memset(dst + len - missing, 0, missing); | ||
94 | *err_ptr = -EFAULT; | ||
95 | } | ||
96 | |||
97 | return csum_partial(src, len, sum); | ||
98 | } | ||
99 | EXPORT_SYMBOL(csum_and_copy_to_user); | ||