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