diff mbox

[v4,1/3] lib: add crc64 calculation routines

Message ID 20180718165545.1622-2-colyli@suse.de (mailing list archive)
State New, archived
Headers show

Commit Message

Coly Li July 18, 2018, 4:55 p.m. UTC
This patch adds the re-write crc64 calculation routines for Linux kernel.
The CRC64 polynomical arithmetic follows ECMA-182 specification, inspired
by CRC paper of Dr. Ross N. Williams
(see http://www.ross.net/crc/download/crc_v3.txt) and other public domain
implementations.

All the changes work in this way,
- When Linux kernel is built, host program lib/gen_crc64table.c will be
  compiled to lib/gen_crc64table and executed.
- The output of gen_crc64table execution is an array called as lookup
  table (a.k.a POLY 0x42f0e1eba9ea369) which contain 256 64-bit long
  numbers, this talbe is dumped into header file lib/crc64table.h.
- Then the header file is included by lib/crc64.c for normal 64bit crc
  calculation.
- Function declaration of the crc64 calculation routines is placed in
  include/linux/crc64.h

Currently bcache is the only user of crc64_be(), another potential user
is bcachefs which is on the way to be in mainline kernel. Therefore it
makes sense to move crc64 calculation into lib/crc64.c as public code.

Signed-off-by: Coly Li <colyli@suse.de>
Co-developed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Michael Lyle <mlyle@lyle.org>
Cc: Kent Overstreet <kent.overstreet@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Kate Stewart <kstewart@linuxfoundation.org>
Cc: Eric Biggers <ebiggers3@gmail.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Randy Dunlap <rdunlap@infradead.org>
---
Changelog:
v4: Only keep crc64_be() in lib/crc64.c, move rested bcache specific
    stuffs back to bcache code.
    Other fixes from the review comments of v3
v3: More fixes for review comments of v2
    By review comments from Eric Biggers, current functions naming with
    'le' is misleading. Remove 'le' from the crc function names, and use
    u64 to replace __le64 in parameters and return values.
v2: Fix reivew comments of v1
v1: Initial version.

 include/linux/crc64.h | 11 +++++++
 lib/.gitignore        |  2 ++
 lib/Kconfig           |  8 +++++
 lib/Makefile          | 11 +++++++
 lib/crc64.c           | 56 +++++++++++++++++++++++++++++++++++
 lib/gen_crc64table.c  | 68 +++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 156 insertions(+)
 create mode 100644 include/linux/crc64.h
 create mode 100644 lib/crc64.c
 create mode 100644 lib/gen_crc64table.c

Comments

Eric Biggers July 24, 2018, 4:26 a.m. UTC | #1
On Thu, Jul 19, 2018 at 12:55:43AM +0800, Coly Li wrote:
> This patch adds the re-write crc64 calculation routines for Linux kernel.
> The CRC64 polynomical arithmetic follows ECMA-182 specification, inspired

"polynomical" => "polynomial".  Same everywhere else in the patches.

> + * crc64table[256] is the lookup table of a table-driver 64-bit CRC

"table-driver" => "table-driven"

> + * calculation, which is generated by gen_crc64table.c in kernel build
> + * time. The polynomial of crc64 arithmetic is from ECMA-182 specification
> + * as well, which is defined as,
> + *
> + * x^64 + x^62 + x^57 + x^55 + x^54 + x^53 + x^52 + x^47 + x^46 + x^45 +
> + * x^40 + x^39 + x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 +
> + * x^24 + x^23 + x^22 + x^21 + x^19 + x^17 + x^13 + x^12 + x^10 + x^9 +
> + * x^7 + x^4 + x + 1
> + *
> + * Copyright 2018 SUSE Linux.
> + *   Author: Coly Li <colyli@suse.de>
> + */
> +
> +#include <linux/module.h>
> +#include <linux/types.h>
> +#include "crc64table.h"
> +
> +MODULE_DESCRIPTION("CRC64 calculations");
> +MODULE_LICENSE("GPL v2");
> +
> +/**
> + * crc64_be - Calculate bitwise big-endian ECMA-182 CRC64
> + * @crc: seed value for computation. 0 for a new CRC computing, or the
> + *	previous crc64 value if computing incrementally.

"0 or (u64)~0 for a new CRC calculation".  Both conventions are common in CRCs.
In fact the all-ones convention is generally considered better, because it
causes leading zeroes in the data to affect the checksum.

> + * @p: pointer to buffer over which CRC64 is run
> + * @len: length of buffer @p
> + */
> +u64 __pure crc64_be(u64 crc, const void *p, size_t len)
> +{
> +	size_t i, t;
> +
> +	const unsigned char *_p = p;
> +
> +	for (i = 0; i < len; i++) {
> +		t = ((crc >> 56) ^ (*_p++)) & 0xFF;
> +		crc = crc64table[t] ^ (crc << 8);
> +	}
> +
> +	return crc;
> +}
> +EXPORT_SYMBOL_GPL(crc64_be);
> diff --git a/lib/gen_crc64table.c b/lib/gen_crc64table.c
> new file mode 100644
> index 000000000000..8296b0c3ea30
> --- /dev/null
> +++ b/lib/gen_crc64table.c
> @@ -0,0 +1,68 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Generate lookup table for the talbe-driven CRC64 calculation.

"talbe-driven" => "table-driven"

> + *
> + * gen_crc64table is executed in kernel build time and generates
> + * lib/crc64table.h. This header is included by lib/crc64.c for
> + * the table-driver CRC64 calculation.

"table-driver" => "table-driven"

> + *
> + * See lib/crc64.c for more information about which specification
> + * and polynomical arithmetic that gen_crc64table.c follows to
> + * generate the lookup table.
> + *
> + * Copyright 2018 SUSE Linux.
> + *   Author: Coly Li <colyli@suse.de>
> + */
> +#include <inttypes.h>
> +#include <stdio.h>
> +
> +#include <linux/swab.h>
> +
> +#define CRC64_ECMA182_POLY 0x42F0E1EBA9EA3693ULL
> +
> +static int64_t crc64_table[256] = {0};

This really should be uint64_t, not int64_t.

> +
> +static void generate_crc64_table(void)
> +{
> +	uint64_t i, j, c, crc;
> +
> +	for (i = 0; i < 256; i++) {
> +		crc = 0;
> +		c = i << 56;
> +
> +		for (j = 0; j < 8; j++) {
> +			if ((crc ^ c) & 0x8000000000000000ULL)
> +				crc = (crc << 1) ^ CRC64_ECMA182_POLY;
> +			else
> +				crc <<= 1;
> +			c <<= 1;
> +		}
> +
> +		crc64_table[i] = crc;
> +	}
> +}
> +
> +static void print_crc64_table(void)
> +{
> +	int i;
> +
> +	printf("/* this file is generated - do not edit */\n\n");
> +	printf("#include <linux/types.h>\n");
> +	printf("#include <linux/cache.h>\n\n");
> +	printf("static const u64 ____cacheline_aligned crc64table[256] = {\n");
> +	for (i = 0; i < 256; i++) {
> +		printf("\t0x%016" PRIx64 "ULL", crc64_table[i]);
> +		if (i & 0x1)
> +			printf(",\n");
> +		else
> +			printf(", ");
> +	}
> +	printf("};\n");
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +	generate_crc64_table();
> +	print_crc64_table();
> +	return 0;
> +}
> -- 
> 2.17.1
> 

- Eric
Coly Li July 24, 2018, 4:29 p.m. UTC | #2
On 2018/7/24 12:26 PM, Eric Biggers wrote:
> On Thu, Jul 19, 2018 at 12:55:43AM +0800, Coly Li wrote:
>> This patch adds the re-write crc64 calculation routines for Linux kernel.
>> The CRC64 polynomical arithmetic follows ECMA-182 specification, inspired
> 
> "polynomical" => "polynomial".  Same everywhere else in the patches.
> 

Hi Eric,

Thanks for your careful review. I will post a fixing patch to fix all
these issues.

Coly Li

>> + * crc64table[256] is the lookup table of a table-driver 64-bit CRC
> 
> "table-driver" => "table-driven"
> 
>> + * calculation, which is generated by gen_crc64table.c in kernel build
>> + * time. The polynomial of crc64 arithmetic is from ECMA-182 specification
>> + * as well, which is defined as,
>> + *
>> + * x^64 + x^62 + x^57 + x^55 + x^54 + x^53 + x^52 + x^47 + x^46 + x^45 +
>> + * x^40 + x^39 + x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 +
>> + * x^24 + x^23 + x^22 + x^21 + x^19 + x^17 + x^13 + x^12 + x^10 + x^9 +
>> + * x^7 + x^4 + x + 1
>> + *
>> + * Copyright 2018 SUSE Linux.
>> + *   Author: Coly Li <colyli@suse.de>
>> + */
>> +
>> +#include <linux/module.h>
>> +#include <linux/types.h>
>> +#include "crc64table.h"
>> +
>> +MODULE_DESCRIPTION("CRC64 calculations");
>> +MODULE_LICENSE("GPL v2");
>> +
>> +/**
>> + * crc64_be - Calculate bitwise big-endian ECMA-182 CRC64
>> + * @crc: seed value for computation. 0 for a new CRC computing, or the
>> + *	previous crc64 value if computing incrementally.
> 
> "0 or (u64)~0 for a new CRC calculation".  Both conventions are common in CRCs.
> In fact the all-ones convention is generally considered better, because it
> causes leading zeroes in the data to affect the checksum.
> 
>> + * @p: pointer to buffer over which CRC64 is run
>> + * @len: length of buffer @p
>> + */
>> +u64 __pure crc64_be(u64 crc, const void *p, size_t len)
>> +{
>> +	size_t i, t;
>> +
>> +	const unsigned char *_p = p;
>> +
>> +	for (i = 0; i < len; i++) {
>> +		t = ((crc >> 56) ^ (*_p++)) & 0xFF;
>> +		crc = crc64table[t] ^ (crc << 8);
>> +	}
>> +
>> +	return crc;
>> +}
>> +EXPORT_SYMBOL_GPL(crc64_be);
>> diff --git a/lib/gen_crc64table.c b/lib/gen_crc64table.c
>> new file mode 100644
>> index 000000000000..8296b0c3ea30
>> --- /dev/null
>> +++ b/lib/gen_crc64table.c
>> @@ -0,0 +1,68 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Generate lookup table for the talbe-driven CRC64 calculation.
> 
> "talbe-driven" => "table-driven"
> 
>> + *
>> + * gen_crc64table is executed in kernel build time and generates
>> + * lib/crc64table.h. This header is included by lib/crc64.c for
>> + * the table-driver CRC64 calculation.
> 
> "table-driver" => "table-driven"
> 
>> + *
>> + * See lib/crc64.c for more information about which specification
>> + * and polynomical arithmetic that gen_crc64table.c follows to
>> + * generate the lookup table.
>> + *
>> + * Copyright 2018 SUSE Linux.
>> + *   Author: Coly Li <colyli@suse.de>
>> + */
>> +#include <inttypes.h>
>> +#include <stdio.h>
>> +
>> +#include <linux/swab.h>
>> +
>> +#define CRC64_ECMA182_POLY 0x42F0E1EBA9EA3693ULL
>> +
>> +static int64_t crc64_table[256] = {0};
> 
> This really should be uint64_t, not int64_t.
> 
>> +
>> +static void generate_crc64_table(void)
>> +{
>> +	uint64_t i, j, c, crc;
>> +
>> +	for (i = 0; i < 256; i++) {
>> +		crc = 0;
>> +		c = i << 56;
>> +
>> +		for (j = 0; j < 8; j++) {
>> +			if ((crc ^ c) & 0x8000000000000000ULL)
>> +				crc = (crc << 1) ^ CRC64_ECMA182_POLY;
>> +			else
>> +				crc <<= 1;
>> +			c <<= 1;
>> +		}
>> +
>> +		crc64_table[i] = crc;
>> +	}
>> +}
>> +
>> +static void print_crc64_table(void)
>> +{
>> +	int i;
>> +
>> +	printf("/* this file is generated - do not edit */\n\n");
>> +	printf("#include <linux/types.h>\n");
>> +	printf("#include <linux/cache.h>\n\n");
>> +	printf("static const u64 ____cacheline_aligned crc64table[256] = {\n");
>> +	for (i = 0; i < 256; i++) {
>> +		printf("\t0x%016" PRIx64 "ULL", crc64_table[i]);
>> +		if (i & 0x1)
>> +			printf(",\n");
>> +		else
>> +			printf(", ");
>> +	}
>> +	printf("};\n");
>> +}
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +	generate_crc64_table();
>> +	print_crc64_table();
>> +	return 0;
>> +}
>> -- 
>> 2.17.1
>>
> 
> - Eric
>
Andy Shevchenko July 24, 2018, 5:06 p.m. UTC | #3
On Wed, 2018-07-25 at 00:29 +0800, Coly Li wrote:
> On 2018/7/24 12:26 PM, Eric Biggers wrote:
> > On Thu, Jul 19, 2018 at 12:55:43AM +0800, Coly Li wrote:
> > > This patch adds the re-write crc64 calculation routines for Linux
> > > kernel.
> > > The CRC64 polynomical arithmetic follows ECMA-182 specification,
> > > inspired
> > 
> > "polynomical" => "polynomial".  Same everywhere else in the patches.
> > 
> 
> Hi Eric,
> 
> Thanks for your careful review. I will post a fixing patch to fix all
> these issues.

