| // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB |
| /* Copyright (c) 2019 Mellanox Technologies. */ |
| |
| /* Copyright (c) 2011-2015 Stephan Brumme. All rights reserved. |
| * Slicing-by-16 contributed by Bulat Ziganshin |
| * |
| * This software is provided 'as-is', without any express or implied warranty. |
| * In no event will the author be held liable for any damages arising from the |
| * of this software. |
| * |
| * Permission is granted to anyone to use this software for any purpose, |
| * including commercial applications, and to alter it and redistribute it |
| * freely, subject to the following restrictions: |
| * |
| * 1. The origin of this software must not be misrepresented; you must not |
| * claim that you wrote the original software. |
| * 2. If you use this software in a product, an acknowledgment in the product |
| * documentation would be appreciated but is not required. |
| * 3. Altered source versions must be plainly marked as such, and must not be |
| * misrepresented as being the original software. |
| * |
| * Taken from http://create.stephan-brumme.com/crc32/ and adapted. |
| */ |
| |
| #include "dr_types.h" |
| |
| #define DR_STE_CRC_POLY 0xEDB88320L |
| |
| static u32 dr_ste_crc_tab32[8][256]; |
| |
| static void dr_crc32_calc_lookup_entry(u32 (*tbl)[256], u8 i, u8 j) |
| { |
| tbl[i][j] = (tbl[i - 1][j] >> 8) ^ tbl[0][tbl[i - 1][j] & 0xff]; |
| } |
| |
| void mlx5dr_crc32_init_table(void) |
| { |
| u32 crc, i, j; |
| |
| for (i = 0; i < 256; i++) { |
| crc = i; |
| for (j = 0; j < 8; j++) { |
| if (crc & 0x00000001L) |
| crc = (crc >> 1) ^ DR_STE_CRC_POLY; |
| else |
| crc = crc >> 1; |
| } |
| dr_ste_crc_tab32[0][i] = crc; |
| } |
| |
| /* Init CRC lookup tables according to crc_slice_8 algorithm */ |
| for (i = 0; i < 256; i++) { |
| dr_crc32_calc_lookup_entry(dr_ste_crc_tab32, 1, i); |
| dr_crc32_calc_lookup_entry(dr_ste_crc_tab32, 2, i); |
| dr_crc32_calc_lookup_entry(dr_ste_crc_tab32, 3, i); |
| dr_crc32_calc_lookup_entry(dr_ste_crc_tab32, 4, i); |
| dr_crc32_calc_lookup_entry(dr_ste_crc_tab32, 5, i); |
| dr_crc32_calc_lookup_entry(dr_ste_crc_tab32, 6, i); |
| dr_crc32_calc_lookup_entry(dr_ste_crc_tab32, 7, i); |
| } |
| } |
| |
| /* Compute CRC32 (Slicing-by-8 algorithm) */ |
| u32 mlx5dr_crc32_slice8_calc(const void *input_data, size_t length) |
| { |
| const u32 *curr = (const u32 *)input_data; |
| const u8 *curr_char; |
| u32 crc = 0, one, two; |
| |
| if (!input_data) |
| return 0; |
| |
| /* Process eight bytes at once (Slicing-by-8) */ |
| while (length >= 8) { |
| one = *curr++ ^ crc; |
| two = *curr++; |
| |
| crc = dr_ste_crc_tab32[0][(two >> 24) & 0xff] |
| ^ dr_ste_crc_tab32[1][(two >> 16) & 0xff] |
| ^ dr_ste_crc_tab32[2][(two >> 8) & 0xff] |
| ^ dr_ste_crc_tab32[3][two & 0xff] |
| ^ dr_ste_crc_tab32[4][(one >> 24) & 0xff] |
| ^ dr_ste_crc_tab32[5][(one >> 16) & 0xff] |
| ^ dr_ste_crc_tab32[6][(one >> 8) & 0xff] |
| ^ dr_ste_crc_tab32[7][one & 0xff]; |
| |
| length -= 8; |
| } |
| |
| curr_char = (const u8 *)curr; |
| /* Remaining 1 to 7 bytes (standard algorithm) */ |
| while (length-- != 0) |
| crc = (crc >> 8) ^ dr_ste_crc_tab32[0][(crc & 0xff) |
| ^ *curr_char++]; |
| |
| return ((crc >> 24) & 0xff) | ((crc << 8) & 0xff0000) | |
| ((crc >> 8) & 0xff00) | ((crc << 24) & 0xff000000); |
| } |