]>
Commit | Line | Data |
---|---|---|
b920de1b DH |
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> | |
7c0f6ba6 | 15 | #include <linux/uaccess.h> |
b920de1b DH |
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) | |
d6bb7a1a | 25 | : "cc" |
b920de1b DH |
26 | ); |
27 | return sum >> 16; | |
28 | } | |
29 | ||
30 | __sum16 ip_fast_csum(const void *iph, unsigned int ihl) | |
31 | { | |
32 | return ~do_csum(iph, ihl * 4); | |
33 | } | |
34 | EXPORT_SYMBOL(ip_fast_csum); | |
35 | ||
36 | __wsum csum_partial(const void *buff, int len, __wsum sum) | |
37 | { | |
38 | __wsum result; | |
39 | ||
40 | result = do_csum(buff, len); | |
41 | result += sum; | |
42 | if (sum > result) | |
43 | result++; | |
44 | return result; | |
45 | } | |
46 | EXPORT_SYMBOL(csum_partial); | |
47 | ||
48 | __sum16 ip_compute_csum(const void *buff, int len) | |
49 | { | |
50 | return ~from32to16(do_csum(buff, len)); | |
51 | } | |
52 | EXPORT_SYMBOL(ip_compute_csum); | |
53 | ||
54 | __wsum csum_partial_copy(const void *src, void *dst, int len, __wsum sum) | |
55 | { | |
56 | copy_from_user(dst, src, len); | |
57 | return csum_partial(dst, len, sum); | |
58 | } | |
59 | EXPORT_SYMBOL(csum_partial_copy); | |
60 | ||
61 | __wsum csum_partial_copy_nocheck(const void *src, void *dst, | |
62 | int len, __wsum sum) | |
63 | { | |
64 | sum = csum_partial(src, len, sum); | |
65 | memcpy(dst, src, len); | |
66 | return sum; | |
67 | } | |
68 | EXPORT_SYMBOL(csum_partial_copy_nocheck); | |
69 | ||
70 | __wsum csum_partial_copy_from_user(const void *src, void *dst, | |
71 | int len, __wsum sum, | |
72 | int *err_ptr) | |
73 | { | |
74 | int missing; | |
75 | ||
76 | missing = copy_from_user(dst, src, len); | |
77 | if (missing) { | |
78 | memset(dst + len - missing, 0, missing); | |
79 | *err_ptr = -EFAULT; | |
80 | } | |
81 | ||
82 | return csum_partial(dst, len, sum); | |
83 | } | |
84 | EXPORT_SYMBOL(csum_partial_copy_from_user); | |
85 | ||
86 | __wsum csum_and_copy_to_user(const void *src, void *dst, | |
87 | int len, __wsum sum, | |
88 | int *err_ptr) | |
89 | { | |
90 | int missing; | |
91 | ||
92 | missing = copy_to_user(dst, src, len); | |
93 | if (missing) { | |
94 | memset(dst + len - missing, 0, missing); | |
95 | *err_ptr = -EFAULT; | |
96 | } | |
97 | ||
98 | return csum_partial(src, len, sum); | |
99 | } | |
100 | EXPORT_SYMBOL(csum_and_copy_to_user); |