18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef _M68K_CHECKSUM_H 38c2ecf20Sopenharmony_ci#define _M68K_CHECKSUM_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <linux/in6.h> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#ifdef CONFIG_GENERIC_CSUM 88c2ecf20Sopenharmony_ci#include <asm-generic/checksum.h> 98c2ecf20Sopenharmony_ci#else 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci/* 128c2ecf20Sopenharmony_ci * computes the checksum of a memory block at buff, length len, 138c2ecf20Sopenharmony_ci * and adds in "sum" (32-bit) 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * returns a 32-bit number suitable for feeding into itself 168c2ecf20Sopenharmony_ci * or csum_tcpudp_magic 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * this function must be called with even lengths, except 198c2ecf20Sopenharmony_ci * for the last fragment, which may be odd 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * it's best to have buff aligned on a 32-bit boundary 228c2ecf20Sopenharmony_ci */ 238c2ecf20Sopenharmony_ci__wsum csum_partial(const void *buff, int len, __wsum sum); 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci/* 268c2ecf20Sopenharmony_ci * the same as csum_partial, but copies from src while it 278c2ecf20Sopenharmony_ci * checksums 288c2ecf20Sopenharmony_ci * 298c2ecf20Sopenharmony_ci * here even more important to align src and dst on a 32-bit (or even 308c2ecf20Sopenharmony_ci * better 64-bit) boundary 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER 348c2ecf20Sopenharmony_ci#define _HAVE_ARCH_CSUM_AND_COPY 358c2ecf20Sopenharmony_ciextern __wsum csum_and_copy_from_user(const void __user *src, 368c2ecf20Sopenharmony_ci void *dst, 378c2ecf20Sopenharmony_ci int len); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ciextern __wsum csum_partial_copy_nocheck(const void *src, 408c2ecf20Sopenharmony_ci void *dst, int len); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* 438c2ecf20Sopenharmony_ci * This is a version of ip_fast_csum() optimized for IP headers, 448c2ecf20Sopenharmony_ci * which always checksum on 4 octet boundaries. 458c2ecf20Sopenharmony_ci */ 468c2ecf20Sopenharmony_cistatic inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci unsigned int sum = 0; 498c2ecf20Sopenharmony_ci unsigned long tmp; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci __asm__ ("subqw #1,%2\n" 528c2ecf20Sopenharmony_ci "1:\t" 538c2ecf20Sopenharmony_ci "movel %1@+,%3\n\t" 548c2ecf20Sopenharmony_ci "addxl %3,%0\n\t" 558c2ecf20Sopenharmony_ci "dbra %2,1b\n\t" 568c2ecf20Sopenharmony_ci "movel %0,%3\n\t" 578c2ecf20Sopenharmony_ci "swap %3\n\t" 588c2ecf20Sopenharmony_ci "addxw %3,%0\n\t" 598c2ecf20Sopenharmony_ci "clrw %3\n\t" 608c2ecf20Sopenharmony_ci "addxw %3,%0\n\t" 618c2ecf20Sopenharmony_ci : "=d" (sum), "=&a" (iph), "=&d" (ihl), "=&d" (tmp) 628c2ecf20Sopenharmony_ci : "0" (sum), "1" (iph), "2" (ihl) 638c2ecf20Sopenharmony_ci : "memory"); 648c2ecf20Sopenharmony_ci return (__force __sum16)~sum; 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic inline __sum16 csum_fold(__wsum sum) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci unsigned int tmp = (__force u32)sum; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci __asm__("swap %1\n\t" 728c2ecf20Sopenharmony_ci "addw %1, %0\n\t" 738c2ecf20Sopenharmony_ci "clrw %1\n\t" 748c2ecf20Sopenharmony_ci "addxw %1, %0" 758c2ecf20Sopenharmony_ci : "=&d" (sum), "=&d" (tmp) 768c2ecf20Sopenharmony_ci : "0" (sum), "1" (tmp)); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci return (__force __sum16)~sum; 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic inline __wsum 828c2ecf20Sopenharmony_cicsum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, 838c2ecf20Sopenharmony_ci unsigned short proto, __wsum sum) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci __asm__ ("addl %2,%0\n\t" 868c2ecf20Sopenharmony_ci "addxl %3,%0\n\t" 878c2ecf20Sopenharmony_ci "addxl %4,%0\n\t" 888c2ecf20Sopenharmony_ci "clrl %1\n\t" 898c2ecf20Sopenharmony_ci "addxl %1,%0" 908c2ecf20Sopenharmony_ci : "=&d" (sum), "=d" (saddr) 918c2ecf20Sopenharmony_ci : "g" (daddr), "1" (saddr), "d" (len + proto), 928c2ecf20Sopenharmony_ci "0" (sum)); 938c2ecf20Sopenharmony_ci return sum; 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci/* 988c2ecf20Sopenharmony_ci * computes the checksum of the TCP/UDP pseudo-header 998c2ecf20Sopenharmony_ci * returns a 16-bit checksum, already complemented 1008c2ecf20Sopenharmony_ci */ 1018c2ecf20Sopenharmony_cistatic inline __sum16 1028c2ecf20Sopenharmony_cicsum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len, 1038c2ecf20Sopenharmony_ci unsigned short proto, __wsum sum) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci/* 1098c2ecf20Sopenharmony_ci * this routine is used for miscellaneous IP-like checksums, mainly 1108c2ecf20Sopenharmony_ci * in icmp.c 1118c2ecf20Sopenharmony_ci */ 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic inline __sum16 ip_compute_csum(const void *buff, int len) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci return csum_fold (csum_partial(buff, len, 0)); 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci#define _HAVE_ARCH_IPV6_CSUM 1198c2ecf20Sopenharmony_cistatic __inline__ __sum16 1208c2ecf20Sopenharmony_cicsum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, 1218c2ecf20Sopenharmony_ci __u32 len, __u8 proto, __wsum sum) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci register unsigned long tmp; 1248c2ecf20Sopenharmony_ci __asm__("addl %2@,%0\n\t" 1258c2ecf20Sopenharmony_ci "movel %2@(4),%1\n\t" 1268c2ecf20Sopenharmony_ci "addxl %1,%0\n\t" 1278c2ecf20Sopenharmony_ci "movel %2@(8),%1\n\t" 1288c2ecf20Sopenharmony_ci "addxl %1,%0\n\t" 1298c2ecf20Sopenharmony_ci "movel %2@(12),%1\n\t" 1308c2ecf20Sopenharmony_ci "addxl %1,%0\n\t" 1318c2ecf20Sopenharmony_ci "movel %3@,%1\n\t" 1328c2ecf20Sopenharmony_ci "addxl %1,%0\n\t" 1338c2ecf20Sopenharmony_ci "movel %3@(4),%1\n\t" 1348c2ecf20Sopenharmony_ci "addxl %1,%0\n\t" 1358c2ecf20Sopenharmony_ci "movel %3@(8),%1\n\t" 1368c2ecf20Sopenharmony_ci "addxl %1,%0\n\t" 1378c2ecf20Sopenharmony_ci "movel %3@(12),%1\n\t" 1388c2ecf20Sopenharmony_ci "addxl %1,%0\n\t" 1398c2ecf20Sopenharmony_ci "addxl %4,%0\n\t" 1408c2ecf20Sopenharmony_ci "clrl %1\n\t" 1418c2ecf20Sopenharmony_ci "addxl %1,%0" 1428c2ecf20Sopenharmony_ci : "=&d" (sum), "=&d" (tmp) 1438c2ecf20Sopenharmony_ci : "a" (saddr), "a" (daddr), "d" (len + proto), 1448c2ecf20Sopenharmony_ci "0" (sum)); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci return csum_fold(sum); 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci#endif /* CONFIG_GENERIC_CSUM */ 1508c2ecf20Sopenharmony_ci#endif /* _M68K_CHECKSUM_H */ 151