linux-hexagon.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Richard Kuo <rkuo@codeaurora.org>
To: linux-kernel@vger.kernel.org, linux-hexagon@vger.kernel.org
Subject: [patch 09/36] Hexagon: Add checksum functions
Date: Wed, 17 Aug 2011 11:35:06 -0500	[thread overview]
Message-ID: <20110817163520.702483311@codeaurora.org> (raw)
In-Reply-To: 20110817163457.878854582@codeaurora.org

[-- Attachment #1: checksum.diff --]
[-- Type: text/plain, Size: 12572 bytes --]

Signed-off-by: Richard Kuo <rkuo@codeaurora.org>

---
 arch/hexagon/include/asm/checksum.h   |   91 +++++++++++
 arch/hexagon/include/asm/intrinsics.h |   26 +++
 arch/hexagon/lib/checksum.c           |  269 ++++++++++++++++++++++++++++++++++
 3 files changed, 386 insertions(+)

Index: linux-hexagon-kernel/arch/hexagon/include/asm/checksum.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-hexagon-kernel/arch/hexagon/include/asm/checksum.h	2011-07-20 15:19:38.005153124 -0500
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_CHECKSUM_H
+#define _ASM_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
+ */
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+					int len, __wsum sum);
+
+/*
+ * the same as csum_partial_copy, but copies from user space.
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+					int len, __wsum sum, int *csum_err);
+
+
+/*
+ *	This is a version of ip_compute_csum() optimized for IP headers,
+ *	which always checksum on 4 octet boundaries.
+ *
+ */
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
+
+/*
+ *	Fold a partial checksum
+ */
+static inline __sum16 csum_fold(__wsum csum)
+{
+	u32 sum = (__force u32)csum;
+	sum = (sum & 0xffff) + (sum >> 16);
+	sum = (sum & 0xffff) + (sum >> 16);
+	return (__force __sum16)~sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+__wsum csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
+	unsigned short len, unsigned short proto, __wsum sum);
+__sum16 csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
+	unsigned short len, unsigned short proto, __wsum sum);
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+__sum16 ip_compute_csum(const void *buff, int len);
+
+#endif
Index: linux-hexagon-kernel/arch/hexagon/include/asm/intrinsics.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-hexagon-kernel/arch/hexagon/include/asm/intrinsics.h	2011-07-20 15:19:38.005153124 -0500
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_INTRINSICS_H
+#define _ASM_HEXAGON_INTRINSICS_H
+
+#define HEXAGON_P_vrmpyhacc_PP	__builtin_HEXAGON_M2_vrmac_s0
+#define HEXAGON_P_vrmpyh_PP	__builtin_HEXAGON_M2_vrmpy_s0
+#define HEXAGON_R_cl0_R		__builtin_HEXAGON_S2_cl0
+
+#endif
Index: linux-hexagon-kernel/arch/hexagon/lib/checksum.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-hexagon-kernel/arch/hexagon/lib/checksum.c	2011-07-20 15:19:38.005153124 -0500
@@ -0,0 +1,269 @@
+/*
+ * Checksum functions for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*  This was derived from arch/alpha/lib/checksum.c  */
+
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/byteorder.h>
+#include <net/checksum.h>
+#include <linux/uaccess.h>
+#include <asm/intrinsics.h>
+
+
+/*  Vector value operations  */
+#define SIGN(x, y)	((0x8000ULL*x)<<y)
+#define CARRY(x, y)	((0x0002ULL*x)<<y)
+#define SELECT(x, y)	((0x0001ULL*x)<<y)
+
+#define VR_NEGATE(a, b, c, d)	(SIGN(a, 48) + SIGN(b, 32) + SIGN(c, 16) \
+	+ SIGN(d, 0))
+#define VR_CARRY(a, b, c, d)	(CARRY(a, 48) + CARRY(b, 32) + CARRY(c, 16) \
+	+ CARRY(d, 0))
+#define VR_SELECT(a, b, c, d)	(SELECT(a, 48) + SELECT(b, 32) + SELECT(c, 16) \
+	+ SELECT(d, 0))
+
+
+/* optimized HEXAGON V3 intrinsic version */
+static inline unsigned short from64to16(u64 x)
+{
+	u64 sum;
+
+	sum = HEXAGON_P_vrmpyh_PP(x^VR_NEGATE(1, 1, 1, 1),
+			     VR_SELECT(1, 1, 1, 1));
+	sum += VR_CARRY(0, 0, 1, 0);
+	sum = HEXAGON_P_vrmpyh_PP(sum, VR_SELECT(0, 0, 1, 1));
+
+	return 0xFFFF & sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented.
+ */
+__sum16 csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
+			  unsigned short len, unsigned short proto,
+			  __wsum sum)
+{
+	return (__force __sum16)~from64to16(
+		(__force u64)saddr + (__force u64)daddr +
+		(__force u64)sum + ((len + proto) << 8));
+}
+
+__wsum csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
+			  unsigned short len, unsigned short proto,
+			  __wsum sum)
+{
+	u64 result;
+
+	result = (__force u64)saddr + (__force u64)daddr +
+		 (__force u64)sum + ((len + proto) << 8);
+
+	/* Fold down to 32-bits so we don't lose in the typedef-less
+	   network stack.  */
+	/* 64 to 33 */
+	result = (result & 0xffffffffUL) + (result >> 32);
+	/* 33 to 32 */
+	result = (result & 0xffffffffUL) + (result >> 32);
+	return (__force __wsum)result;
+}
+EXPORT_SYMBOL(csum_tcpudp_nofold);
+
+/*
+ * Do a 64-bit checksum on an arbitrary memory area..
+ *
+ * This isn't a great routine, but it's not _horrible_ either. The
+ * inner loop could be unrolled a bit further, and there are better
+ * ways to do the carry, but this is reasonable.
+ */
+
+/* optimized HEXAGON intrinsic version, with over read fixed */
+static inline u64 do_csum(const void *voidptr, int len)
+{
+	u64 sum0, sum1, x0, x1, *ptr8_o, *ptr8_e, *ptr8;
+	int i, start, mid, end, mask;
+	const char *ptr = voidptr;
+	unsigned short *ptr2;
+	unsigned int *ptr4;
+
+	if (len <= 0)
+		return 0;
+
+	start = 0xF & (16-(((int) ptr) & 0xF)) ;
+	mask  = 0x7fffffffUL >> HEXAGON_R_cl0_R(len);
+	start = start & mask ;
+
+	mid = len - start;
+	end = mid & 0xF;
+	mid = mid>>4;
+	sum0 = mid << 18;
+	sum1 = 0;
+
+	if (start & 1)
+		sum0 += (u64) (ptr[0] << 8);
+	ptr2 = (unsigned short *) &ptr[start & 1];
+	if (start & 2)
+		sum1 += (u64) ptr2[0];
+	ptr4 = (unsigned int *) &ptr[start & 3];
+	if (start & 4) {
+		sum0 = HEXAGON_P_vrmpyhacc_PP(sum0,
+			VR_NEGATE(0, 0, 1, 1)^((u64)ptr4[0]),
+			VR_SELECT(0, 0, 1, 1));
+		sum0 += VR_SELECT(0, 0, 1, 0);
+	}
+	ptr8 = (u64 *) &ptr[start & 7];
+	if (start & 8) {
+		sum1 = HEXAGON_P_vrmpyhacc_PP(sum1,
+			VR_NEGATE(1, 1, 1, 1)^(ptr8[0]),
+			VR_SELECT(1, 1, 1, 1));
+		sum1 += VR_CARRY(0, 0, 1, 0);
+	}
+	ptr8_o = (u64 *) (ptr + start);
+	ptr8_e = (u64 *) (ptr + start + 8);
+
+	if (mid) {
+		x0 = *ptr8_e; ptr8_e += 2;
+		x1 = *ptr8_o; ptr8_o += 2;
+		if (mid > 1)
+			for (i = 0; i < mid-1; i++) {
+				sum0 = HEXAGON_P_vrmpyhacc_PP(sum0,
+					x0^VR_NEGATE(1, 1, 1, 1),
+					VR_SELECT(1, 1, 1, 1));
+				sum1 = HEXAGON_P_vrmpyhacc_PP(sum1,
+					x1^VR_NEGATE(1, 1, 1, 1),
+					VR_SELECT(1, 1, 1, 1));
+				x0 = *ptr8_e; ptr8_e += 2;
+				x1 = *ptr8_o; ptr8_o += 2;
+			}
+		sum0 = HEXAGON_P_vrmpyhacc_PP(sum0, x0^VR_NEGATE(1, 1, 1, 1),
+			VR_SELECT(1, 1, 1, 1));
+		sum1 = HEXAGON_P_vrmpyhacc_PP(sum1, x1^VR_NEGATE(1, 1, 1, 1),
+			VR_SELECT(1, 1, 1, 1));
+	}
+
+	ptr4 = (unsigned int *) &ptr[start + (mid * 16) + (end & 8)];
+	if (end & 4) {
+		sum1 = HEXAGON_P_vrmpyhacc_PP(sum1,
+			VR_NEGATE(0, 0, 1, 1)^((u64)ptr4[0]),
+			VR_SELECT(0, 0, 1, 1));
+		sum1 += VR_SELECT(0, 0, 1, 0);
+	}
+	ptr2 = (unsigned short *) &ptr[start + (mid * 16) + (end & 12)];
+	if (end & 2)
+		sum0 += (u64) ptr2[0];
+
+	if (end & 1)
+		sum1 += (u64) ptr[start + (mid * 16) + (end & 14)];
+
+	ptr8 = (u64 *) &ptr[start + (mid * 16)];
+	if (end & 8) {
+		sum0 = HEXAGON_P_vrmpyhacc_PP(sum0,
+			VR_NEGATE(1, 1, 1, 1)^(ptr8[0]),
+			VR_SELECT(1, 1, 1, 1));
+		sum0 += VR_CARRY(0, 0, 1, 0);
+	}
+	sum0 = HEXAGON_P_vrmpyh_PP((sum0+sum1)^VR_NEGATE(0, 0, 0, 1),
+		VR_SELECT(0, 0, 1, 1));
+	sum0 += VR_NEGATE(0, 0, 0, 1);
+	sum0 = HEXAGON_P_vrmpyh_PP(sum0, VR_SELECT(0, 0, 1, 1));
+
+	if (start & 1)
+		sum0 = (sum0 << 8) | (0xFF & (sum0 >> 8));
+
+	return 0xFFFF & sum0;
+}
+
+/*
+ *	This is a version of ip_compute_csum() optimized for IP headers,
+ *	which always checksum on 4 octet boundaries.
+ */
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+	return (__force __sum16) ~do_csum(iph, ihl*4);
+}
+
+/*
+ * 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)
+{
+	u64 result = do_csum(buff, len);
+
+	/* add in old sum, and carry.. */
+	result += (__force u32)sum;
+	/* 32+c bits -> 32 bits */
+	result = (result & 0xffffffffUL) + (result >> 32);
+	return (__force __wsum)result;
+}
+EXPORT_SYMBOL(csum_partial);
+
+/*
+ * This routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+__sum16 ip_compute_csum(const void *buff, int len)
+{
+	return (__force __sum16) ~from64to16(do_csum(buff, len));
+}
+
+/*
+ * Copy from fs while checksumming, otherwise like csum_partial
+ */
+__wsum
+csum_partial_copy_from_user(const void __user *src, void *dst,
+			    int len, __wsum sum, int *csum_err)
+{
+	int rem;
+
+	if (csum_err)
+		*csum_err = 0;
+
+	rem = copy_from_user(dst, src, len);
+	if (rem != 0) {
+		if (csum_err)
+			*csum_err = -EFAULT;
+		memset(dst + len - rem, 0, rem);
+		len = rem;
+	}
+
+	return csum_partial(dst, len, sum);
+}
+EXPORT_SYMBOL(csum_partial_copy_from_user);
+
+/*
+ * copy from ds while checksumming, otherwise like csum_partial
+ */
+__wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
+{
+	memcpy(dst, src, len);
+	return csum_partial(dst, len, sum);
+}

Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


  parent reply	other threads:[~2011-08-17 16:35 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-08-17 16:34 [patch 00/36] Hexagon: Add support for Qualcomm Hexagon architecture Richard Kuo
2011-08-17 16:34 ` [patch 01/36] Hexagon: Add generic headers Richard Kuo
2011-08-17 19:19   ` Arnd Bergmann
2011-08-17 16:34 ` [patch 02/36] Hexagon: Core arch-specific header files Richard Kuo
2011-08-17 19:19   ` Arnd Bergmann
2011-08-17 16:35 ` [patch 03/36] Hexagon: Add bitops support Richard Kuo
2011-08-17 19:19   ` Arnd Bergmann
2011-08-26 20:34   ` Pavel Machek
2011-08-30 21:14     ` ARM assembly syntax (was Re: [patch 03/36] Hexagon: Add bitops support) Linas Vepstas (Code Aurora)
2011-09-02 16:53       ` Pavel Machek
2011-08-17 16:35 ` [patch 04/36] Hexagon: Add atomic ops support Richard Kuo
2011-08-17 19:20   ` Arnd Bergmann
2011-08-17 16:35 ` [patch 05/36] Hexagon: Add syscalls Richard Kuo
2011-08-17 19:29   ` Arnd Bergmann
2011-08-17 20:12   ` Jonas Bonn
2011-08-17 16:35 ` [patch 06/36] Hexagon: Add processor and system headers Richard Kuo
2011-08-17 19:31   ` Arnd Bergmann
2011-08-17 16:35 ` [patch 07/36] Hexagon: Add threadinfo Richard Kuo
2011-08-17 19:37   ` Arnd Bergmann
2011-08-17 16:35 ` [patch 08/36] Hexagon: Add delay functions Richard Kuo
2011-08-17 19:38   ` Arnd Bergmann
2011-08-17 16:35 ` Richard Kuo [this message]
2011-08-17 19:40   ` [patch 09/36] Hexagon: Add checksum functions Arnd Bergmann
2011-08-17 16:35 ` [patch 10/36] Hexagon: Add memcpy and memset accelerated functions Richard Kuo
2011-08-17 16:35 ` [patch 11/36] Hexagon: Add hypervisor interface Richard Kuo
2011-08-17 16:35 ` [patch 12/36] Hexagon: Export ksyms defined in assembly files Richard Kuo
2011-08-17 16:35 ` [patch 13/36] Hexagon: Support dynamic module loading Richard Kuo
2011-08-17 19:41   ` Arnd Bergmann
2011-08-17 16:35 ` [patch 14/36] Hexagon: Add signal functions Richard Kuo
2012-02-11 23:27   ` hexagon: signal handling bugs Al Viro
2012-02-15 17:45     ` Richard Kuo
2012-02-15 18:18     ` Linas Vepstas
2011-08-17 16:35 ` [patch 15/36] Hexagon: Add init_task and process functions Richard Kuo
2011-08-17 19:45   ` Arnd Bergmann
2011-08-17 16:35 ` [patch 16/36] Hexagon: Add startup code Richard Kuo
2011-08-17 16:35 ` [patch 17/36] Hexagon: Add interrupts Richard Kuo
2011-08-17 16:35 ` [patch 18/36] Hexagon: Add time and timer functions Richard Kuo
2011-08-17 16:35 ` [patch 19/36] Hexagon: Add ptrace support Richard Kuo
2011-08-17 19:47   ` Arnd Bergmann
2011-08-17 16:35 ` [patch 20/36] Hexagon: Provide basic debugging and system trap support Richard Kuo
2011-08-17 16:35 ` [patch 21/36] Hexagon: Add SMP support Richard Kuo
2011-08-17 16:35 ` [patch 22/36] Hexagon: Add locking types and functions Richard Kuo
2011-08-17 16:35 ` [patch 23/36] Hexagon: Add user access functions Richard Kuo
2011-08-17 16:35 ` [patch 24/36] Hexagon: Provide basic implementation and/or stubs for I/O routines Richard Kuo
2011-08-17 19:55   ` Arnd Bergmann
2011-08-17 16:35 ` [patch 25/36] Hexagon: Implement basic cache-flush support Richard Kuo
2011-08-17 16:35 ` [patch 26/36] Hexagon: Implement basic TLB management routines for Hexagon Richard Kuo
2011-08-17 16:35 ` [patch 27/36] Hexagon: Provide DMA implementation Richard Kuo
2011-08-17 20:01   ` Arnd Bergmann
2011-08-17 16:35 ` [patch 28/36] Hexagon: Add ioremap support Richard Kuo
2011-08-17 16:35 ` [patch 29/36] Hexagon: Add page table header files & etc Richard Kuo
2011-08-17 16:35 ` [patch 30/36] Hexagon: Add page-fault support Richard Kuo
2011-08-17 16:35 ` [patch 31/36] Hexagon: kgdb support files Richard Kuo
2011-08-17 16:35 ` [patch 32/36] Hexagon: Comet platform support Richard Kuo
2011-08-17 20:07   ` Arnd Bergmann
2011-08-17 23:45     ` Linas Vepstas
2011-08-17 20:08   ` David Brown
2011-08-17 16:35 ` [patch 33/36] Hexagon: Platform-generic support Richard Kuo
2011-08-17 20:20   ` Arnd Bergmann
2011-08-17 16:35 ` [patch 34/36] Hexagon: Add configuration and makefiles for the Hexagon architecture Richard Kuo
2011-08-17 20:27   ` Arnd Bergmann
2011-08-17 16:35 ` [patch 35/36] Hexagon: Add basic stacktrace functionality for " Richard Kuo
2011-08-17 16:35 ` [patch 36/36] Hexagon: Add self to MAINTAINERS Richard Kuo
2011-08-17 19:00 ` [patch 00/36] Hexagon: Add support for Qualcomm Hexagon architecture Zan Lynx
2011-08-17 19:42   ` Richard Kuo
2011-08-17 20:34 ` Arnd Bergmann
2011-08-18  0:31   ` Richard Kuo
2011-08-31  5:48 ` Avi Kivity

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20110817163520.702483311@codeaurora.org \
    --to=rkuo@codeaurora.org \
    --cc=linux-hexagon@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).