linux/arch/m68k/include/asm/checksum.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef _M68K_CHECKSUM_H
   3#define _M68K_CHECKSUM_H
   4
   5#include <linux/in6.h>
   6
   7#ifdef CONFIG_GENERIC_CSUM
   8#include <asm-generic/checksum.h>
   9#else
  10
  11/*
  12 * computes the checksum of a memory block at buff, length len,
  13 * and adds in "sum" (32-bit)
  14 *
  15 * returns a 32-bit number suitable for feeding into itself
  16 * or csum_tcpudp_magic
  17 *
  18 * this function must be called with even lengths, except
  19 * for the last fragment, which may be odd
  20 *
  21 * it's best to have buff aligned on a 32-bit boundary
  22 */
  23__wsum csum_partial(const void *buff, int len, __wsum sum);
  24
  25/*
  26 * the same as csum_partial, but copies from src while it
  27 * checksums
  28 *
  29 * here even more important to align src and dst on a 32-bit (or even
  30 * better 64-bit) boundary
  31 */
  32
  33#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
  34extern __wsum csum_and_copy_from_user(const void __user *src,
  35                                                void *dst,
  36                                                int len, __wsum sum,
  37                                                int *csum_err);
  38
  39extern __wsum csum_partial_copy_nocheck(const void *src,
  40                                              void *dst, int len,
  41                                              __wsum sum);
  42
  43/*
  44 *      This is a version of ip_fast_csum() optimized for IP headers,
  45 *      which always checksum on 4 octet boundaries.
  46 */
  47static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
  48{
  49        unsigned int sum = 0;
  50        unsigned long tmp;
  51
  52        __asm__ ("subqw #1,%2\n"
  53                 "1:\t"
  54                 "movel %1@+,%3\n\t"
  55                 "addxl %3,%0\n\t"
  56                 "dbra  %2,1b\n\t"
  57                 "movel %0,%3\n\t"
  58                 "swap  %3\n\t"
  59                 "addxw %3,%0\n\t"
  60                 "clrw  %3\n\t"
  61                 "addxw %3,%0\n\t"
  62                 : "=d" (sum), "=&a" (iph), "=&d" (ihl), "=&d" (tmp)
  63                 : "0" (sum), "1" (iph), "2" (ihl)
  64                 : "memory");
  65        return (__force __sum16)~sum;
  66}
  67
  68static inline __sum16 csum_fold(__wsum sum)
  69{
  70        unsigned int tmp = (__force u32)sum;
  71
  72        __asm__("swap %1\n\t"
  73                "addw %1, %0\n\t"
  74                "clrw %1\n\t"
  75                "addxw %1, %0"
  76                : "=&d" (sum), "=&d" (tmp)
  77                : "0" (sum), "1" (tmp));
  78
  79        return (__force __sum16)~sum;
  80}
  81
  82static inline __wsum
  83csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
  84                  unsigned short proto, __wsum sum)
  85{
  86        __asm__ ("addl  %2,%0\n\t"
  87                 "addxl %3,%0\n\t"
  88                 "addxl %4,%0\n\t"
  89                 "clrl %1\n\t"
  90                 "addxl %1,%0"
  91                 : "=&d" (sum), "=d" (saddr)
  92                 : "g" (daddr), "1" (saddr), "d" (len + proto),
  93                   "0" (sum));
  94        return sum;
  95}
  96
  97
  98/*
  99 * computes the checksum of the TCP/UDP pseudo-header
 100 * returns a 16-bit checksum, already complemented
 101 */
 102static inline __sum16
 103csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
 104                  unsigned short proto, __wsum sum)
 105{
 106        return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
 107}
 108
 109/*
 110 * this routine is used for miscellaneous IP-like checksums, mainly
 111 * in icmp.c
 112 */
 113
 114static inline __sum16 ip_compute_csum(const void *buff, int len)
 115{
 116        return csum_fold (csum_partial(buff, len, 0));
 117}
 118
 119#define _HAVE_ARCH_IPV6_CSUM
 120static __inline__ __sum16
 121csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
 122                __u32 len, __u8 proto, __wsum sum)
 123{
 124        register unsigned long tmp;
 125        __asm__("addl %2@,%0\n\t"
 126                "movel %2@(4),%1\n\t"
 127                "addxl %1,%0\n\t"
 128                "movel %2@(8),%1\n\t"
 129                "addxl %1,%0\n\t"
 130                "movel %2@(12),%1\n\t"
 131                "addxl %1,%0\n\t"
 132                "movel %3@,%1\n\t"
 133                "addxl %1,%0\n\t"
 134                "movel %3@(4),%1\n\t"
 135                "addxl %1,%0\n\t"
 136                "movel %3@(8),%1\n\t"
 137                "addxl %1,%0\n\t"
 138                "movel %3@(12),%1\n\t"
 139                "addxl %1,%0\n\t"
 140                "addxl %4,%0\n\t"
 141                "clrl %1\n\t"
 142                "addxl %1,%0"
 143                : "=&d" (sum), "=&d" (tmp)
 144                : "a" (saddr), "a" (daddr), "d" (len + proto),
 145                  "0" (sum));
 146
 147        return csum_fold(sum);
 148}
 149
 150#endif /* CONFIG_GENERIC_CSUM */
 151#endif /* _M68K_CHECKSUM_H */
 152