/* SPDX-License-Identifier: GPL-2.0 */1#ifndef __UM_CHECKSUM_H2#define __UM_CHECKSUM_H34#include <linux/string.h>5#include <linux/in6.h>6#include <linux/uaccess.h>78/*9* computes the checksum of a memory block at buff, length len,10* and adds in "sum" (32-bit)11*12* returns a 32-bit number suitable for feeding into itself13* or csum_tcpudp_magic14*15* this function must be called with even lengths, except16* for the last fragment, which may be odd17*18* it's best to have buff aligned on a 32-bit boundary19*/20extern __wsum csum_partial(const void *buff, int len, __wsum sum);2122/* Do not call this directly. Declared for export type visibility. */23extern __visible __wsum csum_partial_copy_generic(const void *src, void *dst, int len);2425/**26* csum_fold - Fold and invert a 32bit checksum.27* sum: 32bit unfolded sum28*29* Fold a 32bit running checksum to 16bit and invert it. This is usually30* the last step before putting a checksum into a packet.31* Make sure not to mix with 64bit checksums.32*/33static inline __sum16 csum_fold(__wsum sum)34{35__asm__(36" addl %1,%0\n"37" adcl $0xffff,%0"38: "=r" (sum)39: "r" ((__force u32)sum << 16),40"0" ((__force u32)sum & 0xffff0000)41);42return (__force __sum16)(~(__force u32)sum >> 16);43}4445/**46* csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.47* @saddr: source address48* @daddr: destination address49* @len: length of packet50* @proto: ip protocol of packet51* @sum: initial sum to be added in (32bit unfolded)52*53* Returns the pseudo header checksum the input data. Result is54* 32bit unfolded.55*/56static inline __wsum57csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len,58__u8 proto, __wsum sum)59{60asm(" addl %1, %0\n"61" adcl %2, %0\n"62" adcl %3, %0\n"63" adcl $0, %0\n"64: "=r" (sum)65: "g" (daddr), "g" (saddr), "g" ((len + proto) << 8), "0" (sum));66return sum;67}6869/*70* computes the checksum of the TCP/UDP pseudo-header71* returns a 16-bit checksum, already complemented72*/73static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,74__u32 len, __u8 proto,75__wsum sum)76{77return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));78}7980/**81* ip_fast_csum - Compute the IPv4 header checksum efficiently.82* iph: ipv4 header83* ihl: length of header / 484*/85static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)86{87unsigned int sum;8889asm( " movl (%1), %0\n"90" subl $4, %2\n"91" jbe 2f\n"92" addl 4(%1), %0\n"93" adcl 8(%1), %0\n"94" adcl 12(%1), %0\n"95"1: adcl 16(%1), %0\n"96" lea 4(%1), %1\n"97" decl %2\n"98" jne 1b\n"99" adcl $0, %0\n"100" movl %0, %2\n"101" shrl $16, %0\n"102" addw %w2, %w0\n"103" adcl $0, %0\n"104" notl %0\n"105"2:"106/* Since the input registers which are loaded with iph and ipl107are modified, we must also specify them as outputs, or gcc108will assume they contain their original values. */109: "=r" (sum), "=r" (iph), "=r" (ihl)110: "1" (iph), "2" (ihl)111: "memory");112return (__force __sum16)sum;113}114115#ifdef CONFIG_X86_32116# include "checksum_32.h"117#else118# include "checksum_64.h"119#endif120121#endif122123124