checksum.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 1995, 96, 97, 98, 99, 2001 by Ralf Baechle
  7. * Copyright (C) 1999 Silicon Graphics, Inc.
  8. * Copyright (C) 2001 Thiemo Seufer.
  9. * Copyright (C) 2002 Maciej W. Rozycki
  10. * Copyright (C) 2014 Imagination Technologies Ltd.
  11. */
  12. #ifndef _ASM_CHECKSUM_H
  13. #define _ASM_CHECKSUM_H
  14. #ifdef CONFIG_GENERIC_CSUM
  15. #include <asm-generic/checksum.h>
  16. #else
  17. #include <linux/in6.h>
  18. #include <asm/uaccess.h>
  19. /*
  20. * computes the checksum of a memory block at buff, length len,
  21. * and adds in "sum" (32-bit)
  22. *
  23. * returns a 32-bit number suitable for feeding into itself
  24. * or csum_tcpudp_magic
  25. *
  26. * this function must be called with even lengths, except
  27. * for the last fragment, which may be odd
  28. *
  29. * it's best to have buff aligned on a 32-bit boundary
  30. */
  31. __wsum csum_partial(const void *buff, int len, __wsum sum);
  32. __wsum __csum_partial_copy_kernel(const void *src, void *dst,
  33. int len, __wsum sum, int *err_ptr);
  34. __wsum __csum_partial_copy_from_user(const void *src, void *dst,
  35. int len, __wsum sum, int *err_ptr);
  36. __wsum __csum_partial_copy_to_user(const void *src, void *dst,
  37. int len, __wsum sum, int *err_ptr);
  38. /*
  39. * this is a new version of the above that records errors it finds in *errp,
  40. * but continues and zeros the rest of the buffer.
  41. */
  42. static inline
  43. __wsum csum_partial_copy_from_user(const void __user *src, void *dst, int len,
  44. __wsum sum, int *err_ptr)
  45. {
  46. might_fault();
  47. if (segment_eq(get_fs(), get_ds()))
  48. return __csum_partial_copy_kernel((__force void *)src, dst,
  49. len, sum, err_ptr);
  50. else
  51. return __csum_partial_copy_from_user((__force void *)src, dst,
  52. len, sum, err_ptr);
  53. }
  54. #define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
  55. static inline
  56. __wsum csum_and_copy_from_user(const void __user *src, void *dst,
  57. int len, __wsum sum, int *err_ptr)
  58. {
  59. if (access_ok(VERIFY_READ, src, len))
  60. return csum_partial_copy_from_user(src, dst, len, sum,
  61. err_ptr);
  62. if (len)
  63. *err_ptr = -EFAULT;
  64. return sum;
  65. }
  66. /*
  67. * Copy and checksum to user
  68. */
  69. #define HAVE_CSUM_COPY_USER
  70. static inline
  71. __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
  72. __wsum sum, int *err_ptr)
  73. {
  74. might_fault();
  75. if (access_ok(VERIFY_WRITE, dst, len)) {
  76. if (segment_eq(get_fs(), get_ds()))
  77. return __csum_partial_copy_kernel(src,
  78. (__force void *)dst,
  79. len, sum, err_ptr);
  80. else
  81. return __csum_partial_copy_to_user(src,
  82. (__force void *)dst,
  83. len, sum, err_ptr);
  84. }
  85. if (len)
  86. *err_ptr = -EFAULT;
  87. return (__force __wsum)-1; /* invalid checksum */
  88. }
  89. /*
  90. * the same as csum_partial, but copies from user space (but on MIPS
  91. * we have just one address space, so this is identical to the above)
  92. */
  93. __wsum csum_partial_copy_nocheck(const void *src, void *dst,
  94. int len, __wsum sum);
  95. #define csum_partial_copy_nocheck csum_partial_copy_nocheck
  96. /*
  97. * Fold a partial checksum without adding pseudo headers
  98. */
  99. static inline __sum16 csum_fold(__wsum csum)
  100. {
  101. u32 sum = (__force u32)csum;;
  102. sum += (sum << 16);
  103. csum = (sum < csum);
  104. sum >>= 16;
  105. sum += csum;
  106. return (__force __sum16)~sum;
  107. }
  108. #define csum_fold csum_fold
  109. /*
  110. * This is a version of ip_compute_csum() optimized for IP headers,
  111. * which always checksum on 4 octet boundaries.
  112. *
  113. * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
  114. * Arnt Gulbrandsen.
  115. */
  116. static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
  117. {
  118. const unsigned int *word = iph;
  119. const unsigned int *stop = word + ihl;
  120. unsigned int csum;
  121. int carry;
  122. csum = word[0];
  123. csum += word[1];
  124. carry = (csum < word[1]);
  125. csum += carry;
  126. csum += word[2];
  127. carry = (csum < word[2]);
  128. csum += carry;
  129. csum += word[3];
  130. carry = (csum < word[3]);
  131. csum += carry;
  132. word += 4;
  133. do {
  134. csum += *word;
  135. carry = (csum < *word);
  136. csum += carry;
  137. word++;
  138. } while (word != stop);
  139. return csum_fold(csum);
  140. }
  141. #define ip_fast_csum ip_fast_csum
  142. static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
  143. __u32 len, __u8 proto,
  144. __wsum sum)
  145. {
  146. __asm__(
  147. " .set push # csum_tcpudp_nofold\n"
  148. " .set noat \n"
  149. #ifdef CONFIG_32BIT
  150. " addu %0, %2 \n"
  151. " sltu $1, %0, %2 \n"
  152. " addu %0, $1 \n"
  153. " addu %0, %3 \n"
  154. " sltu $1, %0, %3 \n"
  155. " addu %0, $1 \n"
  156. " addu %0, %4 \n"
  157. " sltu $1, %0, %4 \n"
  158. " addu %0, $1 \n"
  159. #endif
  160. #ifdef CONFIG_64BIT
  161. " daddu %0, %2 \n"
  162. " daddu %0, %3 \n"
  163. " daddu %0, %4 \n"
  164. " dsll32 $1, %0, 0 \n"
  165. " daddu %0, $1 \n"
  166. " sltu $1, %0, $1 \n"
  167. " dsra32 %0, %0, 0 \n"
  168. " addu %0, $1 \n"
  169. #endif
  170. " .set pop"
  171. : "=r" (sum)
  172. : "0" ((__force unsigned long)daddr),
  173. "r" ((__force unsigned long)saddr),
  174. #ifdef __MIPSEL__
  175. "r" ((proto + len) << 8),
  176. #else
  177. "r" (proto + len),
  178. #endif
  179. "r" ((__force unsigned long)sum));
  180. return sum;
  181. }
  182. #define csum_tcpudp_nofold csum_tcpudp_nofold
  183. /*
  184. * this routine is used for miscellaneous IP-like checksums, mainly
  185. * in icmp.c
  186. */
  187. static inline __sum16 ip_compute_csum(const void *buff, int len)
  188. {
  189. return csum_fold(csum_partial(buff, len, 0));
  190. }
  191. #define _HAVE_ARCH_IPV6_CSUM
  192. static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
  193. const struct in6_addr *daddr,
  194. __u32 len, __u8 proto,
  195. __wsum sum)
  196. {
  197. __wsum tmp;
  198. __asm__(
  199. " .set push # csum_ipv6_magic\n"
  200. " .set noreorder \n"
  201. " .set noat \n"
  202. " addu %0, %5 # proto (long in network byte order)\n"
  203. " sltu $1, %0, %5 \n"
  204. " addu %0, $1 \n"
  205. " addu %0, %6 # csum\n"
  206. " sltu $1, %0, %6 \n"
  207. " lw %1, 0(%2) # four words source address\n"
  208. " addu %0, $1 \n"
  209. " addu %0, %1 \n"
  210. " sltu $1, %0, %1 \n"
  211. " lw %1, 4(%2) \n"
  212. " addu %0, $1 \n"
  213. " addu %0, %1 \n"
  214. " sltu $1, %0, %1 \n"
  215. " lw %1, 8(%2) \n"
  216. " addu %0, $1 \n"
  217. " addu %0, %1 \n"
  218. " sltu $1, %0, %1 \n"
  219. " lw %1, 12(%2) \n"
  220. " addu %0, $1 \n"
  221. " addu %0, %1 \n"
  222. " sltu $1, %0, %1 \n"
  223. " lw %1, 0(%3) \n"
  224. " addu %0, $1 \n"
  225. " addu %0, %1 \n"
  226. " sltu $1, %0, %1 \n"
  227. " lw %1, 4(%3) \n"
  228. " addu %0, $1 \n"
  229. " addu %0, %1 \n"
  230. " sltu $1, %0, %1 \n"
  231. " lw %1, 8(%3) \n"
  232. " addu %0, $1 \n"
  233. " addu %0, %1 \n"
  234. " sltu $1, %0, %1 \n"
  235. " lw %1, 12(%3) \n"
  236. " addu %0, $1 \n"
  237. " addu %0, %1 \n"
  238. " sltu $1, %0, %1 \n"
  239. " addu %0, $1 # Add final carry\n"
  240. " .set pop"
  241. : "=&r" (sum), "=&r" (tmp)
  242. : "r" (saddr), "r" (daddr),
  243. "0" (htonl(len)), "r" (htonl(proto)), "r" (sum));
  244. return csum_fold(sum);
  245. }
  246. #include <asm-generic/checksum.h>
  247. #endif /* CONFIG_GENERIC_CSUM */
  248. #endif /* _ASM_CHECKSUM_H */