diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-17 20:52:43 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-17 20:52:43 +0400 |
commit | 66bc4a6f34a950c7aede597c578352c3eba82017 (patch) | |
tree | d8005bd9abc0209cff47072d7e48cf19fddc52f5 /arch/m68k/include/asm/checksum.h | |
parent | 96c015b75feaaa67c8744229937bd9c35919d16b (diff) | |
parent | 2985709d7f3078c7609ae7f16affc0fb478d7d7a (diff) | |
download | linux-66bc4a6f34a950c7aede597c578352c3eba82017.tar.xz |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu: (53 commits)
m68knommu: Make PAGE_SIZE available to assembly files.
m68knommu: fix ColdFire definition of CLOCK_TICK_RATE
m68knommu: set multi-function pins for ethernet when enabled
m68knommu: remove special interrupt handling code for ne2k support
m68knommu: relax IO_SPACE_LIMIT setting
m68knommu: remove ColdFire direct interrupt register access
m68knommu: create a speciailized ColdFire 5272 interrupt controller
m68knommu: add support for second interrupt controller of ColdFire 5249
m68knommu: clean up old ColdFire timer irq setup
m68knommu: map ColdFire interrupts to correct masking bits
m68knommu: clean up ColdFire 532x CPU timer setup
m68knommu: simplify ColdFire "timers" clock initialization
m68knommu: support code to mask external interrupts on old ColdFire CPU's
m68knommu: merge old ColdFire interrupt controller masking macros
m68knommu: remove duplicate ColdFire mcf_autovector() code
m68knommu: move ColdFire INTC definitions to new include file
m68knommu: mask off all interrupts in ColdFire intc-simr controller
m68knommu: remove timer device interrupt setup for ColdFire 532x
m68knommu: remove interrupt masking from ColdFire pit timer
m68knommu: remove unecessary interrupt level setting in ColdFire 520x setup
...
Diffstat (limited to 'arch/m68k/include/asm/checksum.h')
-rw-r--r-- | arch/m68k/include/asm/checksum.h | 173 |
1 files changed, 169 insertions, 4 deletions
diff --git a/arch/m68k/include/asm/checksum.h b/arch/m68k/include/asm/checksum.h index 1cf544767453..ec514485c8b6 100644 --- a/arch/m68k/include/asm/checksum.h +++ b/arch/m68k/include/asm/checksum.h @@ -1,5 +1,170 @@ -#ifdef __uClinux__ -#include "checksum_no.h" +#ifndef _M68K_CHECKSUM_H +#define _M68K_CHECKSUM_H + +#include <linux/in6.h> + +/* + * 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); + +/* + * 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_from_user(const void __user *src, + void *dst, + int len, __wsum sum, + int *csum_err); + +extern __wsum csum_partial_copy_nocheck(const void *src, + void *dst, int len, + __wsum sum); + + +#ifdef CONFIG_COLDFIRE + +/* + * The ColdFire cores don't support all the 68k instructions used + * in the optimized checksum code below. So it reverts back to using + * more standard C coded checksums. The fast checksum code is + * significantly larger than the optimized version, so it is not + * inlined here. + */ +__sum16 ip_fast_csum(const void *iph, unsigned int ihl); + +static inline __sum16 csum_fold(__wsum sum) +{ + unsigned int tmp = (__force u32)sum; + + tmp = (tmp & 0xffff) + (tmp >> 16); + tmp = (tmp & 0xffff) + (tmp >> 16); + + return (__force __sum16)~tmp; +} + #else -#include "checksum_mm.h" -#endif + +/* + * This is a version of ip_fast_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. + */ +static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) +{ + unsigned int sum = 0; + unsigned long tmp; + + __asm__ ("subqw #1,%2\n" + "1:\t" + "movel %1@+,%3\n\t" + "addxl %3,%0\n\t" + "dbra %2,1b\n\t" + "movel %0,%3\n\t" + "swap %3\n\t" + "addxw %3,%0\n\t" + "clrw %3\n\t" + "addxw %3,%0\n\t" + : "=d" (sum), "=&a" (iph), "=&d" (ihl), "=&d" (tmp) + : "0" (sum), "1" (iph), "2" (ihl) + : "memory"); + return (__force __sum16)~sum; +} + +static inline __sum16 csum_fold(__wsum sum) +{ + unsigned int tmp = (__force u32)sum; + + __asm__("swap %1\n\t" + "addw %1, %0\n\t" + "clrw %1\n\t" + "addxw %1, %0" + : "=&d" (sum), "=&d" (tmp) + : "0" (sum), "1" (tmp)); + + return (__force __sum16)~sum; +} + +#endif /* CONFIG_COLDFIRE */ + +static inline __wsum +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, + unsigned short proto, __wsum sum) +{ + __asm__ ("addl %2,%0\n\t" + "addxl %3,%0\n\t" + "addxl %4,%0\n\t" + "clrl %1\n\t" + "addxl %1,%0" + : "=&d" (sum), "=d" (saddr) + : "g" (daddr), "1" (saddr), "d" (len + proto), + "0" (sum)); + return sum; +} + + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +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 + */ + +static inline __sum16 ip_compute_csum(const void *buff, int len) +{ + return csum_fold (csum_partial(buff, len, 0)); +} + +#define _HAVE_ARCH_IPV6_CSUM +static __inline__ __sum16 +csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, + __u32 len, unsigned short proto, __wsum sum) +{ + register unsigned long tmp; + __asm__("addl %2@,%0\n\t" + "movel %2@(4),%1\n\t" + "addxl %1,%0\n\t" + "movel %2@(8),%1\n\t" + "addxl %1,%0\n\t" + "movel %2@(12),%1\n\t" + "addxl %1,%0\n\t" + "movel %3@,%1\n\t" + "addxl %1,%0\n\t" + "movel %3@(4),%1\n\t" + "addxl %1,%0\n\t" + "movel %3@(8),%1\n\t" + "addxl %1,%0\n\t" + "movel %3@(12),%1\n\t" + "addxl %1,%0\n\t" + "addxl %4,%0\n\t" + "clrl %1\n\t" + "addxl %1,%0" + : "=&d" (sum), "=&d" (tmp) + : "a" (saddr), "a" (daddr), "d" (len + proto), + "0" (sum)); + + return csum_fold(sum); +} + +#endif /* _M68K_CHECKSUM_H */ |