diff options
Diffstat (limited to 'arch/arm64/lib/csum.c')
| -rw-r--r-- | arch/arm64/lib/csum.c | 27 | 
1 files changed, 27 insertions, 0 deletions
diff --git a/arch/arm64/lib/csum.c b/arch/arm64/lib/csum.c index 1f82c66b32ea..60eccae2abad 100644 --- a/arch/arm64/lib/csum.c +++ b/arch/arm64/lib/csum.c @@ -124,3 +124,30 @@ unsigned int do_csum(const unsigned char *buff, int len)  	return sum >> 16;  } + +__sum16 csum_ipv6_magic(const struct in6_addr *saddr, +			const struct in6_addr *daddr, +			__u32 len, __u8 proto, __wsum csum) +{ +	__uint128_t src, dst; +	u64 sum = (__force u64)csum; + +	src = *(const __uint128_t *)saddr->s6_addr; +	dst = *(const __uint128_t *)daddr->s6_addr; + +	sum += (__force u32)htonl(len); +#ifdef __LITTLE_ENDIAN +	sum += (u32)proto << 24; +#else +	sum += proto; +#endif +	src += (src >> 64) | (src << 64); +	dst += (dst >> 64) | (dst << 64); + +	sum = accumulate(sum, src >> 64); +	sum = accumulate(sum, dst >> 64); + +	sum += ((sum >> 32) | (sum << 32)); +	return csum_fold((__force __wsum)(sum >> 32)); +} +EXPORT_SYMBOL(csum_ipv6_magic);  |