1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2019 Mellanox Technologies. */
3 
4 /* Copyright (c) 2011-2015 Stephan Brumme. All rights reserved.
5  * Slicing-by-16 contributed by Bulat Ziganshin
6  *
7  * This software is provided 'as-is', without any express or implied warranty.
8  * In no event will the author be held liable for any damages arising from the
9  * of this software.
10  *
11  * Permission is granted to anyone to use this software for any purpose,
12  * including commercial applications, and to alter it and redistribute it
13  * freely, subject to the following restrictions:
14  *
15  * 1. The origin of this software must not be misrepresented; you must not
16  *    claim that you wrote the original software.
17  * 2. If you use this software in a product, an acknowledgment in the product
18  *    documentation would be appreciated but is not required.
19  * 3. Altered source versions must be plainly marked as such, and must not be
20  *    misrepresented as being the original software.
21  *
22  * Taken from http://create.stephan-brumme.com/crc32/ and adapted.
23  */
24 
25 #include "dr_types.h"
26 
27 #define DR_STE_CRC_POLY 0xEDB88320L
28 
29 static u32 dr_ste_crc_tab32[8][256];
30 
dr_crc32_calc_lookup_entry(u32 (* tbl)[256],u8 i,u8 j)31 static void dr_crc32_calc_lookup_entry(u32 (*tbl)[256], u8 i, u8 j)
32 {
33 	tbl[i][j] = (tbl[i - 1][j] >> 8) ^ tbl[0][tbl[i - 1][j] & 0xff];
34 }
35 
mlx5dr_crc32_init_table(void)36 void mlx5dr_crc32_init_table(void)
37 {
38 	u32 crc, i, j;
39 
40 	for (i = 0; i < 256; i++) {
41 		crc = i;
42 		for (j = 0; j < 8; j++) {
43 			if (crc & 0x00000001L)
44 				crc = (crc >> 1) ^ DR_STE_CRC_POLY;
45 			else
46 				crc = crc >> 1;
47 		}
48 		dr_ste_crc_tab32[0][i] = crc;
49 	}
50 
51 	/* Init CRC lookup tables according to crc_slice_8 algorithm */
52 	for (i = 0; i < 256; i++) {
53 		dr_crc32_calc_lookup_entry(dr_ste_crc_tab32, 1, i);
54 		dr_crc32_calc_lookup_entry(dr_ste_crc_tab32, 2, i);
55 		dr_crc32_calc_lookup_entry(dr_ste_crc_tab32, 3, i);
56 		dr_crc32_calc_lookup_entry(dr_ste_crc_tab32, 4, i);
57 		dr_crc32_calc_lookup_entry(dr_ste_crc_tab32, 5, i);
58 		dr_crc32_calc_lookup_entry(dr_ste_crc_tab32, 6, i);
59 		dr_crc32_calc_lookup_entry(dr_ste_crc_tab32, 7, i);
60 	}
61 }
62 
63 /* Compute CRC32 (Slicing-by-8 algorithm) */
mlx5dr_crc32_slice8_calc(const void * input_data,size_t length)64 u32 mlx5dr_crc32_slice8_calc(const void *input_data, size_t length)
65 {
66 	const u32 *curr = (const u32 *)input_data;
67 	const u8 *curr_char;
68 	u32 crc = 0, one, two;
69 
70 	if (!input_data)
71 		return 0;
72 
73 	/* Process eight bytes at once (Slicing-by-8) */
74 	while (length >= 8) {
75 		one = *curr++ ^ crc;
76 		two = *curr++;
77 
78 		crc = dr_ste_crc_tab32[0][(two >> 24) & 0xff]
79 			^ dr_ste_crc_tab32[1][(two >> 16) & 0xff]
80 			^ dr_ste_crc_tab32[2][(two >> 8) & 0xff]
81 			^ dr_ste_crc_tab32[3][two & 0xff]
82 			^ dr_ste_crc_tab32[4][(one >> 24) & 0xff]
83 			^ dr_ste_crc_tab32[5][(one >> 16) & 0xff]
84 			^ dr_ste_crc_tab32[6][(one >> 8) & 0xff]
85 			^ dr_ste_crc_tab32[7][one & 0xff];
86 
87 		length -= 8;
88 	}
89 
90 	curr_char = (const u8 *)curr;
91 	/* Remaining 1 to 7 bytes (standard algorithm) */
92 	while (length-- != 0)
93 		crc = (crc >> 8) ^ dr_ste_crc_tab32[0][(crc & 0xff)
94 			^ *curr_char++];
95 
96 	return ((crc >> 24) & 0xff) | ((crc << 8) & 0xff0000) |
97 		((crc >> 8) & 0xff00) | ((crc << 24) & 0xff000000);
98 }
99