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
  34#define _HAVE_ARCH_CSUM_AND_COPY
  35extern __wsum csum_and_copy_from_user(const void __user *src,
  36                                                void *dst,
  37                                                int len);
  38
  39extern __wsum csum_partial_copy_nocheck(const void *src,
  40                                              void *dst, int len);
  41
  42/*
  43 *      This is a version of ip_fast_csum() optimized for IP headers,
  44 *      which always checksum on 4 octet boundaries.
  45 */
  46static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
  47{
  48        unsigned int sum = 0;
  49        unsigned long tmp;
  50
  51        __asm__ ("subqw #1,%2\n"
  52                 "1:\t"
  53                 "movel %1@+,%3\n\t"
  54                 "addxl %3,%0\n\t"
  55                 "dbra  %2,1b\n\t"
  56                 "movel %0,%3\n\t"
  57                 "swap  %3\n\t"
  58                 "addxw %3,%0\n\t"
  59                 "clrw  %3\n\t"
  60                 "addxw %3,%0\n\t"
  61                 : "=d" (sum), "=&a" (iph), "=&d" (ihl), "=&d" (tmp)
  62                 : "0" (sum), "1" (iph), "2" (ihl)
  63                 : "memory");
  64        return (__force __sum16)~sum;
  65}
  66
  67static inline __sum16 csum_fold(__wsum sum)
  68{
  69        unsigned int tmp = (__force u32)sum;
  70
  71        __asm__("swap %1\n\t"
  72                "addw %1, %0\n\t"
  73                "clrw %1\n\t"
  74                "addxw %1, %0"
  75                : "=&d" (sum), "=&d" (tmp)
  76                : "0" (sum), "1" (tmp));
  77
  78        return (__force __sum16)~sum;
  79}
  80
  81static inline __wsum
  82csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
  83                  unsigned short proto, __wsum sum)
  84{
  85        __asm__ ("addl  %2,%0\n\t"
  86                 "addxl %3,%0\n\t"
  87                 "addxl %4,%0\n\t"
  88                 "clrl %1\n\t"
  89                 "addxl %1,%0"
  90                 : "=&d" (sum), "=d" (saddr)
  91                 : "g" (daddr), "1" (saddr), "d" (len + proto),
  92                   "0" (sum));
  93        return sum;
  94}
  95
  96
  97/*
  98 * computes the checksum of the TCP/UDP pseudo-header
  99 * returns a 16-bit checksum, already complemented
 100 */
 101static inline __sum16
 102csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
 103                  unsigned short proto, __wsum sum)
 104{
 105        return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
 106}
 107
 108/*
 109 * this routine is used for miscellaneous IP-like checksums, mainly
 110 * in icmp.c
 111 */
 112
 113static inline __sum16 ip_compute_csum(const void *buff, int len)
 114{
 115        return csum_fold (csum_partial(buff, len, 0));
 116}
 117
 118#define _HAVE_ARCH_IPV6_CSUM
 119static __inline__ __sum16
 120csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
 121                __u32 len, __u8 proto, __wsum sum)
 122{
 123        register unsigned long tmp;
 124        __asm__("addl %2@,%0\n\t"
 125                "movel %2@(4),%1\n\t"
 126                "addxl %1,%0\n\t"
 127                "movel %2@(8),%1\n\t"
 128                "addxl %1,%0\n\t"
 129                "movel %2@(12),%1\n\t"
 130                "addxl %1,%0\n\t"
 131                "movel %3@,%1\n\t"
 132                "addxl %1,%0\n\t"
 133                "movel %3@(4),%1\n\t"
 134                "addxl %1,%0\n\t"
 135                "movel %3@(8),%1\n\t"
 136                "addxl %1,%0\n\t"
 137                "movel %3@(12),%1\n\t"
 138                "addxl %1,%0\n\t"
 139                "addxl %4,%0\n\t"
 140                "clrl %1\n\t"
 141                "addxl %1,%0"
 142                : "=&d" (sum), "=&d" (tmp)
 143                : "a" (saddr), "a" (daddr), "d" (len + proto),
 144                  "0" (sum));
 145
 146        return csum_fold(sum);
 147}
 148
 149#endif /* CONFIG_GENERIC_CSUM */
 150#endif /* _M68K_CHECKSUM_H */
 151