VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
2874c5fd28426 (Thomas Gleixner 2019-05-27 08:55:01 +0200   1) // SPDX-License-Identifier: GPL-2.0-or-later
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000   2) /*
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000   3)  *
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000   4)  * INET		An implementation of the TCP/IP protocol suite for the LINUX
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000   5)  *		operating system.  INET is implemented using the  BSD Socket
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000   6)  *		interface as the means of communication with the user level.
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000   7)  *
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000   8)  *		IP/TCP/UDP checksumming routines
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000   9)  *
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  10)  * Authors:	Jorge Cwik, <jorge@laser.satlink.net>
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  11)  *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  12)  *		Tom May, <ftom@netcom.com>
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  13)  *		Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  14)  *		Lots of code moved from tcp.c and ip.c; see those files
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  15)  *		for more names.
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  16)  *
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  17)  * 03/02/96	Jes Sorensen, Andreas Schwab, Roman Hodek:
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  18)  *		Fixed some nasty bugs, causing some horrible crashes.
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  19)  *		A: At some points, the sum (%0) was used as
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  20)  *		length-counter instead of the length counter
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  21)  *		(%1). Thanks to Roman Hodek for pointing this out.
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  22)  *		B: GCC seems to mess up if one uses too many
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  23)  *		data-registers to hold input values and one tries to
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  24)  *		specify d0 and d1 as scratch registers. Letting gcc
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  25)  *		choose these registers itself solves the problem.
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  26)  */
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  27) 
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  28) /* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  29)  kills, so most of the assembly has to go. */
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  30) 
8bc3bcc93a2b4 (Paul Gortmaker  2011-11-16 21:29:17 -0500  31) #include <linux/export.h>
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  32) #include <net/checksum.h>
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  33) 
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  34) #include <asm/byteorder.h>
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  35) 
20c1f641bb80f (Arnd Bergmann   2009-06-23 21:37:26 +0200  36) #ifndef do_csum
c44ba9f668494 (Arnd Bergmann   2009-06-23 21:22:58 +0200  37) static inline unsigned short from32to16(unsigned int x)
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  38) {
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  39) 	/* add up 16-bit and 16-bit for 16+c bit */
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  40) 	x = (x & 0xffff) + (x >> 16);
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  41) 	/* add up carry.. */
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  42) 	x = (x & 0xffff) + (x >> 16);
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  43) 	return x;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  44) }
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  45) 
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  46) static unsigned int do_csum(const unsigned char *buff, int len)
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  47) {
be0e1e788b097 (Ian Abbott      2011-07-07 01:18:49 +0000  48) 	int odd;
c44ba9f668494 (Arnd Bergmann   2009-06-23 21:22:58 +0200  49) 	unsigned int result = 0;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  50) 
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  51) 	if (len <= 0)
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  52) 		goto out;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  53) 	odd = 1 & (unsigned long) buff;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  54) 	if (odd) {
32a9ff9cc55b4 (Arnd Bergmann   2009-06-19 10:41:19 +0200  55) #ifdef __LITTLE_ENDIAN
32a9ff9cc55b4 (Arnd Bergmann   2009-06-19 10:41:19 +0200  56) 		result += (*buff << 8);
0a5549ed16352 (Arnd Bergmann   2009-06-23 22:52:51 +0200  57) #else
0a5549ed16352 (Arnd Bergmann   2009-06-23 22:52:51 +0200  58) 		result = *buff;
32a9ff9cc55b4 (Arnd Bergmann   2009-06-19 10:41:19 +0200  59) #endif
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  60) 		len--;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  61) 		buff++;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  62) 	}
be0e1e788b097 (Ian Abbott      2011-07-07 01:18:49 +0000  63) 	if (len >= 2) {
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  64) 		if (2 & (unsigned long) buff) {
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  65) 			result += *(unsigned short *) buff;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  66) 			len -= 2;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  67) 			buff += 2;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  68) 		}
be0e1e788b097 (Ian Abbott      2011-07-07 01:18:49 +0000  69) 		if (len >= 4) {
be0e1e788b097 (Ian Abbott      2011-07-07 01:18:49 +0000  70) 			const unsigned char *end = buff + ((unsigned)len & ~3);
c44ba9f668494 (Arnd Bergmann   2009-06-23 21:22:58 +0200  71) 			unsigned int carry = 0;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  72) 			do {
c44ba9f668494 (Arnd Bergmann   2009-06-23 21:22:58 +0200  73) 				unsigned int w = *(unsigned int *) buff;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  74) 				buff += 4;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  75) 				result += carry;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  76) 				result += w;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  77) 				carry = (w > result);
be0e1e788b097 (Ian Abbott      2011-07-07 01:18:49 +0000  78) 			} while (buff < end);
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  79) 			result += carry;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  80) 			result = (result & 0xffff) + (result >> 16);
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  81) 		}
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  82) 		if (len & 2) {
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  83) 			result += *(unsigned short *) buff;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  84) 			buff += 2;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  85) 		}
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  86) 	}
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  87) 	if (len & 1)
32a9ff9cc55b4 (Arnd Bergmann   2009-06-19 10:41:19 +0200  88) #ifdef __LITTLE_ENDIAN
32a9ff9cc55b4 (Arnd Bergmann   2009-06-19 10:41:19 +0200  89) 		result += *buff;
32a9ff9cc55b4 (Arnd Bergmann   2009-06-19 10:41:19 +0200  90) #else
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  91) 		result += (*buff << 8);
32a9ff9cc55b4 (Arnd Bergmann   2009-06-19 10:41:19 +0200  92) #endif
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  93) 	result = from32to16(result);
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  94) 	if (odd)
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  95) 		result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  96) out:
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  97) 	return result;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000  98) }
20c1f641bb80f (Arnd Bergmann   2009-06-23 21:37:26 +0200  99) #endif
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 100) 
64e69073c3543 (Vineet Gupta    2013-01-18 15:12:16 +0530 101) #ifndef ip_fast_csum
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 102) /*
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 103)  *	This is a version of ip_compute_csum() optimized for IP headers,
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 104)  *	which always checksum on 4 octet boundaries.
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 105)  */
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 106) __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 107) {
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 108) 	return (__force __sum16)~do_csum(iph, ihl*4);
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 109) }
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 110) EXPORT_SYMBOL(ip_fast_csum);
64e69073c3543 (Vineet Gupta    2013-01-18 15:12:16 +0530 111) #endif
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 112) 
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 113) /*
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 114)  * computes the checksum of a memory block at buff, length len,
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 115)  * and adds in "sum" (32-bit)
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 116)  *
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 117)  * returns a 32-bit number suitable for feeding into itself
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 118)  * or csum_tcpudp_magic
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 119)  *
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 120)  * this function must be called with even lengths, except
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 121)  * for the last fragment, which may be odd
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 122)  *
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 123)  * it's best to have buff aligned on a 32-bit boundary
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 124)  */
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 125) __wsum csum_partial(const void *buff, int len, __wsum wsum)
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 126) {
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 127) 	unsigned int sum = (__force unsigned int)wsum;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 128) 	unsigned int result = do_csum(buff, len);
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 129) 
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 130) 	/* add in old sum, and carry.. */
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 131) 	result += sum;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 132) 	if (sum > result)
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 133) 		result += 1;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 134) 	return (__force __wsum)result;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 135) }
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 136) EXPORT_SYMBOL(csum_partial);
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 137) 
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 138) /*
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 139)  * this routine is used for miscellaneous IP-like checksums, mainly
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 140)  * in icmp.c
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 141)  */
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 142) __sum16 ip_compute_csum(const void *buff, int len)
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 143) {
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 144) 	return (__force __sum16)~do_csum(buff, len);
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 145) }
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 146) EXPORT_SYMBOL(ip_compute_csum);
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 147) 
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 148) #ifndef csum_tcpudp_nofold
9ce357795ef20 (karl beldan     2015-01-29 11:10:22 +0100 149) static inline u32 from64to32(u64 x)
9ce357795ef20 (karl beldan     2015-01-29 11:10:22 +0100 150) {
9ce357795ef20 (karl beldan     2015-01-29 11:10:22 +0100 151) 	/* add up 32-bit and 32-bit for 32+c bit */
9ce357795ef20 (karl beldan     2015-01-29 11:10:22 +0100 152) 	x = (x & 0xffffffff) + (x >> 32);
9ce357795ef20 (karl beldan     2015-01-29 11:10:22 +0100 153) 	/* add up carry.. */
9ce357795ef20 (karl beldan     2015-01-29 11:10:22 +0100 154) 	x = (x & 0xffffffff) + (x >> 32);
9ce357795ef20 (karl beldan     2015-01-29 11:10:22 +0100 155) 	return (u32)x;
9ce357795ef20 (karl beldan     2015-01-29 11:10:22 +0100 156) }
9ce357795ef20 (karl beldan     2015-01-29 11:10:22 +0100 157) 
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 158) __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
01cfbad79a5e2 (Alexander Duyck 2016-03-11 14:05:34 -0800 159) 			  __u32 len, __u8 proto, __wsum sum)
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 160) {
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 161) 	unsigned long long s = (__force u32)sum;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 162) 
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 163) 	s += (__force u32)saddr;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 164) 	s += (__force u32)daddr;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 165) #ifdef __BIG_ENDIAN
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 166) 	s += proto + len;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 167) #else
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 168) 	s += (proto + len) << 8;
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 169) #endif
150ae0e946347 (karl beldan     2015-01-28 10:58:11 +0100 170) 	return (__force __wsum)from64to32(s);
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 171) }
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 172) EXPORT_SYMBOL(csum_tcpudp_nofold);
26a28fa4fea5b (Arnd Bergmann   2009-05-13 22:56:38 +0000 173) #endif