Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.16-rc5 183 lines 4.8 kB view raw
1/* checksum.h: FRV checksumming 2 * 3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12#ifndef _ASM_CHECKSUM_H 13#define _ASM_CHECKSUM_H 14 15#include <linux/in6.h> 16 17/* 18 * computes the checksum of a memory block at buff, length len, 19 * and adds in "sum" (32-bit) 20 * 21 * returns a 32-bit number suitable for feeding into itself 22 * or csum_tcpudp_magic 23 * 24 * this function must be called with even lengths, except 25 * for the last fragment, which may be odd 26 * 27 * it's best to have buff aligned on a 32-bit boundary 28 */ 29unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum); 30 31/* 32 * the same as csum_partial, but copies from src while it 33 * checksums 34 * 35 * here even more important to align src and dst on a 32-bit (or even 36 * better 64-bit) boundary 37 */ 38unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum); 39 40/* 41 * the same as csum_partial_copy, but copies from user space. 42 * 43 * here even more important to align src and dst on a 32-bit (or even 44 * better 64-bit) boundary 45 */ 46extern unsigned int csum_partial_copy_from_user(const char *src, char *dst, 47 int len, int sum, int *csum_err); 48 49#define csum_partial_copy_nocheck(src, dst, len, sum) \ 50 csum_partial_copy((src), (dst), (len), (sum)) 51 52/* 53 * This is a version of ip_compute_csum() optimized for IP headers, 54 * which always checksum on 4 octet boundaries. 55 * 56 */ 57static inline 58unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl) 59{ 60 unsigned int tmp, inc, sum = 0; 61 62 asm(" addcc gr0,gr0,gr0,icc0\n" /* clear icc0.C */ 63 " subi %1,#4,%1 \n" 64 "0: \n" 65 " ldu.p @(%1,%3),%4 \n" 66 " subicc %2,#1,%2,icc1 \n" 67 " addxcc.p %4,%0,%0,icc0 \n" 68 " bhi icc1,#2,0b \n" 69 70 /* fold the 33-bit result into 16-bits */ 71 " addxcc gr0,%0,%0,icc0 \n" 72 " srli %0,#16,%1 \n" 73 " sethi #0,%0 \n" 74 " add %1,%0,%0 \n" 75 " srli %0,#16,%1 \n" 76 " add %1,%0,%0 \n" 77 78 : "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (inc), "=&r"(tmp) 79 : "0" (sum), "1" (iph), "2" (ihl), "3" (4), 80 "m"(*(volatile struct { int _[100]; } *)iph) 81 : "icc0", "icc1" 82 ); 83 84 return ~sum; 85} 86 87/* 88 * Fold a partial checksum 89 */ 90static inline unsigned int csum_fold(unsigned int sum) 91{ 92 unsigned int tmp; 93 94 asm(" srli %0,#16,%1 \n" 95 " sethi #0,%0 \n" 96 " add %1,%0,%0 \n" 97 " srli %0,#16,%1 \n" 98 " add %1,%0,%0 \n" 99 : "=r"(sum), "=&r"(tmp) 100 : "0"(sum) 101 ); 102 103 return ~sum; 104} 105 106/* 107 * computes the checksum of the TCP/UDP pseudo-header 108 * returns a 16-bit checksum, already complemented 109 */ 110static inline unsigned int 111csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len, 112 unsigned short proto, unsigned int sum) 113{ 114 asm(" addcc %1,%0,%0,icc0 \n" 115 " addxcc %2,%0,%0,icc0 \n" 116 " addxcc %3,%0,%0,icc0 \n" 117 " addxcc gr0,%0,%0,icc0 \n" 118 : "=r" (sum) 119 : "r" (daddr), "r" (saddr), "r" (len + proto), "0"(sum) 120 : "icc0" 121 ); 122 return sum; 123} 124 125static inline unsigned short int 126csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len, 127 unsigned short proto, unsigned int sum) 128{ 129 return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); 130} 131 132/* 133 * this routine is used for miscellaneous IP-like checksums, mainly 134 * in icmp.c 135 */ 136extern unsigned short ip_compute_csum(const unsigned char * buff, int len); 137 138#define _HAVE_ARCH_IPV6_CSUM 139static inline unsigned short int 140csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, 141 __u32 len, unsigned short proto, unsigned int sum) 142{ 143 unsigned long tmp, tmp2; 144 145 asm(" addcc %2,%0,%0,icc0 \n" 146 147 /* add up the source addr */ 148 " ldi @(%3,0),%1 \n" 149 " addxcc %1,%0,%0,icc0 \n" 150 " ldi @(%3,4),%2 \n" 151 " addxcc %2,%0,%0,icc0 \n" 152 " ldi @(%3,8),%1 \n" 153 " addxcc %1,%0,%0,icc0 \n" 154 " ldi @(%3,12),%2 \n" 155 " addxcc %2,%0,%0,icc0 \n" 156 157 /* add up the dest addr */ 158 " ldi @(%4,0),%1 \n" 159 " addxcc %1,%0,%0,icc0 \n" 160 " ldi @(%4,4),%2 \n" 161 " addxcc %2,%0,%0,icc0 \n" 162 " ldi @(%4,8),%1 \n" 163 " addxcc %1,%0,%0,icc0 \n" 164 " ldi @(%4,12),%2 \n" 165 " addxcc %2,%0,%0,icc0 \n" 166 167 /* fold the 33-bit result into 16-bits */ 168 " addxcc gr0,%0,%0,icc0 \n" 169 " srli %0,#16,%1 \n" 170 " sethi #0,%0 \n" 171 " add %1,%0,%0 \n" 172 " srli %0,#16,%1 \n" 173 " add %1,%0,%0 \n" 174 175 : "=r" (sum), "=&r" (tmp), "=r" (tmp2) 176 : "r" (saddr), "r" (daddr), "0" (sum), "2" (len + proto) 177 : "icc0" 178 ); 179 180 return ~sum; 181} 182 183#endif /* _ASM_CHECKSUM_H */