checksum.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /*
  2. * Copyright 2010 Tilera Corporation. All Rights Reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation, version 2.
  7. *
  8. * This program is distributed in the hope that it will be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  11. * NON INFRINGEMENT. See the GNU General Public License for
  12. * more details.
  13. * Support code for the main lib/checksum.c.
  14. */
  15. #include <net/checksum.h>
  16. #include <linux/module.h>
  17. static inline unsigned int longto16(unsigned long x)
  18. {
  19. unsigned long ret;
  20. #ifdef __tilegx__
  21. ret = __insn_v2sadu(x, 0);
  22. ret = __insn_v2sadu(ret, 0);
  23. #else
  24. ret = __insn_sadh_u(x, 0);
  25. ret = __insn_sadh_u(ret, 0);
  26. #endif
  27. return ret;
  28. }
  29. __wsum do_csum(const unsigned char *buff, int len)
  30. {
  31. int odd, count;
  32. unsigned long result = 0;
  33. if (len <= 0)
  34. goto out;
  35. odd = 1 & (unsigned long) buff;
  36. if (odd) {
  37. result = (*buff << 8);
  38. len--;
  39. buff++;
  40. }
  41. count = len >> 1; /* nr of 16-bit words.. */
  42. if (count) {
  43. if (2 & (unsigned long) buff) {
  44. result += *(const unsigned short *)buff;
  45. count--;
  46. len -= 2;
  47. buff += 2;
  48. }
  49. count >>= 1; /* nr of 32-bit words.. */
  50. if (count) {
  51. #ifdef __tilegx__
  52. if (4 & (unsigned long) buff) {
  53. unsigned int w = *(const unsigned int *)buff;
  54. result = __insn_v2sadau(result, w, 0);
  55. count--;
  56. len -= 4;
  57. buff += 4;
  58. }
  59. count >>= 1; /* nr of 64-bit words.. */
  60. #endif
  61. /*
  62. * This algorithm could wrap around for very
  63. * large buffers, but those should be impossible.
  64. */
  65. BUG_ON(count >= 65530);
  66. while (count) {
  67. unsigned long w = *(const unsigned long *)buff;
  68. count--;
  69. buff += sizeof(w);
  70. #ifdef __tilegx__
  71. result = __insn_v2sadau(result, w, 0);
  72. #else
  73. result = __insn_sadah_u(result, w, 0);
  74. #endif
  75. }
  76. #ifdef __tilegx__
  77. if (len & 4) {
  78. unsigned int w = *(const unsigned int *)buff;
  79. result = __insn_v2sadau(result, w, 0);
  80. buff += 4;
  81. }
  82. #endif
  83. }
  84. if (len & 2) {
  85. result += *(const unsigned short *) buff;
  86. buff += 2;
  87. }
  88. }
  89. if (len & 1)
  90. result += *buff;
  91. result = longto16(result);
  92. if (odd)
  93. result = swab16(result);
  94. out:
  95. return result;
  96. }