10bcfca56SEric Biggers // SPDX-License-Identifier: GPL-2.0-only
20bcfca56SEric Biggers /*
30bcfca56SEric Biggers * T10 Data Integrity Field CRC16 calculation
40bcfca56SEric Biggers *
50bcfca56SEric Biggers * Copyright (c) 2007 Oracle Corporation. All rights reserved.
60bcfca56SEric Biggers * Written by Martin K. Petersen <martin.petersen@oracle.com>
70bcfca56SEric Biggers */
80bcfca56SEric Biggers
90bcfca56SEric Biggers #include <linux/crc-t10dif.h>
10*1a822ea5SEric Biggers #include <linux/export.h>
11*1a822ea5SEric Biggers #include <linux/module.h>
12*1a822ea5SEric Biggers #include <linux/types.h>
130bcfca56SEric Biggers
140bcfca56SEric Biggers /*
150bcfca56SEric Biggers * Table generated using the following polynomial:
160bcfca56SEric Biggers * x^16 + x^15 + x^11 + x^9 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
170bcfca56SEric Biggers * gt: 0x8bb7
180bcfca56SEric Biggers */
190bcfca56SEric Biggers static const u16 t10_dif_crc_table[256] = {
200bcfca56SEric Biggers 0x0000, 0x8BB7, 0x9CD9, 0x176E, 0xB205, 0x39B2, 0x2EDC, 0xA56B,
210bcfca56SEric Biggers 0xEFBD, 0x640A, 0x7364, 0xF8D3, 0x5DB8, 0xD60F, 0xC161, 0x4AD6,
220bcfca56SEric Biggers 0x54CD, 0xDF7A, 0xC814, 0x43A3, 0xE6C8, 0x6D7F, 0x7A11, 0xF1A6,
230bcfca56SEric Biggers 0xBB70, 0x30C7, 0x27A9, 0xAC1E, 0x0975, 0x82C2, 0x95AC, 0x1E1B,
240bcfca56SEric Biggers 0xA99A, 0x222D, 0x3543, 0xBEF4, 0x1B9F, 0x9028, 0x8746, 0x0CF1,
250bcfca56SEric Biggers 0x4627, 0xCD90, 0xDAFE, 0x5149, 0xF422, 0x7F95, 0x68FB, 0xE34C,
260bcfca56SEric Biggers 0xFD57, 0x76E0, 0x618E, 0xEA39, 0x4F52, 0xC4E5, 0xD38B, 0x583C,
270bcfca56SEric Biggers 0x12EA, 0x995D, 0x8E33, 0x0584, 0xA0EF, 0x2B58, 0x3C36, 0xB781,
280bcfca56SEric Biggers 0xD883, 0x5334, 0x445A, 0xCFED, 0x6A86, 0xE131, 0xF65F, 0x7DE8,
290bcfca56SEric Biggers 0x373E, 0xBC89, 0xABE7, 0x2050, 0x853B, 0x0E8C, 0x19E2, 0x9255,
300bcfca56SEric Biggers 0x8C4E, 0x07F9, 0x1097, 0x9B20, 0x3E4B, 0xB5FC, 0xA292, 0x2925,
310bcfca56SEric Biggers 0x63F3, 0xE844, 0xFF2A, 0x749D, 0xD1F6, 0x5A41, 0x4D2F, 0xC698,
320bcfca56SEric Biggers 0x7119, 0xFAAE, 0xEDC0, 0x6677, 0xC31C, 0x48AB, 0x5FC5, 0xD472,
330bcfca56SEric Biggers 0x9EA4, 0x1513, 0x027D, 0x89CA, 0x2CA1, 0xA716, 0xB078, 0x3BCF,
340bcfca56SEric Biggers 0x25D4, 0xAE63, 0xB90D, 0x32BA, 0x97D1, 0x1C66, 0x0B08, 0x80BF,
350bcfca56SEric Biggers 0xCA69, 0x41DE, 0x56B0, 0xDD07, 0x786C, 0xF3DB, 0xE4B5, 0x6F02,
360bcfca56SEric Biggers 0x3AB1, 0xB106, 0xA668, 0x2DDF, 0x88B4, 0x0303, 0x146D, 0x9FDA,
370bcfca56SEric Biggers 0xD50C, 0x5EBB, 0x49D5, 0xC262, 0x6709, 0xECBE, 0xFBD0, 0x7067,
380bcfca56SEric Biggers 0x6E7C, 0xE5CB, 0xF2A5, 0x7912, 0xDC79, 0x57CE, 0x40A0, 0xCB17,
390bcfca56SEric Biggers 0x81C1, 0x0A76, 0x1D18, 0x96AF, 0x33C4, 0xB873, 0xAF1D, 0x24AA,
400bcfca56SEric Biggers 0x932B, 0x189C, 0x0FF2, 0x8445, 0x212E, 0xAA99, 0xBDF7, 0x3640,
410bcfca56SEric Biggers 0x7C96, 0xF721, 0xE04F, 0x6BF8, 0xCE93, 0x4524, 0x524A, 0xD9FD,
420bcfca56SEric Biggers 0xC7E6, 0x4C51, 0x5B3F, 0xD088, 0x75E3, 0xFE54, 0xE93A, 0x628D,
430bcfca56SEric Biggers 0x285B, 0xA3EC, 0xB482, 0x3F35, 0x9A5E, 0x11E9, 0x0687, 0x8D30,
440bcfca56SEric Biggers 0xE232, 0x6985, 0x7EEB, 0xF55C, 0x5037, 0xDB80, 0xCCEE, 0x4759,
450bcfca56SEric Biggers 0x0D8F, 0x8638, 0x9156, 0x1AE1, 0xBF8A, 0x343D, 0x2353, 0xA8E4,
460bcfca56SEric Biggers 0xB6FF, 0x3D48, 0x2A26, 0xA191, 0x04FA, 0x8F4D, 0x9823, 0x1394,
470bcfca56SEric Biggers 0x5942, 0xD2F5, 0xC59B, 0x4E2C, 0xEB47, 0x60F0, 0x779E, 0xFC29,
480bcfca56SEric Biggers 0x4BA8, 0xC01F, 0xD771, 0x5CC6, 0xF9AD, 0x721A, 0x6574, 0xEEC3,
490bcfca56SEric Biggers 0xA415, 0x2FA2, 0x38CC, 0xB37B, 0x1610, 0x9DA7, 0x8AC9, 0x017E,
500bcfca56SEric Biggers 0x1F65, 0x94D2, 0x83BC, 0x080B, 0xAD60, 0x26D7, 0x31B9, 0xBA0E,
510bcfca56SEric Biggers 0xF0D8, 0x7B6F, 0x6C01, 0xE7B6, 0x42DD, 0xC96A, 0xDE04, 0x55B3
520bcfca56SEric Biggers };
530bcfca56SEric Biggers
540bcfca56SEric Biggers static inline u16 __maybe_unused
crc_t10dif_generic(u16 crc,const u8 * p,size_t len)550bcfca56SEric Biggers crc_t10dif_generic(u16 crc, const u8 *p, size_t len)
560bcfca56SEric Biggers {
570bcfca56SEric Biggers while (len--)
580bcfca56SEric Biggers crc = (crc << 8) ^ t10_dif_crc_table[(crc >> 8) ^ *p++];
590bcfca56SEric Biggers return crc;
600bcfca56SEric Biggers }
610bcfca56SEric Biggers
620bcfca56SEric Biggers #ifdef CONFIG_CRC_T10DIF_ARCH
630bcfca56SEric Biggers #include "crc-t10dif.h" /* $(SRCARCH)/crc-t10dif.h */
640bcfca56SEric Biggers #else
650bcfca56SEric Biggers #define crc_t10dif_arch crc_t10dif_generic
660bcfca56SEric Biggers #endif
670bcfca56SEric Biggers
crc_t10dif_update(u16 crc,const u8 * p,size_t len)680bcfca56SEric Biggers u16 crc_t10dif_update(u16 crc, const u8 *p, size_t len)
690bcfca56SEric Biggers {
700bcfca56SEric Biggers return crc_t10dif_arch(crc, p, len);
710bcfca56SEric Biggers }
720bcfca56SEric Biggers EXPORT_SYMBOL(crc_t10dif_update);
730bcfca56SEric Biggers
740bcfca56SEric Biggers #ifdef crc_t10dif_mod_init_arch
crc_t10dif_mod_init(void)750bcfca56SEric Biggers static int __init crc_t10dif_mod_init(void)
760bcfca56SEric Biggers {
770bcfca56SEric Biggers crc_t10dif_mod_init_arch();
780bcfca56SEric Biggers return 0;
790bcfca56SEric Biggers }
800bcfca56SEric Biggers subsys_initcall(crc_t10dif_mod_init);
810bcfca56SEric Biggers
crc_t10dif_mod_exit(void)820bcfca56SEric Biggers static void __exit crc_t10dif_mod_exit(void)
830bcfca56SEric Biggers {
840bcfca56SEric Biggers }
850bcfca56SEric Biggers module_exit(crc_t10dif_mod_exit);
860bcfca56SEric Biggers #endif
870bcfca56SEric Biggers
880bcfca56SEric Biggers MODULE_DESCRIPTION("CRC-T10DIF library functions");
890bcfca56SEric Biggers MODULE_LICENSE("GPL");
90