IIUC this series in Andrew's quilt. So, it's still possible to replace
it with better one, I suppose. Ask Andrew (at least I remember recent
case where he just replaced series by fixed one).
Coly Li July 25, 2018, 2:37 a.m. UTC | #4
On 2018/7/25 1:06 AM, Andy Shevchenko wrote:
> On Wed, 2018-07-25 at 00:29 +0800, Coly Li wrote:
>> On 2018/7/24 12:26 PM, Eric Biggers wrote:
>>> On Thu, Jul 19, 2018 at 12:55:43AM +0800, Coly Li wrote:
>>>> This patch adds the re-write crc64 calculation routines for Linux
>>>> kernel.
>>>> The CRC64 polynomical arithmetic follows ECMA-182 specification,
>>>> inspired
>>>
>>> "polynomical" => "polynomial".  Same everywhere else in the patches.
>>>
>>
>> Hi Eric,
>>
>> Thanks for your careful review. I will post a fixing patch to fix all
>> these issues.
> 
> IIUC this series in Andrew's quilt. So, it's still possible to replace
> it with better one, I suppose. Ask Andrew (at least I remember recent
> case where he just replaced series by fixed one).

Hi Andrew,

It seems there should be some fix/update for this series. I see current
series is in linux-next for now. If I want to add the fix, should I post
a new version of the series, or the incremental patches to fix current
series ?

