Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / tile / lib / checksum.c
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);
87 out:
88         return result;
89 }