1 /*
2 * arch/s390/lib/checksum.c
3 * S390 fast network checksum routines
4 *
5 * S390 version
6 * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Author(s): Ulrich Hild (first version),
8 * Martin Schwidefsky (schwidefsky@de.ibm.com),
9 * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
10 *
11 * This file contains network checksum routines
12 */
13
14 #include <linux/string.h>
15 #include <linux/types.h>
16 #include <asm/uaccess.h>
17 #include <asm/byteorder.h>
18 #include <asm/checksum.h>
19
20 /*
21 * computes a partial checksum, e.g. for TCP/UDP fragments
22 */
23 unsigned int
csum_partial(const unsigned char * buff,int len,unsigned int sum)24 csum_partial (const unsigned char *buff, int len, unsigned int sum)
25 {
26 register_pair rp;
27 /*
28 * Experiments with ethernet and slip connections show that buff
29 * is aligned on either a 2-byte or 4-byte boundary.
30 */
31 rp.subreg.even = (unsigned long) buff;
32 rp.subreg.odd = (unsigned long) len;
33 __asm__ __volatile__ (
34 "0: cksm %0,%1\n" /* do checksum on longs */
35 " jo 0b\n"
36 : "+&d" (sum), "+&a" (rp) : : "cc" );
37 return sum;
38 }
39
40 /*
41 * Fold a partial checksum without adding pseudo headers
42 */
csum_fold(unsigned int sum)43 unsigned short csum_fold(unsigned int sum)
44 {
45 register_pair rp;
46
47 __asm__ __volatile__ (
48 " slr %N1,%N1\n" /* %0 = H L */
49 " lr %1,%0\n" /* %0 = H L, %1 = H L 0 0 */
50 " srdl %1,16\n" /* %0 = H L, %1 = 0 H L 0 */
51 " alr %1,%N1\n" /* %0 = H L, %1 = L H L 0 */
52 " alr %0,%1\n" /* %0 = H+L+C L+H */
53 " srl %0,16\n" /* %0 = H+L+C */
54 : "+&d" (sum), "=d" (rp) : : "cc" );
55 return ((unsigned short) ~sum);
56 }
57
58