Thanks in advance for your advice.

Coly Li
Andrew Morton July 25, 2018, 9:22 p.m. UTC | #5
On Wed, 25 Jul 2018 10:37:23 +0800 Coly Li <colyli@suse.de> wrote:

> > IIUC this series in Andrew's quilt. So, it's still possible to replace
> > it with better one, I suppose. Ask Andrew (at least I remember recent
> > case where he just replaced series by fixed one).
> 
> Hi Andrew,
> 
> It seems there should be some fix/update for this series. I see current
> series is in linux-next for now. If I want to add the fix, should I post
> a new version of the series, or the incremental patches to fix current
> series ?

mm...  it sounds like the changes will be large, so probably a new
series would be better at this early stage.  If the changes are small
then little fixup patches would be nicer to the people who have already
reviewed v1.
Coly Li July 26, 2018, 3:28 a.m. UTC | #6
On 2018/7/26 5:22 AM, Andrew Morton wrote:
> On Wed, 25 Jul 2018 10:37:23 +0800 Coly Li <colyli@suse.de> wrote:
> 
>>> IIUC this series in Andrew's quilt. So, it's still possible to replace
>>> it with better one, I suppose. Ask Andrew (at least I remember recent
>>> case where he just replaced series by fixed one).
>>
>> Hi Andrew,
>>
>> It seems there should be some fix/update for this series. I see current
>> series is in linux-next for now. If I want to add the fix, should I post
>> a new version of the series, or the incremental patches to fix current
>> series ?
> 
> mm...  it sounds like the changes will be large, so probably a new
> series would be better at this early stage.  If the changes are small
> then little fixup patches would be nicer to the people who have already
> reviewed v1.
> 

