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