-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reviewed-by: Ingo Molnar <mingo@elte.hu> Acked-by: Stephen Neuendorffer <stephen.neuendorffer@xilinx.com> Acked-by: John Linn <john.linn@xilinx.com> Acked-by: John Williams <john.williams@petalogix.com> Signed-off-by: Michal Simek <monstr@monstr.eu>
- Loading branch information
Michal Simek
committed
Mar 27, 2009
1 parent
322ae8e
commit f11e044
Showing
2 changed files
with
261 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/* | ||
* Copyright (C) 2008 Michal Simek <monstr@monstr.eu> | ||
* Copyright (C) 2006 Atmark Techno, Inc. | ||
* | ||
* This file is subject to the terms and conditions of the GNU General Public | ||
* License. See the file "COPYING" in the main directory of this archive | ||
* for more details. | ||
*/ | ||
|
||
#ifndef _ASM_MICROBLAZE_CHECKSUM_H | ||
#define _ASM_MICROBLAZE_CHECKSUM_H | ||
|
||
#include <linux/in6.h> | ||
|
||
/* | ||
* computes the checksum of the TCP/UDP pseudo-header | ||
* returns a 16-bit checksum, already complemented | ||
*/ | ||
static inline __wsum | ||
csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, | ||
unsigned short proto, __wsum sum) | ||
{ | ||
__asm__("add %0, %0, %1\n\t" | ||
"addc %0, %0, %2\n\t" | ||
"addc %0, %0, %3\n\t" | ||
"addc %0, %0, r0\n\t" | ||
: "+&d" (sum) | ||
: "d" (saddr), "d" (daddr), "d" (len + proto)); | ||
|
||
return sum; | ||
} | ||
|
||
/* | ||
* computes the checksum of a memory block at buff, length len, | ||
* and adds in "sum" (32-bit) | ||
* | ||
* returns a 32-bit number suitable for feeding into itself | ||
* or csum_tcpudp_magic | ||
* | ||
* this function must be called with even lengths, except | ||
* for the last fragment, which may be odd | ||
* | ||
* it's best to have buff aligned on a 32-bit boundary | ||
*/ | ||
extern __wsum csum_partial(const void *buff, int len, __wsum sum); | ||
|
||
/* | ||
* the same as csum_partial, but copies from src while it | ||
* checksums | ||
* | ||
* here even more important to align src and dst on a 32-bit (or even | ||
* better 64-bit) boundary | ||
*/ | ||
extern __wsum csum_partial_copy(const char *src, char *dst, int len, int sum); | ||
|
||
/* | ||
* the same as csum_partial_copy, but copies from user space. | ||
* | ||
* here even more important to align src and dst on a 32-bit (or even | ||
* better 64-bit) boundary | ||
*/ | ||
extern __wsum csum_partial_copy_from_user(const char *src, char *dst, | ||
int len, int sum, int *csum_err); | ||
|
||
#define csum_partial_copy_nocheck(src, dst, len, sum) \ | ||
csum_partial_copy((src), (dst), (len), (sum)) | ||
|
||
/* | ||
* This is a version of ip_compute_csum() optimized for IP headers, | ||
* which always checksum on 4 octet boundaries. | ||
* | ||
*/ | ||
extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl); | ||
|
||
/* | ||
* Fold a partial checksum | ||
*/ | ||
static inline __sum16 csum_fold(unsigned int sum) | ||
{ | ||
sum = (sum & 0xffff) + (sum >> 16); | ||
sum = (sum & 0xffff) + (sum >> 16); | ||
return ~sum; | ||
} | ||
|
||
static inline __sum16 | ||
csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len, | ||
unsigned short proto, __wsum sum) | ||
{ | ||
return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); | ||
} | ||
|
||
/* | ||
* this routine is used for miscellaneous IP-like checksums, mainly | ||
* in icmp.c | ||
*/ | ||
extern __sum16 ip_compute_csum(const unsigned char *buff, int len); | ||
|
||
#endif /* _ASM_MICROBLAZE_CHECKSUM_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
/* | ||
* | ||
* INET An implementation of the TCP/IP protocol suite for the LINUX | ||
* operating system. INET is implemented using the BSD Socket | ||
* interface as the means of communication with the user level. | ||
* | ||
* IP/TCP/UDP checksumming routines | ||
* | ||
* Authors: Jorge Cwik, <jorge@laser.satlink.net> | ||
* Arnt Gulbrandsen, <agulbra@nvg.unit.no> | ||
* Tom May, <ftom@netcom.com> | ||
* Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de> | ||
* Lots of code moved from tcp.c and ip.c; see those files | ||
* for more names. | ||
* | ||
* 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek: | ||
* Fixed some nasty bugs, causing some horrible crashes. | ||
* A: At some points, the sum (%0) was used as | ||
* length-counter instead of the length counter | ||
* (%1). Thanks to Roman Hodek for pointing this out. | ||
* B: GCC seems to mess up if one uses too many | ||
* data-registers to hold input values and one tries to | ||
* specify d0 and d1 as scratch registers. Letting gcc | ||
* choose these registers itself solves the problem. | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License | ||
* as published by the Free Software Foundation; either version | ||
* 2 of the License, or (at your option) any later version. | ||
*/ | ||
|
||
/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access | ||
kills, so most of the assembly has to go. */ | ||
|
||
#include <net/checksum.h> | ||
#include <asm/checksum.h> | ||
#include <linux/module.h> | ||
|
||
static inline unsigned short from32to16(unsigned long x) | ||
{ | ||
/* add up 16-bit and 16-bit for 16+c bit */ | ||
x = (x & 0xffff) + (x >> 16); | ||
/* add up carry.. */ | ||
x = (x & 0xffff) + (x >> 16); | ||
return x; | ||
} | ||
|
||
static unsigned int do_csum(const unsigned char *buff, int len) | ||
{ | ||
int odd, count; | ||
unsigned long result = 0; | ||
|
||
if (len <= 0) | ||
goto out; | ||
odd = 1 & (unsigned long) buff; | ||
if (odd) { | ||
result = *buff; | ||
len--; | ||
buff++; | ||
} | ||
count = len >> 1; /* nr of 16-bit words.. */ | ||
if (count) { | ||
if (2 & (unsigned long) buff) { | ||
result += *(unsigned short *) buff; | ||
count--; | ||
len -= 2; | ||
buff += 2; | ||
} | ||
count >>= 1; /* nr of 32-bit words.. */ | ||
if (count) { | ||
unsigned long carry = 0; | ||
do { | ||
unsigned long w = *(unsigned long *) buff; | ||
count--; | ||
buff += 4; | ||
result += carry; | ||
result += w; | ||
carry = (w > result); | ||
} while (count); | ||
result += carry; | ||
result = (result & 0xffff) + (result >> 16); | ||
} | ||
if (len & 2) { | ||
result += *(unsigned short *) buff; | ||
buff += 2; | ||
} | ||
} | ||
if (len & 1) | ||
result += (*buff << 8); | ||
result = from32to16(result); | ||
if (odd) | ||
result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); | ||
out: | ||
return result; | ||
} | ||
|
||
/* | ||
* This is a version of ip_compute_csum() optimized for IP headers, | ||
* which always checksum on 4 octet boundaries. | ||
*/ | ||
__sum16 ip_fast_csum(const void *iph, unsigned int ihl) | ||
{ | ||
return (__force __sum16)~do_csum(iph, ihl*4); | ||
} | ||
|
||
/* | ||
* computes the checksum of a memory block at buff, length len, | ||
* and adds in "sum" (32-bit) | ||
* | ||
* returns a 32-bit number suitable for feeding into itself | ||
* or csum_tcpudp_magic | ||
* | ||
* this function must be called with even lengths, except | ||
* for the last fragment, which may be odd | ||
* | ||
* it's best to have buff aligned on a 32-bit boundary | ||
*/ | ||
__wsum csum_partial(const void *buff, int len, __wsum sum) | ||
{ | ||
unsigned int result = do_csum(buff, len); | ||
|
||
/* add in old sum, and carry.. */ | ||
result += sum; | ||
if (sum > result) | ||
result += 1; | ||
return result; | ||
} | ||
EXPORT_SYMBOL(csum_partial); | ||
|
||
/* | ||
* this routine is used for miscellaneous IP-like checksums, mainly | ||
* in icmp.c | ||
*/ | ||
__sum16 ip_compute_csum(const unsigned char *buff, int len) | ||
{ | ||
return ~do_csum(buff, len); | ||
} | ||
EXPORT_SYMBOL(ip_compute_csum); | ||
|
||
/* | ||
* copy from fs while checksumming, otherwise like csum_partial | ||
*/ | ||
__wsum | ||
csum_partial_copy_from_user(const char __user *src, char *dst, int len, | ||
int sum, int *csum_err) | ||
{ | ||
if (csum_err) | ||
*csum_err = 0; | ||
memcpy(dst, src, len); | ||
return csum_partial(dst, len, sum); | ||
} | ||
EXPORT_SYMBOL(csum_partial_copy_from_user); | ||
|
||
/* | ||
* copy from ds while checksumming, otherwise like csum_partial | ||
*/ | ||
__wsum | ||
csum_partial_copy(const char *src, char *dst, int len, int sum) | ||
{ | ||
memcpy(dst, src, len); | ||
return csum_partial(dst, len, sum); | ||
} | ||
EXPORT_SYMBOL(csum_partial_copy); |