linux-bk/include/asm-mips/checksum.h
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 1995, 96, 97, 98, 99, 2001 by Ralf Baechle
   7 * Copyright (C) 1999 Silicon Graphics, Inc.
   8 * Copyright (C) 2001 Thiemo Seufer.
   9 * Copyright (C) 2002 Maciej W. Rozycki
  10 */
  11#ifndef _ASM_CHECKSUM_H
  12#define _ASM_CHECKSUM_H
  13
  14#include <linux/config.h>
  15#include <linux/in6.h>
  16
  17#include <asm/uaccess.h>
  18
  19/*
  20 * computes the checksum of a memory block at buff, length len,
  21 * and adds in "sum" (32-bit)
  22 *
  23 * returns a 32-bit number suitable for feeding into itself
  24 * or csum_tcpudp_magic
  25 *
  26 * this function must be called with even lengths, except
  27 * for the last fragment, which may be odd
  28 *
  29 * it's best to have buff aligned on a 32-bit boundary
  30 */
  31unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum);
  32
  33/*
  34 * this is a new version of the above that records errors it finds in *errp,
  35 * but continues and zeros the rest of the buffer.
  36 */
  37unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst, int len,
  38                                         unsigned int sum, int *errp);
  39
  40/*
  41 * Copy and checksum to user
  42 */
  43#define HAVE_CSUM_COPY_USER
  44static inline unsigned int csum_and_copy_to_user (const unsigned char *src,
  45                                                  unsigned char __user *dst,
  46                                                  int len, int sum,
  47                                                  int *err_ptr)
  48{
  49        might_sleep();
  50        sum = csum_partial(src, len, sum);
  51
  52        if (copy_to_user(dst, src, len)) {
  53                *err_ptr = -EFAULT;
  54                return -1;
  55        }
  56
  57        return sum;
  58}
  59
  60/*
  61 * the same as csum_partial, but copies from user space (but on MIPS
  62 * we have just one address space, so this is identical to the above)
  63 */
  64unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst,
  65                                       int len, unsigned int sum);
  66
  67/*
  68 *      Fold a partial checksum without adding pseudo headers
  69 */
  70static inline unsigned short int csum_fold(unsigned int sum)
  71{
  72        __asm__(
  73        ".set\tnoat\t\t\t# csum_fold\n\t"
  74        "sll\t$1,%0,16\n\t"
  75        "addu\t%0,$1\n\t"
  76        "sltu\t$1,%0,$1\n\t"
  77        "srl\t%0,%0,16\n\t"
  78        "addu\t%0,$1\n\t"
  79        "xori\t%0,0xffff\n\t"
  80        ".set\tat"
  81        : "=r" (sum)
  82        : "0" (sum));
  83
  84        return sum;
  85}
  86
  87/*
  88 *      This is a version of ip_compute_csum() optimized for IP headers,
  89 *      which always checksum on 4 octet boundaries.
  90 *
  91 *      By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
  92 *      Arnt Gulbrandsen.
  93 */
  94static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl)
  95{
  96        unsigned int *word = (unsigned int *) iph;
  97        unsigned int *stop = word + ihl;
  98        unsigned int csum;
  99        int carry;
 100
 101        csum = word[0];
 102        csum += word[1];
 103        carry = (csum < word[1]);
 104        csum += carry;
 105
 106        csum += word[2];
 107        carry = (csum < word[2]);
 108        csum += carry;
 109
 110        csum += word[3];
 111        carry = (csum < word[3]);
 112        csum += carry;
 113
 114        word += 4;
 115        do {
 116                csum += *word;
 117                carry = (csum < *word);
 118                csum += carry;
 119                word++;
 120        } while (word != stop);
 121
 122        return csum_fold(csum);
 123}
 124
 125static inline unsigned int csum_tcpudp_nofold(unsigned long saddr,
 126        unsigned long daddr, unsigned short len, unsigned short proto,
 127        unsigned int sum)
 128{
 129        __asm__(
 130        ".set\tnoat\t\t\t# csum_tcpudp_nofold\n\t"
 131#ifdef CONFIG_MIPS32
 132        "addu\t%0, %2\n\t"
 133        "sltu\t$1, %0, %2\n\t"
 134        "addu\t%0, $1\n\t"
 135
 136        "addu\t%0, %3\n\t"
 137        "sltu\t$1, %0, %3\n\t"
 138        "addu\t%0, $1\n\t"
 139
 140        "addu\t%0, %4\n\t"
 141        "sltu\t$1, %0, %4\n\t"
 142        "addu\t%0, $1\n\t"
 143#endif
 144#ifdef CONFIG_MIPS64
 145        "daddu\t%0, %2\n\t"
 146        "daddu\t%0, %3\n\t"
 147        "daddu\t%0, %4\n\t"
 148        "dsll32\t$1, %0, 0\n\t"
 149        "daddu\t%0, $1\n\t"
 150        "dsrl32\t%0, %0, 0\n\t"
 151#endif
 152        ".set\tat"
 153        : "=r" (sum)
 154        : "0" (daddr), "r"(saddr),
 155#ifdef __MIPSEL__
 156          "r" (((unsigned long)htons(len)<<16) + proto*256),
 157#else
 158          "r" (((unsigned long)(proto)<<16) + len),
 159#endif
 160          "r" (sum));
 161
 162        return sum;
 163}
 164
 165/*
 166 * computes the checksum of the TCP/UDP pseudo-header
 167 * returns a 16-bit checksum, already complemented
 168 */
 169static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
 170                                                   unsigned long daddr,
 171                                                   unsigned short len,
 172                                                   unsigned short proto,
 173                                                   unsigned int sum)
 174{
 175        return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
 176}
 177
 178/*
 179 * this routine is used for miscellaneous IP-like checksums, mainly
 180 * in icmp.c
 181 */
 182static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
 183{
 184        return csum_fold(csum_partial(buff, len, 0));
 185}
 186
 187#define _HAVE_ARCH_IPV6_CSUM
 188static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
 189                                                     struct in6_addr *daddr,
 190                                                     __u32 len,
 191                                                     unsigned short proto,
 192                                                     unsigned int sum)
 193{
 194        __asm__(
 195        ".set\tpush\t\t\t# csum_ipv6_magic\n\t"
 196        ".set\tnoreorder\n\t"
 197        ".set\tnoat\n\t"
 198        "addu\t%0, %5\t\t\t# proto (long in network byte order)\n\t"
 199        "sltu\t$1, %0, %5\n\t"
 200        "addu\t%0, $1\n\t"
 201
 202        "addu\t%0, %6\t\t\t# csum\n\t"
 203        "sltu\t$1, %0, %6\n\t"
 204        "lw\t%1, 0(%2)\t\t\t# four words source address\n\t"
 205        "addu\t%0, $1\n\t"
 206        "addu\t%0, %1\n\t"
 207        "sltu\t$1, %0, %1\n\t"
 208
 209        "lw\t%1, 4(%2)\n\t"
 210        "addu\t%0, $1\n\t"
 211        "addu\t%0, %1\n\t"
 212        "sltu\t$1, %0, %1\n\t"
 213
 214        "lw\t%1, 8(%2)\n\t"
 215        "addu\t%0, $1\n\t"
 216        "addu\t%0, %1\n\t"
 217        "sltu\t$1, %0, %1\n\t"
 218
 219        "lw\t%1, 12(%2)\n\t"
 220        "addu\t%0, $1\n\t"
 221        "addu\t%0, %1\n\t"
 222        "sltu\t$1, %0, %1\n\t"
 223
 224        "lw\t%1, 0(%3)\n\t"
 225        "addu\t%0, $1\n\t"
 226        "addu\t%0, %1\n\t"
 227        "sltu\t$1, %0, %1\n\t"
 228
 229        "lw\t%1, 4(%3)\n\t"
 230        "addu\t%0, $1\n\t"
 231        "addu\t%0, %1\n\t"
 232        "sltu\t$1, %0, %1\n\t"
 233
 234        "lw\t%1, 8(%3)\n\t"
 235        "addu\t%0, $1\n\t"
 236        "addu\t%0, %1\n\t"
 237        "sltu\t$1, %0, %1\n\t"
 238
 239        "lw\t%1, 12(%3)\n\t"
 240        "addu\t%0, $1\n\t"
 241        "addu\t%0, %1\n\t"
 242        "sltu\t$1, %0, %1\n\t"
 243
 244        "addu\t%0, $1\t\t\t# Add final carry\n\t"
 245        ".set\tpop"
 246        : "=r" (sum), "=r" (proto)
 247        : "r" (saddr), "r" (daddr),
 248          "0" (htonl(len)), "1" (htonl(proto)), "r" (sum));
 249
 250        return csum_fold(sum);
 251}
 252
 253#endif /* _ASM_CHECKSUM_H */
 254
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.