checksum.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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. __wsum do_csum(const unsigned char *buff, int len)
  18. {
  19. int odd, count;
  20. unsigned long result = 0;
  21. if (len <= 0)
  22. goto out;
  23. odd = 1 & (unsigned long) buff;
  24. if (odd) {
  25. result = (*buff << 8);
  26. len--;
  27. buff++;
  28. }
  29. count = len >> 1; /* nr of 16-bit words.. */
  30. if (count) {
  31. if (2 & (unsigned long) buff) {
  32. result += *(const unsigned short *)buff;
  33. count--;
  34. len -= 2;
  35. buff += 2;
  36. }
  37. count >>= 1; /* nr of 32-bit words.. */
  38. if (count) {
  39. #ifdef __tilegx__
  40. if (4 & (unsigned long) buff) {
  41. unsigned int w = *(const unsigned int *)buff;
  42. result = __insn_v2sadau(result, w, 0);
  43. count--;
  44. len -= 4;
  45. buff += 4;
  46. }
  47. count >>= 1; /* nr of 64-bit words.. */
  48. #endif
  49. /*
  50. * This algorithm could wrap around for very
  51. * large buffers, but those should be impossible.
  52. */
  53. BUG_ON(count >= 65530);
  54. while (count) {
  55. unsigned long w = *(const unsigned long *)buff;
  56. count--;
  57. buff += sizeof(w);
  58. #ifdef __tilegx__
  59. result = __insn_v2sadau(result, w, 0);
  60. #else
  61. result = __insn_sadah_u(result, w, 0);
  62. #endif
  63. }
  64. #ifdef __tilegx__
  65. if (len & 4) {
  66. unsigned int w = *(const unsigned int *)buff;
  67. result = __insn_v2sadau(result, w, 0);
  68. buff += 4;
  69. }
  70. #endif
  71. }
  72. if (len & 2) {
  73. result += *(const unsigned short *) buff;
  74. buff += 2;
  75. }
  76. }
  77. if (len & 1)
  78. result += *buff;
  79. result = csum_long(result);
  80. if (odd)
  81. result = swab16(result);
  82. out:
  83. return result;
  84. }