xref: /linux/arch/loongarch/include/asm/checksum.h (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
169e3a6aaSBibo Mao /* SPDX-License-Identifier: GPL-2.0-only */
269e3a6aaSBibo Mao /*
369e3a6aaSBibo Mao  * Copyright (C) 2016 ARM Ltd.
469e3a6aaSBibo Mao  * Copyright (C) 2023 Loongson Technology Corporation Limited
569e3a6aaSBibo Mao  */
669e3a6aaSBibo Mao #ifndef __ASM_CHECKSUM_H
769e3a6aaSBibo Mao #define __ASM_CHECKSUM_H
869e3a6aaSBibo Mao 
969e3a6aaSBibo Mao #include <linux/bitops.h>
1069e3a6aaSBibo Mao #include <linux/in6.h>
1169e3a6aaSBibo Mao 
1269e3a6aaSBibo Mao #define _HAVE_ARCH_IPV6_CSUM
1369e3a6aaSBibo Mao __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
1469e3a6aaSBibo Mao 			const struct in6_addr *daddr,
1569e3a6aaSBibo Mao 			__u32 len, __u8 proto, __wsum sum);
1669e3a6aaSBibo Mao 
1769e3a6aaSBibo Mao /*
1869e3a6aaSBibo Mao  * turns a 32-bit partial checksum (e.g. from csum_partial) into a
1969e3a6aaSBibo Mao  * 1's complement 16-bit checksum.
2069e3a6aaSBibo Mao  */
csum_fold(__wsum sum)2169e3a6aaSBibo Mao static inline __sum16 csum_fold(__wsum sum)
2269e3a6aaSBibo Mao {
2369e3a6aaSBibo Mao 	u32 tmp = (__force u32)sum;
2469e3a6aaSBibo Mao 
2569e3a6aaSBibo Mao 	/*
2669e3a6aaSBibo Mao 	 * swap the two 16-bit halves of sum
2769e3a6aaSBibo Mao 	 * if there is a carry from adding the two 16-bit halves,
2869e3a6aaSBibo Mao 	 * it will carry from the lower half into the upper half,
2969e3a6aaSBibo Mao 	 * giving us the correct sum in the upper half.
3069e3a6aaSBibo Mao 	 */
3169e3a6aaSBibo Mao 	return (__force __sum16)(~(tmp + rol32(tmp, 16)) >> 16);
3269e3a6aaSBibo Mao }
3369e3a6aaSBibo Mao #define csum_fold csum_fold
3469e3a6aaSBibo Mao 
3569e3a6aaSBibo Mao /*
3669e3a6aaSBibo Mao  * This is a version of ip_compute_csum() optimized for IP headers,
3769e3a6aaSBibo Mao  * which always checksum on 4 octet boundaries.  ihl is the number
3869e3a6aaSBibo Mao  * of 32-bit words and is always >= 5.
3969e3a6aaSBibo Mao  */
ip_fast_csum(const void * iph,unsigned int ihl)4069e3a6aaSBibo Mao static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
4169e3a6aaSBibo Mao {
4269e3a6aaSBibo Mao 	u64 sum;
4369e3a6aaSBibo Mao 	__uint128_t tmp;
4469e3a6aaSBibo Mao 	int n = ihl; /* we want it signed */
4569e3a6aaSBibo Mao 
4669e3a6aaSBibo Mao 	tmp = *(const __uint128_t *)iph;
4769e3a6aaSBibo Mao 	iph += 16;
4869e3a6aaSBibo Mao 	n -= 4;
4969e3a6aaSBibo Mao 	tmp += ((tmp >> 64) | (tmp << 64));
5069e3a6aaSBibo Mao 	sum = tmp >> 64;
5169e3a6aaSBibo Mao 	do {
5269e3a6aaSBibo Mao 		sum += *(const u32 *)iph;
5369e3a6aaSBibo Mao 		iph += 4;
5469e3a6aaSBibo Mao 	} while (--n > 0);
5569e3a6aaSBibo Mao 
5669e3a6aaSBibo Mao 	sum += ror64(sum, 32);
5769e3a6aaSBibo Mao 	return csum_fold((__force __wsum)(sum >> 32));
5869e3a6aaSBibo Mao }
5969e3a6aaSBibo Mao #define ip_fast_csum ip_fast_csum
6069e3a6aaSBibo Mao 
6169e3a6aaSBibo Mao extern unsigned int do_csum(const unsigned char *buff, int len);
6269e3a6aaSBibo Mao #define do_csum do_csum
6369e3a6aaSBibo Mao 
6469e3a6aaSBibo Mao #include <asm-generic/checksum.h>
6569e3a6aaSBibo Mao 
6669e3a6aaSBibo Mao #endif	/* __ASM_CHECKSUM_H */
67