1633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham/*
2633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * This file is subject to the terms and conditions of the GNU General Public
3633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * License.  See the file "COPYING" in the main directory of this archive
4633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * for more details.
5633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham *
6633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * Copyright (C) 1995, 96, 97, 98, 99, 2001 by Ralf Baechle
7633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * Copyright (C) 1999 Silicon Graphics, Inc.
8633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * Copyright (C) 2001 Thiemo Seufer.
9633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * Copyright (C) 2002 Maciej W. Rozycki
10633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham */
11633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham#ifndef _ASM_CHECKSUM_H
12633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham#define _ASM_CHECKSUM_H
13633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
14633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham#include <linux/in6.h>
15633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
16633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham#include <asm/uaccess.h>
17633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
18633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham/*
19633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * computes the checksum of a memory block at buff, length len,
20633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * and adds in "sum" (32-bit)
21633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham *
22633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * returns a 32-bit number suitable for feeding into itself
23633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * or csum_tcpudp_magic
24633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham *
25633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * this function must be called with even lengths, except
26633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * for the last fragment, which may be odd
27633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham *
28633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * it's best to have buff aligned on a 32-bit boundary
29633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham */
30633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham__wsum csum_partial(const void *buff, int len, __wsum sum);
31633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
32633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham__wsum __csum_partial_copy_user(const void *src, void *dst,
33633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham				int len, __wsum sum, int *err_ptr);
34633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
35633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham/*
36633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * this is a new version of the above that records errors it finds in *errp,
37633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * but continues and zeros the rest of the buffer.
38633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham */
39633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandhamstatic inline
40633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham__wsum csum_partial_copy_from_user(const void __user *src, void *dst, int len,
41633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham				   __wsum sum, int *err_ptr)
42633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham{
43633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	might_sleep();
44633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	return __csum_partial_copy_user((__force void *)src, dst,
45633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham					len, sum, err_ptr);
46633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham}
47633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
48633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham/*
49633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * Copy and checksum to user
50633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham */
51633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham#define HAVE_CSUM_COPY_USER
52633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandhamstatic inline
53633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
54633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham			     __wsum sum, int *err_ptr)
55633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham{
56633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	might_sleep();
57633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	if (access_ok(VERIFY_WRITE, dst, len))
58633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham		return __csum_partial_copy_user(src, (__force void *)dst,
59633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham						len, sum, err_ptr);
60633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	if (len)
61633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham		*err_ptr = -EFAULT;
62633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
63633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	return (__force __wsum)-1; /* invalid checksum */
64633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham}
65633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
66633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham/*
67633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * the same as csum_partial, but copies from user space (but on MIPS
68633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * we have just one address space, so this is identical to the above)
69633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham */
70633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham__wsum csum_partial_copy_nocheck(const void *src, void *dst,
71633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham				       int len, __wsum sum);
72633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
73633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham/*
74633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham *	Fold a partial checksum without adding pseudo headers
75633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham */
76633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandhamstatic inline __sum16 csum_fold(__wsum sum)
77633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham{
78633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	__asm__(
79633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	.set	push		# csum_fold\n"
80633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	.set	noat		\n"
81633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	sll	$1, %0, 16	\n"
82633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, $1		\n"
83633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	sltu	$1, %0, $1	\n"
84633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	srl	%0, %0, 16	\n"
85633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, $1		\n"
86633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	xori	%0, 0xffff	\n"
87633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	.set	pop"
88633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	: "=r" (sum)
89633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	: "0" (sum));
90633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
91633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	return (__force __sum16)sum;
92633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham}
93633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
94633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham/*
95633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham *	This is a version of ip_compute_csum() optimized for IP headers,
96633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham *	which always checksum on 4 octet boundaries.
97633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham *
98633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham *	By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
99633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham *	Arnt Gulbrandsen.
100633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham */
101633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandhamstatic inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
102633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham{
103633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	const unsigned int *word = iph;
104633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	const unsigned int *stop = word + ihl;
105633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	unsigned int csum;
106633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	int carry;
107633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
108633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	csum = word[0];
109633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	csum += word[1];
110633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	carry = (csum < word[1]);
111633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	csum += carry;
112633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
113633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	csum += word[2];
114633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	carry = (csum < word[2]);
115633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	csum += carry;
116633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
117633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	csum += word[3];
118633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	carry = (csum < word[3]);
119633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	csum += carry;
120633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
121633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	word += 4;
122633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	do {
123633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham		csum += *word;
124633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham		carry = (csum < *word);
125633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham		csum += carry;
126633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham		word++;
127633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	} while (word != stop);
128633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
129633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	return csum_fold(csum);
130633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham}
131633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
132633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandhamstatic inline __wsum csum_tcpudp_nofold(__be32 saddr,
133633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	__be32 daddr, unsigned short len, unsigned short proto,
134633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	__wsum sum)
135633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham{
136633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	__asm__(
137633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	.set	push		# csum_tcpudp_nofold\n"
138633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	.set	noat		\n"
139633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham#ifdef CONFIG_32BIT
140633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, %2		\n"
141633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	sltu	$1, %0, %2	\n"
142633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, $1		\n"
143633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
144633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, %3		\n"
145633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	sltu	$1, %0, %3	\n"
146633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, $1		\n"
147633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
148633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, %4		\n"
149633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	sltu	$1, %0, %4	\n"
150633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, $1		\n"
151633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham#endif
152633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham#ifdef CONFIG_64BIT
153633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	daddu	%0, %2		\n"
154633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	daddu	%0, %3		\n"
155633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	daddu	%0, %4		\n"
156633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	dsll32	$1, %0, 0	\n"
157633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	daddu	%0, $1		\n"
158633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	dsra32	%0, %0, 0	\n"
159633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham#endif
160633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	.set	pop"
161633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	: "=r" (sum)
162633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	: "0" ((__force unsigned long)daddr),
163633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	  "r" ((__force unsigned long)saddr),
164633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham#ifdef __MIPSEL__
165633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	  "r" ((proto + len) << 8),
166633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham#else
167633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	  "r" (proto + len),
168633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham#endif
169633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	  "r" ((__force unsigned long)sum));
170633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
171633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	return sum;
172633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham}
173633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
174633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham/*
175633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * computes the checksum of the TCP/UDP pseudo-header
176633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * returns a 16-bit checksum, already complemented
177633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham */
178633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandhamstatic inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
179633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham						   unsigned short len,
180633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham						   unsigned short proto,
181633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham						   __wsum sum)
182633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham{
183633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
184633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham}
185633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
186633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham/*
187633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * this routine is used for miscellaneous IP-like checksums, mainly
188633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham * in icmp.c
189633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham */
190633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandhamstatic inline __sum16 ip_compute_csum(const void *buff, int len)
191633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham{
192633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	return csum_fold(csum_partial(buff, len, 0));
193633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham}
194633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
195633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham#define _HAVE_ARCH_IPV6_CSUM
196633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandhamstatic __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
197633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham				          const struct in6_addr *daddr,
198633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham					  __u32 len, unsigned short proto,
199633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham					  __wsum sum)
200633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham{
201633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	__asm__(
202633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	.set	push		# csum_ipv6_magic\n"
203633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	.set	noreorder	\n"
204633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	.set	noat		\n"
205633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, %5		# proto (long in network byte order)\n"
206633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	sltu	$1, %0, %5	\n"
207633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, $1		\n"
208633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
209633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, %6		# csum\n"
210633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	sltu	$1, %0, %6	\n"
211633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	lw	%1, 0(%2)	# four words source address\n"
212633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, $1		\n"
213633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, %1		\n"
214633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	sltu	$1, %0, %1	\n"
215633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
216633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	lw	%1, 4(%2)	\n"
217633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, $1		\n"
218633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, %1		\n"
219633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	sltu	$1, %0, %1	\n"
220633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
221633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	lw	%1, 8(%2)	\n"
222633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, $1		\n"
223633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, %1		\n"
224633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	sltu	$1, %0, %1	\n"
225633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
226633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	lw	%1, 12(%2)	\n"
227633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, $1		\n"
228633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, %1		\n"
229633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	sltu	$1, %0, %1	\n"
230633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
231633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	lw	%1, 0(%3)	\n"
232633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, $1		\n"
233633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, %1		\n"
234633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	sltu	$1, %0, %1	\n"
235633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
236633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	lw	%1, 4(%3)	\n"
237633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, $1		\n"
238633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, %1		\n"
239633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	sltu	$1, %0, %1	\n"
240633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
241633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	lw	%1, 8(%3)	\n"
242633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, $1		\n"
243633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, %1		\n"
244633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	sltu	$1, %0, %1	\n"
245633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
246633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	lw	%1, 12(%3)	\n"
247633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, $1		\n"
248633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, %1		\n"
249633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	sltu	$1, %0, %1	\n"
250633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
251633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	addu	%0, $1		# Add final carry\n"
252633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	"	.set	pop"
253633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	: "=r" (sum), "=r" (proto)
254633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	: "r" (saddr), "r" (daddr),
255633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	  "0" (htonl(len)), "1" (htonl(proto)), "r" (sum));
256633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
257633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham	return csum_fold(sum);
258633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham}
259633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham
260633c3473533ad9f2cca069b22cc5d95cd4e3510bRaghu Gandham#endif /* _ASM_CHECKSUM_H */
261