checksum.h 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
  4. *
  5. * Joern Rennecke <[email protected]>: Jan 2012
  6. * -Insn Scheduling improvements to csum core routines.
  7. * = csum_fold( ) largely derived from ARM version.
  8. * = ip_fast_cum( ) to have module scheduling
  9. * -gcc 4.4.x broke networking. Alias analysis needed to be primed.
  10. * worked around by adding memory clobber to ip_fast_csum( )
  11. *
  12. * vineetg: May 2010
  13. * -Rewrote ip_fast_cscum( ) and csum_fold( ) with fast inline asm
  14. */
  15. #ifndef _ASM_ARC_CHECKSUM_H
  16. #define _ASM_ARC_CHECKSUM_H
  17. /*
  18. * Fold a partial checksum
  19. *
  20. * The 2 swords comprising the 32bit sum are added, any carry to 16th bit
  21. * added back and final sword result inverted.
  22. */
  23. static inline __sum16 csum_fold(__wsum s)
  24. {
  25. unsigned int r = s << 16 | s >> 16; /* ror */
  26. s = ~s;
  27. s -= r;
  28. return s >> 16;
  29. }
  30. /*
  31. * This is a version of ip_compute_csum() optimized for IP headers,
  32. * which always checksum on 4 octet boundaries.
  33. */
  34. static inline __sum16
  35. ip_fast_csum(const void *iph, unsigned int ihl)
  36. {
  37. const void *ptr = iph;
  38. unsigned int tmp, tmp2, sum;
  39. __asm__(
  40. " ld.ab %0, [%3, 4] \n"
  41. " ld.ab %2, [%3, 4] \n"
  42. " sub %1, %4, 2 \n"
  43. " lsr.f lp_count, %1, 1 \n"
  44. " bcc 0f \n"
  45. " add.f %0, %0, %2 \n"
  46. " ld.ab %2, [%3, 4] \n"
  47. "0: lp 1f \n"
  48. " ld.ab %1, [%3, 4] \n"
  49. " adc.f %0, %0, %2 \n"
  50. " ld.ab %2, [%3, 4] \n"
  51. " adc.f %0, %0, %1 \n"
  52. "1: adc.f %0, %0, %2 \n"
  53. " add.cs %0,%0,1 \n"
  54. : "=&r"(sum), "=r"(tmp), "=&r"(tmp2), "+&r" (ptr)
  55. : "r"(ihl)
  56. : "cc", "lp_count", "memory");
  57. return csum_fold(sum);
  58. }
  59. /*
  60. * TCP pseudo Header is 12 bytes:
  61. * SA [4], DA [4], zeroes [1], Proto[1], TCP Seg(hdr+data) Len [2]
  62. */
  63. static inline __wsum
  64. csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len,
  65. __u8 proto, __wsum sum)
  66. {
  67. __asm__ __volatile__(
  68. " add.f %0, %0, %1 \n"
  69. " adc.f %0, %0, %2 \n"
  70. " adc.f %0, %0, %3 \n"
  71. " adc.f %0, %0, %4 \n"
  72. " adc %0, %0, 0 \n"
  73. : "+&r"(sum)
  74. : "r"(saddr), "r"(daddr),
  75. #ifdef CONFIG_CPU_BIG_ENDIAN
  76. "r"(len),
  77. #else
  78. "r"(len << 8),
  79. #endif
  80. "r"(htons(proto))
  81. : "cc");
  82. return sum;
  83. }
  84. #define csum_fold csum_fold
  85. #define ip_fast_csum ip_fast_csum
  86. #define csum_tcpudp_nofold csum_tcpudp_nofold
  87. #include <asm-generic/checksum.h>
  88. #endif /* _ASM_ARC_CHECKSUM_H */