18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Generic Reed Solomon encoder / decoder library 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Reed Solomon code lifted from reed solomon library written by Phil Karn 88c2ecf20Sopenharmony_ci * Copyright 2002 Phil Karn, KA9Q 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Description: 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * The generic Reed Solomon library provides runtime configurable 138c2ecf20Sopenharmony_ci * encoding / decoding of RS codes. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * Each user must call init_rs to get a pointer to a rs_control structure 168c2ecf20Sopenharmony_ci * for the given rs parameters. The control struct is unique per instance. 178c2ecf20Sopenharmony_ci * It points to a codec which can be shared by multiple control structures. 188c2ecf20Sopenharmony_ci * If a codec is newly allocated then the polynomial arrays for fast 198c2ecf20Sopenharmony_ci * encoding / decoding are built. This can take some time so make sure not 208c2ecf20Sopenharmony_ci * to call this function from a time critical path. Usually a module / 218c2ecf20Sopenharmony_ci * driver should initialize the necessary rs_control structure on module / 228c2ecf20Sopenharmony_ci * driver init and release it on exit. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * The encoding puts the calculated syndrome into a given syndrome buffer. 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * The decoding is a two step process. The first step calculates the 278c2ecf20Sopenharmony_ci * syndrome over the received (data + syndrome) and calls the second stage, 288c2ecf20Sopenharmony_ci * which does the decoding / error correction itself. Many hw encoders 298c2ecf20Sopenharmony_ci * provide a syndrome calculation over the received data + syndrome and can 308c2ecf20Sopenharmony_ci * call the second stage directly. 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci#include <linux/errno.h> 338c2ecf20Sopenharmony_ci#include <linux/kernel.h> 348c2ecf20Sopenharmony_ci#include <linux/init.h> 358c2ecf20Sopenharmony_ci#include <linux/module.h> 368c2ecf20Sopenharmony_ci#include <linux/rslib.h> 378c2ecf20Sopenharmony_ci#include <linux/slab.h> 388c2ecf20Sopenharmony_ci#include <linux/mutex.h> 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cienum { 418c2ecf20Sopenharmony_ci RS_DECODE_LAMBDA, 428c2ecf20Sopenharmony_ci RS_DECODE_SYN, 438c2ecf20Sopenharmony_ci RS_DECODE_B, 448c2ecf20Sopenharmony_ci RS_DECODE_T, 458c2ecf20Sopenharmony_ci RS_DECODE_OMEGA, 468c2ecf20Sopenharmony_ci RS_DECODE_ROOT, 478c2ecf20Sopenharmony_ci RS_DECODE_REG, 488c2ecf20Sopenharmony_ci RS_DECODE_LOC, 498c2ecf20Sopenharmony_ci RS_DECODE_NUM_BUFFERS 508c2ecf20Sopenharmony_ci}; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/* This list holds all currently allocated rs codec structures */ 538c2ecf20Sopenharmony_cistatic LIST_HEAD(codec_list); 548c2ecf20Sopenharmony_ci/* Protection for the list */ 558c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(rslistlock); 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/** 588c2ecf20Sopenharmony_ci * codec_init - Initialize a Reed-Solomon codec 598c2ecf20Sopenharmony_ci * @symsize: symbol size, bits (1-8) 608c2ecf20Sopenharmony_ci * @gfpoly: Field generator polynomial coefficients 618c2ecf20Sopenharmony_ci * @gffunc: Field generator function 628c2ecf20Sopenharmony_ci * @fcr: first root of RS code generator polynomial, index form 638c2ecf20Sopenharmony_ci * @prim: primitive element to generate polynomial roots 648c2ecf20Sopenharmony_ci * @nroots: RS code generator polynomial degree (number of roots) 658c2ecf20Sopenharmony_ci * @gfp: GFP_ flags for allocations 668c2ecf20Sopenharmony_ci * 678c2ecf20Sopenharmony_ci * Allocate a codec structure and the polynom arrays for faster 688c2ecf20Sopenharmony_ci * en/decoding. Fill the arrays according to the given parameters. 698c2ecf20Sopenharmony_ci */ 708c2ecf20Sopenharmony_cistatic struct rs_codec *codec_init(int symsize, int gfpoly, int (*gffunc)(int), 718c2ecf20Sopenharmony_ci int fcr, int prim, int nroots, gfp_t gfp) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci int i, j, sr, root, iprim; 748c2ecf20Sopenharmony_ci struct rs_codec *rs; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci rs = kzalloc(sizeof(*rs), gfp); 778c2ecf20Sopenharmony_ci if (!rs) 788c2ecf20Sopenharmony_ci return NULL; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&rs->list); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci rs->mm = symsize; 838c2ecf20Sopenharmony_ci rs->nn = (1 << symsize) - 1; 848c2ecf20Sopenharmony_ci rs->fcr = fcr; 858c2ecf20Sopenharmony_ci rs->prim = prim; 868c2ecf20Sopenharmony_ci rs->nroots = nroots; 878c2ecf20Sopenharmony_ci rs->gfpoly = gfpoly; 888c2ecf20Sopenharmony_ci rs->gffunc = gffunc; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci /* Allocate the arrays */ 918c2ecf20Sopenharmony_ci rs->alpha_to = kmalloc_array(rs->nn + 1, sizeof(uint16_t), gfp); 928c2ecf20Sopenharmony_ci if (rs->alpha_to == NULL) 938c2ecf20Sopenharmony_ci goto err; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci rs->index_of = kmalloc_array(rs->nn + 1, sizeof(uint16_t), gfp); 968c2ecf20Sopenharmony_ci if (rs->index_of == NULL) 978c2ecf20Sopenharmony_ci goto err; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci rs->genpoly = kmalloc_array(rs->nroots + 1, sizeof(uint16_t), gfp); 1008c2ecf20Sopenharmony_ci if(rs->genpoly == NULL) 1018c2ecf20Sopenharmony_ci goto err; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci /* Generate Galois field lookup tables */ 1048c2ecf20Sopenharmony_ci rs->index_of[0] = rs->nn; /* log(zero) = -inf */ 1058c2ecf20Sopenharmony_ci rs->alpha_to[rs->nn] = 0; /* alpha**-inf = 0 */ 1068c2ecf20Sopenharmony_ci if (gfpoly) { 1078c2ecf20Sopenharmony_ci sr = 1; 1088c2ecf20Sopenharmony_ci for (i = 0; i < rs->nn; i++) { 1098c2ecf20Sopenharmony_ci rs->index_of[sr] = i; 1108c2ecf20Sopenharmony_ci rs->alpha_to[i] = sr; 1118c2ecf20Sopenharmony_ci sr <<= 1; 1128c2ecf20Sopenharmony_ci if (sr & (1 << symsize)) 1138c2ecf20Sopenharmony_ci sr ^= gfpoly; 1148c2ecf20Sopenharmony_ci sr &= rs->nn; 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci } else { 1178c2ecf20Sopenharmony_ci sr = gffunc(0); 1188c2ecf20Sopenharmony_ci for (i = 0; i < rs->nn; i++) { 1198c2ecf20Sopenharmony_ci rs->index_of[sr] = i; 1208c2ecf20Sopenharmony_ci rs->alpha_to[i] = sr; 1218c2ecf20Sopenharmony_ci sr = gffunc(sr); 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci /* If it's not primitive, exit */ 1258c2ecf20Sopenharmony_ci if(sr != rs->alpha_to[0]) 1268c2ecf20Sopenharmony_ci goto err; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci /* Find prim-th root of 1, used in decoding */ 1298c2ecf20Sopenharmony_ci for(iprim = 1; (iprim % prim) != 0; iprim += rs->nn); 1308c2ecf20Sopenharmony_ci /* prim-th root of 1, index form */ 1318c2ecf20Sopenharmony_ci rs->iprim = iprim / prim; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci /* Form RS code generator polynomial from its roots */ 1348c2ecf20Sopenharmony_ci rs->genpoly[0] = 1; 1358c2ecf20Sopenharmony_ci for (i = 0, root = fcr * prim; i < nroots; i++, root += prim) { 1368c2ecf20Sopenharmony_ci rs->genpoly[i + 1] = 1; 1378c2ecf20Sopenharmony_ci /* Multiply rs->genpoly[] by @**(root + x) */ 1388c2ecf20Sopenharmony_ci for (j = i; j > 0; j--) { 1398c2ecf20Sopenharmony_ci if (rs->genpoly[j] != 0) { 1408c2ecf20Sopenharmony_ci rs->genpoly[j] = rs->genpoly[j -1] ^ 1418c2ecf20Sopenharmony_ci rs->alpha_to[rs_modnn(rs, 1428c2ecf20Sopenharmony_ci rs->index_of[rs->genpoly[j]] + root)]; 1438c2ecf20Sopenharmony_ci } else 1448c2ecf20Sopenharmony_ci rs->genpoly[j] = rs->genpoly[j - 1]; 1458c2ecf20Sopenharmony_ci } 1468c2ecf20Sopenharmony_ci /* rs->genpoly[0] can never be zero */ 1478c2ecf20Sopenharmony_ci rs->genpoly[0] = 1488c2ecf20Sopenharmony_ci rs->alpha_to[rs_modnn(rs, 1498c2ecf20Sopenharmony_ci rs->index_of[rs->genpoly[0]] + root)]; 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci /* convert rs->genpoly[] to index form for quicker encoding */ 1528c2ecf20Sopenharmony_ci for (i = 0; i <= nroots; i++) 1538c2ecf20Sopenharmony_ci rs->genpoly[i] = rs->index_of[rs->genpoly[i]]; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci rs->users = 1; 1568c2ecf20Sopenharmony_ci list_add(&rs->list, &codec_list); 1578c2ecf20Sopenharmony_ci return rs; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cierr: 1608c2ecf20Sopenharmony_ci kfree(rs->genpoly); 1618c2ecf20Sopenharmony_ci kfree(rs->index_of); 1628c2ecf20Sopenharmony_ci kfree(rs->alpha_to); 1638c2ecf20Sopenharmony_ci kfree(rs); 1648c2ecf20Sopenharmony_ci return NULL; 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci/** 1698c2ecf20Sopenharmony_ci * free_rs - Free the rs control structure 1708c2ecf20Sopenharmony_ci * @rs: The control structure which is not longer used by the 1718c2ecf20Sopenharmony_ci * caller 1728c2ecf20Sopenharmony_ci * 1738c2ecf20Sopenharmony_ci * Free the control structure. If @rs is the last user of the associated 1748c2ecf20Sopenharmony_ci * codec, free the codec as well. 1758c2ecf20Sopenharmony_ci */ 1768c2ecf20Sopenharmony_civoid free_rs(struct rs_control *rs) 1778c2ecf20Sopenharmony_ci{ 1788c2ecf20Sopenharmony_ci struct rs_codec *cd; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci if (!rs) 1818c2ecf20Sopenharmony_ci return; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci cd = rs->codec; 1848c2ecf20Sopenharmony_ci mutex_lock(&rslistlock); 1858c2ecf20Sopenharmony_ci cd->users--; 1868c2ecf20Sopenharmony_ci if(!cd->users) { 1878c2ecf20Sopenharmony_ci list_del(&cd->list); 1888c2ecf20Sopenharmony_ci kfree(cd->alpha_to); 1898c2ecf20Sopenharmony_ci kfree(cd->index_of); 1908c2ecf20Sopenharmony_ci kfree(cd->genpoly); 1918c2ecf20Sopenharmony_ci kfree(cd); 1928c2ecf20Sopenharmony_ci } 1938c2ecf20Sopenharmony_ci mutex_unlock(&rslistlock); 1948c2ecf20Sopenharmony_ci kfree(rs); 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(free_rs); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci/** 1998c2ecf20Sopenharmony_ci * init_rs_internal - Allocate rs control, find a matching codec or allocate a new one 2008c2ecf20Sopenharmony_ci * @symsize: the symbol size (number of bits) 2018c2ecf20Sopenharmony_ci * @gfpoly: the extended Galois field generator polynomial coefficients, 2028c2ecf20Sopenharmony_ci * with the 0th coefficient in the low order bit. The polynomial 2038c2ecf20Sopenharmony_ci * must be primitive; 2048c2ecf20Sopenharmony_ci * @gffunc: pointer to function to generate the next field element, 2058c2ecf20Sopenharmony_ci * or the multiplicative identity element if given 0. Used 2068c2ecf20Sopenharmony_ci * instead of gfpoly if gfpoly is 0 2078c2ecf20Sopenharmony_ci * @fcr: the first consecutive root of the rs code generator polynomial 2088c2ecf20Sopenharmony_ci * in index form 2098c2ecf20Sopenharmony_ci * @prim: primitive element to generate polynomial roots 2108c2ecf20Sopenharmony_ci * @nroots: RS code generator polynomial degree (number of roots) 2118c2ecf20Sopenharmony_ci * @gfp: GFP_ flags for allocations 2128c2ecf20Sopenharmony_ci */ 2138c2ecf20Sopenharmony_cistatic struct rs_control *init_rs_internal(int symsize, int gfpoly, 2148c2ecf20Sopenharmony_ci int (*gffunc)(int), int fcr, 2158c2ecf20Sopenharmony_ci int prim, int nroots, gfp_t gfp) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci struct list_head *tmp; 2188c2ecf20Sopenharmony_ci struct rs_control *rs; 2198c2ecf20Sopenharmony_ci unsigned int bsize; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci /* Sanity checks */ 2228c2ecf20Sopenharmony_ci if (symsize < 1) 2238c2ecf20Sopenharmony_ci return NULL; 2248c2ecf20Sopenharmony_ci if (fcr < 0 || fcr >= (1<<symsize)) 2258c2ecf20Sopenharmony_ci return NULL; 2268c2ecf20Sopenharmony_ci if (prim <= 0 || prim >= (1<<symsize)) 2278c2ecf20Sopenharmony_ci return NULL; 2288c2ecf20Sopenharmony_ci if (nroots < 0 || nroots >= (1<<symsize)) 2298c2ecf20Sopenharmony_ci return NULL; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci /* 2328c2ecf20Sopenharmony_ci * The decoder needs buffers in each control struct instance to 2338c2ecf20Sopenharmony_ci * avoid variable size or large fixed size allocations on 2348c2ecf20Sopenharmony_ci * stack. Size the buffers to arrays of [nroots + 1]. 2358c2ecf20Sopenharmony_ci */ 2368c2ecf20Sopenharmony_ci bsize = sizeof(uint16_t) * RS_DECODE_NUM_BUFFERS * (nroots + 1); 2378c2ecf20Sopenharmony_ci rs = kzalloc(sizeof(*rs) + bsize, gfp); 2388c2ecf20Sopenharmony_ci if (!rs) 2398c2ecf20Sopenharmony_ci return NULL; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci mutex_lock(&rslistlock); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci /* Walk through the list and look for a matching entry */ 2448c2ecf20Sopenharmony_ci list_for_each(tmp, &codec_list) { 2458c2ecf20Sopenharmony_ci struct rs_codec *cd = list_entry(tmp, struct rs_codec, list); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci if (symsize != cd->mm) 2488c2ecf20Sopenharmony_ci continue; 2498c2ecf20Sopenharmony_ci if (gfpoly != cd->gfpoly) 2508c2ecf20Sopenharmony_ci continue; 2518c2ecf20Sopenharmony_ci if (gffunc != cd->gffunc) 2528c2ecf20Sopenharmony_ci continue; 2538c2ecf20Sopenharmony_ci if (fcr != cd->fcr) 2548c2ecf20Sopenharmony_ci continue; 2558c2ecf20Sopenharmony_ci if (prim != cd->prim) 2568c2ecf20Sopenharmony_ci continue; 2578c2ecf20Sopenharmony_ci if (nroots != cd->nroots) 2588c2ecf20Sopenharmony_ci continue; 2598c2ecf20Sopenharmony_ci /* We have a matching one already */ 2608c2ecf20Sopenharmony_ci cd->users++; 2618c2ecf20Sopenharmony_ci rs->codec = cd; 2628c2ecf20Sopenharmony_ci goto out; 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci /* Create a new one */ 2668c2ecf20Sopenharmony_ci rs->codec = codec_init(symsize, gfpoly, gffunc, fcr, prim, nroots, gfp); 2678c2ecf20Sopenharmony_ci if (!rs->codec) { 2688c2ecf20Sopenharmony_ci kfree(rs); 2698c2ecf20Sopenharmony_ci rs = NULL; 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ciout: 2728c2ecf20Sopenharmony_ci mutex_unlock(&rslistlock); 2738c2ecf20Sopenharmony_ci return rs; 2748c2ecf20Sopenharmony_ci} 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci/** 2778c2ecf20Sopenharmony_ci * init_rs_gfp - Create a RS control struct and initialize it 2788c2ecf20Sopenharmony_ci * @symsize: the symbol size (number of bits) 2798c2ecf20Sopenharmony_ci * @gfpoly: the extended Galois field generator polynomial coefficients, 2808c2ecf20Sopenharmony_ci * with the 0th coefficient in the low order bit. The polynomial 2818c2ecf20Sopenharmony_ci * must be primitive; 2828c2ecf20Sopenharmony_ci * @fcr: the first consecutive root of the rs code generator polynomial 2838c2ecf20Sopenharmony_ci * in index form 2848c2ecf20Sopenharmony_ci * @prim: primitive element to generate polynomial roots 2858c2ecf20Sopenharmony_ci * @nroots: RS code generator polynomial degree (number of roots) 2868c2ecf20Sopenharmony_ci * @gfp: Memory allocation flags. 2878c2ecf20Sopenharmony_ci */ 2888c2ecf20Sopenharmony_cistruct rs_control *init_rs_gfp(int symsize, int gfpoly, int fcr, int prim, 2898c2ecf20Sopenharmony_ci int nroots, gfp_t gfp) 2908c2ecf20Sopenharmony_ci{ 2918c2ecf20Sopenharmony_ci return init_rs_internal(symsize, gfpoly, NULL, fcr, prim, nroots, gfp); 2928c2ecf20Sopenharmony_ci} 2938c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(init_rs_gfp); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci/** 2968c2ecf20Sopenharmony_ci * init_rs_non_canonical - Allocate rs control struct for fields with 2978c2ecf20Sopenharmony_ci * non-canonical representation 2988c2ecf20Sopenharmony_ci * @symsize: the symbol size (number of bits) 2998c2ecf20Sopenharmony_ci * @gffunc: pointer to function to generate the next field element, 3008c2ecf20Sopenharmony_ci * or the multiplicative identity element if given 0. Used 3018c2ecf20Sopenharmony_ci * instead of gfpoly if gfpoly is 0 3028c2ecf20Sopenharmony_ci * @fcr: the first consecutive root of the rs code generator polynomial 3038c2ecf20Sopenharmony_ci * in index form 3048c2ecf20Sopenharmony_ci * @prim: primitive element to generate polynomial roots 3058c2ecf20Sopenharmony_ci * @nroots: RS code generator polynomial degree (number of roots) 3068c2ecf20Sopenharmony_ci */ 3078c2ecf20Sopenharmony_cistruct rs_control *init_rs_non_canonical(int symsize, int (*gffunc)(int), 3088c2ecf20Sopenharmony_ci int fcr, int prim, int nroots) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci return init_rs_internal(symsize, 0, gffunc, fcr, prim, nroots, 3118c2ecf20Sopenharmony_ci GFP_KERNEL); 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(init_rs_non_canonical); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci#ifdef CONFIG_REED_SOLOMON_ENC8 3168c2ecf20Sopenharmony_ci/** 3178c2ecf20Sopenharmony_ci * encode_rs8 - Calculate the parity for data values (8bit data width) 3188c2ecf20Sopenharmony_ci * @rsc: the rs control structure 3198c2ecf20Sopenharmony_ci * @data: data field of a given type 3208c2ecf20Sopenharmony_ci * @len: data length 3218c2ecf20Sopenharmony_ci * @par: parity data, must be initialized by caller (usually all 0) 3228c2ecf20Sopenharmony_ci * @invmsk: invert data mask (will be xored on data) 3238c2ecf20Sopenharmony_ci * 3248c2ecf20Sopenharmony_ci * The parity uses a uint16_t data type to enable 3258c2ecf20Sopenharmony_ci * symbol size > 8. The calling code must take care of encoding of the 3268c2ecf20Sopenharmony_ci * syndrome result for storage itself. 3278c2ecf20Sopenharmony_ci */ 3288c2ecf20Sopenharmony_ciint encode_rs8(struct rs_control *rsc, uint8_t *data, int len, uint16_t *par, 3298c2ecf20Sopenharmony_ci uint16_t invmsk) 3308c2ecf20Sopenharmony_ci{ 3318c2ecf20Sopenharmony_ci#include "encode_rs.c" 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(encode_rs8); 3348c2ecf20Sopenharmony_ci#endif 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci#ifdef CONFIG_REED_SOLOMON_DEC8 3378c2ecf20Sopenharmony_ci/** 3388c2ecf20Sopenharmony_ci * decode_rs8 - Decode codeword (8bit data width) 3398c2ecf20Sopenharmony_ci * @rsc: the rs control structure 3408c2ecf20Sopenharmony_ci * @data: data field of a given type 3418c2ecf20Sopenharmony_ci * @par: received parity data field 3428c2ecf20Sopenharmony_ci * @len: data length 3438c2ecf20Sopenharmony_ci * @s: syndrome data field, must be in index form 3448c2ecf20Sopenharmony_ci * (if NULL, syndrome is calculated) 3458c2ecf20Sopenharmony_ci * @no_eras: number of erasures 3468c2ecf20Sopenharmony_ci * @eras_pos: position of erasures, can be NULL 3478c2ecf20Sopenharmony_ci * @invmsk: invert data mask (will be xored on data, not on parity!) 3488c2ecf20Sopenharmony_ci * @corr: buffer to store correction bitmask on eras_pos 3498c2ecf20Sopenharmony_ci * 3508c2ecf20Sopenharmony_ci * The syndrome and parity uses a uint16_t data type to enable 3518c2ecf20Sopenharmony_ci * symbol size > 8. The calling code must take care of decoding of the 3528c2ecf20Sopenharmony_ci * syndrome result and the received parity before calling this code. 3538c2ecf20Sopenharmony_ci * 3548c2ecf20Sopenharmony_ci * Note: The rs_control struct @rsc contains buffers which are used for 3558c2ecf20Sopenharmony_ci * decoding, so the caller has to ensure that decoder invocations are 3568c2ecf20Sopenharmony_ci * serialized. 3578c2ecf20Sopenharmony_ci * 3588c2ecf20Sopenharmony_ci * Returns the number of corrected symbols or -EBADMSG for uncorrectable 3598c2ecf20Sopenharmony_ci * errors. The count includes errors in the parity. 3608c2ecf20Sopenharmony_ci */ 3618c2ecf20Sopenharmony_ciint decode_rs8(struct rs_control *rsc, uint8_t *data, uint16_t *par, int len, 3628c2ecf20Sopenharmony_ci uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, 3638c2ecf20Sopenharmony_ci uint16_t *corr) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci#include "decode_rs.c" 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(decode_rs8); 3688c2ecf20Sopenharmony_ci#endif 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci#ifdef CONFIG_REED_SOLOMON_ENC16 3718c2ecf20Sopenharmony_ci/** 3728c2ecf20Sopenharmony_ci * encode_rs16 - Calculate the parity for data values (16bit data width) 3738c2ecf20Sopenharmony_ci * @rsc: the rs control structure 3748c2ecf20Sopenharmony_ci * @data: data field of a given type 3758c2ecf20Sopenharmony_ci * @len: data length 3768c2ecf20Sopenharmony_ci * @par: parity data, must be initialized by caller (usually all 0) 3778c2ecf20Sopenharmony_ci * @invmsk: invert data mask (will be xored on data, not on parity!) 3788c2ecf20Sopenharmony_ci * 3798c2ecf20Sopenharmony_ci * Each field in the data array contains up to symbol size bits of valid data. 3808c2ecf20Sopenharmony_ci */ 3818c2ecf20Sopenharmony_ciint encode_rs16(struct rs_control *rsc, uint16_t *data, int len, uint16_t *par, 3828c2ecf20Sopenharmony_ci uint16_t invmsk) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci#include "encode_rs.c" 3858c2ecf20Sopenharmony_ci} 3868c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(encode_rs16); 3878c2ecf20Sopenharmony_ci#endif 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci#ifdef CONFIG_REED_SOLOMON_DEC16 3908c2ecf20Sopenharmony_ci/** 3918c2ecf20Sopenharmony_ci * decode_rs16 - Decode codeword (16bit data width) 3928c2ecf20Sopenharmony_ci * @rsc: the rs control structure 3938c2ecf20Sopenharmony_ci * @data: data field of a given type 3948c2ecf20Sopenharmony_ci * @par: received parity data field 3958c2ecf20Sopenharmony_ci * @len: data length 3968c2ecf20Sopenharmony_ci * @s: syndrome data field, must be in index form 3978c2ecf20Sopenharmony_ci * (if NULL, syndrome is calculated) 3988c2ecf20Sopenharmony_ci * @no_eras: number of erasures 3998c2ecf20Sopenharmony_ci * @eras_pos: position of erasures, can be NULL 4008c2ecf20Sopenharmony_ci * @invmsk: invert data mask (will be xored on data, not on parity!) 4018c2ecf20Sopenharmony_ci * @corr: buffer to store correction bitmask on eras_pos 4028c2ecf20Sopenharmony_ci * 4038c2ecf20Sopenharmony_ci * Each field in the data array contains up to symbol size bits of valid data. 4048c2ecf20Sopenharmony_ci * 4058c2ecf20Sopenharmony_ci * Note: The rc_control struct @rsc contains buffers which are used for 4068c2ecf20Sopenharmony_ci * decoding, so the caller has to ensure that decoder invocations are 4078c2ecf20Sopenharmony_ci * serialized. 4088c2ecf20Sopenharmony_ci * 4098c2ecf20Sopenharmony_ci * Returns the number of corrected symbols or -EBADMSG for uncorrectable 4108c2ecf20Sopenharmony_ci * errors. The count includes errors in the parity. 4118c2ecf20Sopenharmony_ci */ 4128c2ecf20Sopenharmony_ciint decode_rs16(struct rs_control *rsc, uint16_t *data, uint16_t *par, int len, 4138c2ecf20Sopenharmony_ci uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, 4148c2ecf20Sopenharmony_ci uint16_t *corr) 4158c2ecf20Sopenharmony_ci{ 4168c2ecf20Sopenharmony_ci#include "decode_rs.c" 4178c2ecf20Sopenharmony_ci} 4188c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(decode_rs16); 4198c2ecf20Sopenharmony_ci#endif 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 4228c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Reed Solomon encoder/decoder"); 4238c2ecf20Sopenharmony_ciMODULE_AUTHOR("Phil Karn, Thomas Gleixner"); 4248c2ecf20Sopenharmony_ci 425