Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/s390/include/asm/checksum.h
26493 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
/*
3
* S390 fast network checksum routines
4
*
5
* S390 version
6
* Copyright IBM Corp. 1999
7
* Author(s): Ulrich Hild (first version)
8
* Martin Schwidefsky (heavily optimized CKSM version)
9
* D.J. Barrow (third attempt)
10
*/
11
12
#ifndef _S390_CHECKSUM_H
13
#define _S390_CHECKSUM_H
14
15
#include <linux/instrumented.h>
16
#include <linux/kmsan-checks.h>
17
#include <linux/in6.h>
18
19
static inline __wsum cksm(const void *buff, int len, __wsum sum)
20
{
21
union register_pair rp = {
22
.even = (unsigned long)buff,
23
.odd = (unsigned long)len,
24
};
25
26
instrument_read(buff, len);
27
kmsan_check_memory(buff, len);
28
asm volatile(
29
"0: cksm %[sum],%[rp]\n"
30
" jo 0b\n"
31
: [sum] "+&d" (sum), [rp] "+&d" (rp.pair) : : "cc", "memory");
32
return sum;
33
}
34
35
__wsum csum_partial(const void *buff, int len, __wsum sum);
36
37
#define _HAVE_ARCH_CSUM_AND_COPY
38
__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len);
39
40
/*
41
* Fold a partial checksum without adding pseudo headers.
42
*/
43
static inline __sum16 csum_fold(__wsum sum)
44
{
45
u32 csum = (__force u32) sum;
46
47
csum += (csum >> 16) | (csum << 16);
48
csum >>= 16;
49
return (__force __sum16) ~csum;
50
}
51
52
/*
53
* This is a version of ip_compute_csum() optimized for IP headers,
54
* which always checksums on 4 octet boundaries.
55
*/
56
static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
57
{
58
__u64 csum = 0;
59
__u32 *ptr = (u32 *)iph;
60
61
csum += *ptr++;
62
csum += *ptr++;
63
csum += *ptr++;
64
csum += *ptr++;
65
ihl -= 4;
66
while (ihl--)
67
csum += *ptr++;
68
csum += (csum >> 32) | (csum << 32);
69
return csum_fold((__force __wsum)(csum >> 32));
70
}
71
72
/*
73
* Computes the checksum of the TCP/UDP pseudo-header.
74
* Returns a 32-bit checksum.
75
*/
76
static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len,
77
__u8 proto, __wsum sum)
78
{
79
__u64 csum = (__force __u64)sum;
80
81
csum += (__force __u32)saddr;
82
csum += (__force __u32)daddr;
83
csum += len;
84
csum += proto;
85
csum += (csum >> 32) | (csum << 32);
86
return (__force __wsum)(csum >> 32);
87
}
88
89
/*
90
* Computes the checksum of the TCP/UDP pseudo-header.
91
* Returns a 16-bit checksum, already complemented.
92
*/
93
static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, __u32 len,
94
__u8 proto, __wsum sum)
95
{
96
return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
97
}
98
99
/*
100
* Used for miscellaneous IP-like checksums, mainly icmp.
101
*/
102
static inline __sum16 ip_compute_csum(const void *buff, int len)
103
{
104
return csum_fold(csum_partial(buff, len, 0));
105
}
106
107
#define _HAVE_ARCH_IPV6_CSUM
108
static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
109
const struct in6_addr *daddr,
110
__u32 len, __u8 proto, __wsum csum)
111
{
112
__u64 sum = (__force __u64)csum;
113
114
sum += (__force __u32)saddr->s6_addr32[0];
115
sum += (__force __u32)saddr->s6_addr32[1];
116
sum += (__force __u32)saddr->s6_addr32[2];
117
sum += (__force __u32)saddr->s6_addr32[3];
118
sum += (__force __u32)daddr->s6_addr32[0];
119
sum += (__force __u32)daddr->s6_addr32[1];
120
sum += (__force __u32)daddr->s6_addr32[2];
121
sum += (__force __u32)daddr->s6_addr32[3];
122
sum += len;
123
sum += proto;
124
sum += (sum >> 32) | (sum << 32);
125
return csum_fold((__force __wsum)(sum >> 32));
126
}
127
128
#endif /* _S390_CHECKSUM_H */
129
130