Yes, it is large (patch 3/3 will be removed). So I will post a new
series to replace current series.

Thanks for the hint.

Coly Li
diff mbox

Patch

diff --git a/include/linux/crc64.h b/include/linux/crc64.h
new file mode 100644
index 000000000000..1fc9f0710c10
--- /dev/null
+++ b/include/linux/crc64.h
@@ -0,0 +1,11 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * See lib/crc64.c for the related specification and polynomical arithmetic.
+ */
+#ifndef _LINUX_CRC64_H
+#define _LINUX_CRC64_H
+
+#include <linux/types.h>
+
+u64 __pure crc64_be(u64 crc, const void *p, size_t len);
+#endif /* _LINUX_CRC64_H */
diff --git a/lib/.gitignore b/lib/.gitignore
index 09aae85418ab..f2a39c9e5485 100644
--- a/lib/.gitignore
+++ b/lib/.gitignore
@@ -2,5 +2,7 @@ 
 # Generated files
 #
 gen_crc32table
+gen_crc64table
 crc32table.h
+crc64table.h
 oid_registry_data.c
diff --git a/lib/Kconfig b/lib/Kconfig
index 706836ec314d..9c10b9852563 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -170,6 +170,14 @@  config CRC32_BIT
 
 endchoice
 
+config CRC64
+	tristate "CRC64 functions"
+	help
+	  This option is provided for the case where no in-kernel-tree
+	  modules require CRC64 functions, but a module built outside
+	  the kernel tree does. Such modules that use library CRC64
+	  functions require M here.
+
 config CRC4
 	tristate "CRC4 functions"
 	help
