Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * arch/x86_64/lib/csum-partial.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * This file contains network checksum routines that are better done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * in an architecture-specific manner due to speed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <asm/checksum.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) static inline unsigned short from32to16(unsigned a) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 	unsigned short b = a >> 16; 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 	asm("addw %w2,%w0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 	    "adcw $0,%w0\n" 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 	    : "=r" (b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 	    : "0" (b), "r" (a));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	return b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * Do a 64-bit checksum on an arbitrary memory area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * Returns a 32bit checksum.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * This isn't as time critical as it used to be because many NICs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  * do hardware checksumming these days.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  * 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  * Things tried and found to not make it faster:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * Manual Prefetching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  * Unrolling to an 128 bytes inner loop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  * Using interleaving with more registers to break the carry chains.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) static unsigned do_csum(const unsigned char *buff, unsigned len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	unsigned odd, count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	unsigned long result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	if (unlikely(len == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		return result; 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	odd = 1 & (unsigned long) buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	if (unlikely(odd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		result = *buff << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		len--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		buff++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	count = len >> 1;		/* nr of 16-bit words.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	if (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		if (2 & (unsigned long) buff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 			result += *(unsigned short *)buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 			count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 			len -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 			buff += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		count >>= 1;		/* nr of 32-bit words.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		if (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 			unsigned long zero;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 			unsigned count64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 			if (4 & (unsigned long) buff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 				result += *(unsigned int *) buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 				count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 				len -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 				buff += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 			count >>= 1;	/* nr of 64-bit words.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 			/* main loop using 64byte blocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 			zero = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 			count64 = count >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 			while (count64) { 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 				asm("addq 0*8(%[src]),%[res]\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 				    "adcq 1*8(%[src]),%[res]\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 				    "adcq 2*8(%[src]),%[res]\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 				    "adcq 3*8(%[src]),%[res]\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 				    "adcq 4*8(%[src]),%[res]\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 				    "adcq 5*8(%[src]),%[res]\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 				    "adcq 6*8(%[src]),%[res]\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 				    "adcq 7*8(%[src]),%[res]\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 				    "adcq %[zero],%[res]"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 				    : [res] "=r" (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 				    : [src] "r" (buff), [zero] "r" (zero),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 				    "[res]" (result));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 				buff += 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 				count64--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 			/* last up to 7 8byte blocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 			count %= 8; 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 			while (count) { 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 				asm("addq %1,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 				    "adcq %2,%0\n" 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 					    : "=r" (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 				    : "m" (*(unsigned long *)buff), 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 				    "r" (zero),  "0" (result));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 				--count; 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 				buff += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 			result = add32_with_carry(result>>32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 						  result&0xffffffff); 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 			if (len & 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 				result += *(unsigned int *) buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 				buff += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		if (len & 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 			result += *(unsigned short *) buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 			buff += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	if (len & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		result += *buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	result = add32_with_carry(result>>32, result & 0xffffffff); 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	if (unlikely(odd)) { 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		result = from32to16(result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)  * computes the checksum of a memory block at buff, length len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)  * and adds in "sum" (32-bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)  * returns a 32-bit number suitable for feeding into itself
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)  * or csum_tcpudp_magic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)  * this function must be called with even lengths, except
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)  * for the last fragment, which may be odd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)  * it's best to have buff aligned on a 64-bit boundary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) __wsum csum_partial(const void *buff, int len, __wsum sum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	return (__force __wsum)add32_with_carry(do_csum(buff, len),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 						(__force u32)sum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) EXPORT_SYMBOL(csum_partial);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)  * this routine is used for miscellaneous IP-like checksums, mainly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)  * in icmp.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) __sum16 ip_compute_csum(const void *buff, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	return csum_fold(csum_partial(buff,len,0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) EXPORT_SYMBOL(ip_compute_csum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)