diff --git a/lib/Makefile b/lib/Makefile
index 90dc5520b784..40c215181687 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -102,6 +102,7 @@  obj-$(CONFIG_CRC16)	+= crc16.o
 obj-$(CONFIG_CRC_T10DIF)+= crc-t10dif.o
 obj-$(CONFIG_CRC_ITU_T)	+= crc-itu-t.o
 obj-$(CONFIG_CRC32)	+= crc32.o
+obj-$(CONFIG_CRC64)     += crc64.o
 obj-$(CONFIG_CRC32_SELFTEST)	+= crc32test.o
 obj-$(CONFIG_CRC4)	+= crc4.o
 obj-$(CONFIG_CRC7)	+= crc7.o
@@ -215,7 +216,9 @@  obj-$(CONFIG_FONT_SUPPORT) += fonts/
 obj-$(CONFIG_PRIME_NUMBERS) += prime_numbers.o
 
 hostprogs-y	:= gen_crc32table
+hostprogs-y	+= gen_crc64table
 clean-files	:= crc32table.h
+clean-files	+= crc64table.h
 
 $(obj)/crc32.o: $(obj)/crc32table.h
 
@@ -225,6 +228,14 @@  quiet_cmd_crc32 = GEN     $@
 $(obj)/crc32table.h: $(obj)/gen_crc32table
 	$(call cmd,crc32)
 
+$(obj)/crc64.o: $(obj)/crc64table.h
+
+quiet_cmd_crc64 = GEN     $@
+      cmd_crc64 = $< > $@
+
+$(obj)/crc64table.h: $(obj)/gen_crc64table
+	$(call cmd,crc64)
+
 #
 # Build a fast OID lookip registry from include/linux/oid_registry.h
 #
diff --git a/lib/crc64.c b/lib/crc64.c
new file mode 100644
index 000000000000..d093298ba2c6
--- /dev/null
+++ b/lib/crc64.c
@@ -0,0 +1,56 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Normal 64-bit CRC calculation.
+ *
+ * This is a basic crc64 implementation following ECMA-182 specification,
+ * which can be found from,
+ * http://www.ecma-international.org/publications/standards/Ecma-182.htm
+ *
+ * Dr. Ross N. Williams has a great document to introduce the idea of CRC
+ * algorithm, here the CRC64 code is also inspired by the table-driven
+ * algorithm and detail example from this paper. This paper can be found
+ * from,
+ * http://www.ross.net/crc/download/crc_v3.txt
+ *
+ * crc64table[256] is the lookup table of a table-driver 64-bit CRC
+ * calculation, which is generated by gen_crc64table.c in kernel build
+ * time. The polynomial of crc64 arithmetic is from ECMA-182 specification
+ * as well, which is defined as,
+ *
+ * x^64 + x^62 + x^57 + x^55 + x^54 + x^53 + x^52 + x^47 + x^46 + x^45 +
+ * x^40 + x^39 + x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 +
+ * x^24 + x^23 + x^22 + x^21 + x^19 + x^17 + x^13 + x^12 + x^10 + x^9 +
+ * x^7 + x^4 + x + 1
+ *
+ * Copyright 2018 SUSE Linux.
+ *   Author: Coly Li <colyli@suse.de>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include "crc64table.h"
+
+MODULE_DESCRIPTION("CRC64 calculations");
+MODULE_LICENSE("GPL v2");
+
+/**
+ * crc64_be - Calculate bitwise big-endian ECMA-182 CRC64
+ * @crc: seed value for computation. 0 for a new CRC computing, or the
+ *	previous crc64 value if computing incrementally.
+ * @p: pointer to buffer over which CRC64 is run
+ * @len: length of buffer @p
+ */
+u64 __pure crc64_be(u64 crc, const void *p, size_t len)
+{
+	size_t i, t;
+
+	const unsigned char *_p = p;
+
+	for (i = 0; i < len; i++) {
+		t = ((crc >> 56) ^ (*_p++)) & 0xFF;
+		crc = crc64table[t] ^ (crc << 8);
+	}
+
+	return crc;
+}
+EXPORT_SYMBOL_GPL(crc64_be);
diff --git a/lib/gen_crc64table.c b/lib/gen_crc64table.c
new file mode 100644
index 000000000000..8296b0c3ea30
--- /dev/null
+++ b/lib/gen_crc64table.c
@@ -0,0 +1,68 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Generate lookup table for the talbe-driven CRC64 calculation.
+ *
+ * gen_crc64table is executed in kernel build time and generates
+ * lib/crc64table.h. This header is included by lib/crc64.c for
+ * the table-driver CRC64 calculation.
+ *
+ * See lib/crc64.c for more information about which specification
+ * and polynomical arithmetic that gen_crc64table.c follows to
+ * generate the lookup table.
+ *
+ * Copyright 2018 SUSE Linux.
+ *   Author: Coly Li <colyli@suse.de>
+ */
+#include <inttypes.h>
+#include <stdio.h>
+
+#include <linux/swab.h>
+
+#define CRC64_ECMA182_POLY 0x42F0E1EBA9EA3693ULL
+
+static int64_t crc64_table[256] = {0};
+
+static void generate_crc64_table(void)
+{
+	uint64_t i, j, c, crc;
+
+	for (i = 0; i < 256; i++) {
+		crc = 0;
+		c = i << 56;
+
+		for (j = 0; j < 8; j++) {
+			if ((crc ^ c) & 0x8000000000000000ULL)
+				crc = (crc << 1) ^ CRC64_ECMA182_POLY;
+			else
+				crc <<= 1;
+			c <<= 1;
+		}
+
+		crc64_table[i] = crc;
+	}
+}
+
+static void print_crc64_table(void)
+{
+	int i;
+
+	printf("/* this file is generated - do not edit */\n\n");
+	printf("#include <linux/types.h>\n");
+	printf("#include <linux/cache.h>\n\n");
+	printf("static const u64 ____cacheline_aligned crc64table[256] = {\n");
+	for (i = 0; i < 256; i++) {
+		printf("\t0x%016" PRIx64 "ULL", crc64_table[i]);
+		if (i & 0x1)
+			printf(",\n");
+		else
+			printf(", ");
+	}
+	printf("};\n");
+}
+
+int main(int argc, char *argv[])
+{
+	generate_crc64_table();
+	print_crc64_table();
+	return 0;
+}