1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Generic Reed Solomon encoder / decoder library
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Reed Solomon code lifted from reed solomon library written by Phil Karn
8*4882a593Smuzhiyun * Copyright 2002 Phil Karn, KA9Q
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Description:
11*4882a593Smuzhiyun *
12*4882a593Smuzhiyun * The generic Reed Solomon library provides runtime configurable
13*4882a593Smuzhiyun * encoding / decoding of RS codes.
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * Each user must call init_rs to get a pointer to a rs_control structure
16*4882a593Smuzhiyun * for the given rs parameters. The control struct is unique per instance.
17*4882a593Smuzhiyun * It points to a codec which can be shared by multiple control structures.
18*4882a593Smuzhiyun * If a codec is newly allocated then the polynomial arrays for fast
19*4882a593Smuzhiyun * encoding / decoding are built. This can take some time so make sure not
20*4882a593Smuzhiyun * to call this function from a time critical path. Usually a module /
21*4882a593Smuzhiyun * driver should initialize the necessary rs_control structure on module /
22*4882a593Smuzhiyun * driver init and release it on exit.
23*4882a593Smuzhiyun *
24*4882a593Smuzhiyun * The encoding puts the calculated syndrome into a given syndrome buffer.
25*4882a593Smuzhiyun *
26*4882a593Smuzhiyun * The decoding is a two step process. The first step calculates the
27*4882a593Smuzhiyun * syndrome over the received (data + syndrome) and calls the second stage,
28*4882a593Smuzhiyun * which does the decoding / error correction itself. Many hw encoders
29*4882a593Smuzhiyun * provide a syndrome calculation over the received data + syndrome and can
30*4882a593Smuzhiyun * call the second stage directly.
31*4882a593Smuzhiyun */
32*4882a593Smuzhiyun #include <linux/errno.h>
33*4882a593Smuzhiyun #include <linux/kernel.h>
34*4882a593Smuzhiyun #include <linux/init.h>
35*4882a593Smuzhiyun #include <linux/module.h>
36*4882a593Smuzhiyun #include <linux/rslib.h>
37*4882a593Smuzhiyun #include <linux/slab.h>
38*4882a593Smuzhiyun #include <linux/mutex.h>
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun enum {
41*4882a593Smuzhiyun RS_DECODE_LAMBDA,
42*4882a593Smuzhiyun RS_DECODE_SYN,
43*4882a593Smuzhiyun RS_DECODE_B,
44*4882a593Smuzhiyun RS_DECODE_T,
45*4882a593Smuzhiyun RS_DECODE_OMEGA,
46*4882a593Smuzhiyun RS_DECODE_ROOT,
47*4882a593Smuzhiyun RS_DECODE_REG,
48*4882a593Smuzhiyun RS_DECODE_LOC,
49*4882a593Smuzhiyun RS_DECODE_NUM_BUFFERS
50*4882a593Smuzhiyun };
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun /* This list holds all currently allocated rs codec structures */
53*4882a593Smuzhiyun static LIST_HEAD(codec_list);
54*4882a593Smuzhiyun /* Protection for the list */
55*4882a593Smuzhiyun static DEFINE_MUTEX(rslistlock);
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun /**
58*4882a593Smuzhiyun * codec_init - Initialize a Reed-Solomon codec
59*4882a593Smuzhiyun * @symsize: symbol size, bits (1-8)
60*4882a593Smuzhiyun * @gfpoly: Field generator polynomial coefficients
61*4882a593Smuzhiyun * @gffunc: Field generator function
62*4882a593Smuzhiyun * @fcr: first root of RS code generator polynomial, index form
63*4882a593Smuzhiyun * @prim: primitive element to generate polynomial roots
64*4882a593Smuzhiyun * @nroots: RS code generator polynomial degree (number of roots)
65*4882a593Smuzhiyun * @gfp: GFP_ flags for allocations
66*4882a593Smuzhiyun *
67*4882a593Smuzhiyun * Allocate a codec structure and the polynom arrays for faster
68*4882a593Smuzhiyun * en/decoding. Fill the arrays according to the given parameters.
69*4882a593Smuzhiyun */
codec_init(int symsize,int gfpoly,int (* gffunc)(int),int fcr,int prim,int nroots,gfp_t gfp)70*4882a593Smuzhiyun static struct rs_codec *codec_init(int symsize, int gfpoly, int (*gffunc)(int),
71*4882a593Smuzhiyun int fcr, int prim, int nroots, gfp_t gfp)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun int i, j, sr, root, iprim;
74*4882a593Smuzhiyun struct rs_codec *rs;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun rs = kzalloc(sizeof(*rs), gfp);
77*4882a593Smuzhiyun if (!rs)
78*4882a593Smuzhiyun return NULL;
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun INIT_LIST_HEAD(&rs->list);
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun rs->mm = symsize;
83*4882a593Smuzhiyun rs->nn = (1 << symsize) - 1;
84*4882a593Smuzhiyun rs->fcr = fcr;
85*4882a593Smuzhiyun rs->prim = prim;
86*4882a593Smuzhiyun rs->nroots = nroots;
87*4882a593Smuzhiyun rs->gfpoly = gfpoly;
88*4882a593Smuzhiyun rs->gffunc = gffunc;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun /* Allocate the arrays */
91*4882a593Smuzhiyun rs->alpha_to = kmalloc_array(rs->nn + 1, sizeof(uint16_t), gfp);
92*4882a593Smuzhiyun if (rs->alpha_to == NULL)
93*4882a593Smuzhiyun goto err;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun rs->index_of = kmalloc_array(rs->nn + 1, sizeof(uint16_t), gfp);
96*4882a593Smuzhiyun if (rs->index_of == NULL)
97*4882a593Smuzhiyun goto err;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun rs->genpoly = kmalloc_array(rs->nroots + 1, sizeof(uint16_t), gfp);
100*4882a593Smuzhiyun if(rs->genpoly == NULL)
101*4882a593Smuzhiyun goto err;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun /* Generate Galois field lookup tables */
104*4882a593Smuzhiyun rs->index_of[0] = rs->nn; /* log(zero) = -inf */
105*4882a593Smuzhiyun rs->alpha_to[rs->nn] = 0; /* alpha**-inf = 0 */
106*4882a593Smuzhiyun if (gfpoly) {
107*4882a593Smuzhiyun sr = 1;
108*4882a593Smuzhiyun for (i = 0; i < rs->nn; i++) {
109*4882a593Smuzhiyun rs->index_of[sr] = i;
110*4882a593Smuzhiyun rs->alpha_to[i] = sr;
111*4882a593Smuzhiyun sr <<= 1;
112*4882a593Smuzhiyun if (sr & (1 << symsize))
113*4882a593Smuzhiyun sr ^= gfpoly;
114*4882a593Smuzhiyun sr &= rs->nn;
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun } else {
117*4882a593Smuzhiyun sr = gffunc(0);
118*4882a593Smuzhiyun for (i = 0; i < rs->nn; i++) {
119*4882a593Smuzhiyun rs->index_of[sr] = i;
120*4882a593Smuzhiyun rs->alpha_to[i] = sr;
121*4882a593Smuzhiyun sr = gffunc(sr);
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun /* If it's not primitive, exit */
125*4882a593Smuzhiyun if(sr != rs->alpha_to[0])
126*4882a593Smuzhiyun goto err;
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun /* Find prim-th root of 1, used in decoding */
129*4882a593Smuzhiyun for(iprim = 1; (iprim % prim) != 0; iprim += rs->nn);
130*4882a593Smuzhiyun /* prim-th root of 1, index form */
131*4882a593Smuzhiyun rs->iprim = iprim / prim;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun /* Form RS code generator polynomial from its roots */
134*4882a593Smuzhiyun rs->genpoly[0] = 1;
135*4882a593Smuzhiyun for (i = 0, root = fcr * prim; i < nroots; i++, root += prim) {
136*4882a593Smuzhiyun rs->genpoly[i + 1] = 1;
137*4882a593Smuzhiyun /* Multiply rs->genpoly[] by @**(root + x) */
138*4882a593Smuzhiyun for (j = i; j > 0; j--) {
139*4882a593Smuzhiyun if (rs->genpoly[j] != 0) {
140*4882a593Smuzhiyun rs->genpoly[j] = rs->genpoly[j -1] ^
141*4882a593Smuzhiyun rs->alpha_to[rs_modnn(rs,
142*4882a593Smuzhiyun rs->index_of[rs->genpoly[j]] + root)];
143*4882a593Smuzhiyun } else
144*4882a593Smuzhiyun rs->genpoly[j] = rs->genpoly[j - 1];
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun /* rs->genpoly[0] can never be zero */
147*4882a593Smuzhiyun rs->genpoly[0] =
148*4882a593Smuzhiyun rs->alpha_to[rs_modnn(rs,
149*4882a593Smuzhiyun rs->index_of[rs->genpoly[0]] + root)];
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun /* convert rs->genpoly[] to index form for quicker encoding */
152*4882a593Smuzhiyun for (i = 0; i <= nroots; i++)
153*4882a593Smuzhiyun rs->genpoly[i] = rs->index_of[rs->genpoly[i]];
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun rs->users = 1;
156*4882a593Smuzhiyun list_add(&rs->list, &codec_list);
157*4882a593Smuzhiyun return rs;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun err:
160*4882a593Smuzhiyun kfree(rs->genpoly);
161*4882a593Smuzhiyun kfree(rs->index_of);
162*4882a593Smuzhiyun kfree(rs->alpha_to);
163*4882a593Smuzhiyun kfree(rs);
164*4882a593Smuzhiyun return NULL;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun /**
169*4882a593Smuzhiyun * free_rs - Free the rs control structure
170*4882a593Smuzhiyun * @rs: The control structure which is not longer used by the
171*4882a593Smuzhiyun * caller
172*4882a593Smuzhiyun *
173*4882a593Smuzhiyun * Free the control structure. If @rs is the last user of the associated
174*4882a593Smuzhiyun * codec, free the codec as well.
175*4882a593Smuzhiyun */
free_rs(struct rs_control * rs)176*4882a593Smuzhiyun void free_rs(struct rs_control *rs)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun struct rs_codec *cd;
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun if (!rs)
181*4882a593Smuzhiyun return;
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun cd = rs->codec;
184*4882a593Smuzhiyun mutex_lock(&rslistlock);
185*4882a593Smuzhiyun cd->users--;
186*4882a593Smuzhiyun if(!cd->users) {
187*4882a593Smuzhiyun list_del(&cd->list);
188*4882a593Smuzhiyun kfree(cd->alpha_to);
189*4882a593Smuzhiyun kfree(cd->index_of);
190*4882a593Smuzhiyun kfree(cd->genpoly);
191*4882a593Smuzhiyun kfree(cd);
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun mutex_unlock(&rslistlock);
194*4882a593Smuzhiyun kfree(rs);
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(free_rs);
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun /**
199*4882a593Smuzhiyun * init_rs_internal - Allocate rs control, find a matching codec or allocate a new one
200*4882a593Smuzhiyun * @symsize: the symbol size (number of bits)
201*4882a593Smuzhiyun * @gfpoly: the extended Galois field generator polynomial coefficients,
202*4882a593Smuzhiyun * with the 0th coefficient in the low order bit. The polynomial
203*4882a593Smuzhiyun * must be primitive;
204*4882a593Smuzhiyun * @gffunc: pointer to function to generate the next field element,
205*4882a593Smuzhiyun * or the multiplicative identity element if given 0. Used
206*4882a593Smuzhiyun * instead of gfpoly if gfpoly is 0
207*4882a593Smuzhiyun * @fcr: the first consecutive root of the rs code generator polynomial
208*4882a593Smuzhiyun * in index form
209*4882a593Smuzhiyun * @prim: primitive element to generate polynomial roots
210*4882a593Smuzhiyun * @nroots: RS code generator polynomial degree (number of roots)
211*4882a593Smuzhiyun * @gfp: GFP_ flags for allocations
212*4882a593Smuzhiyun */
init_rs_internal(int symsize,int gfpoly,int (* gffunc)(int),int fcr,int prim,int nroots,gfp_t gfp)213*4882a593Smuzhiyun static struct rs_control *init_rs_internal(int symsize, int gfpoly,
214*4882a593Smuzhiyun int (*gffunc)(int), int fcr,
215*4882a593Smuzhiyun int prim, int nroots, gfp_t gfp)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun struct list_head *tmp;
218*4882a593Smuzhiyun struct rs_control *rs;
219*4882a593Smuzhiyun unsigned int bsize;
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun /* Sanity checks */
222*4882a593Smuzhiyun if (symsize < 1)
223*4882a593Smuzhiyun return NULL;
224*4882a593Smuzhiyun if (fcr < 0 || fcr >= (1<<symsize))
225*4882a593Smuzhiyun return NULL;
226*4882a593Smuzhiyun if (prim <= 0 || prim >= (1<<symsize))
227*4882a593Smuzhiyun return NULL;
228*4882a593Smuzhiyun if (nroots < 0 || nroots >= (1<<symsize))
229*4882a593Smuzhiyun return NULL;
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun /*
232*4882a593Smuzhiyun * The decoder needs buffers in each control struct instance to
233*4882a593Smuzhiyun * avoid variable size or large fixed size allocations on
234*4882a593Smuzhiyun * stack. Size the buffers to arrays of [nroots + 1].
235*4882a593Smuzhiyun */
236*4882a593Smuzhiyun bsize = sizeof(uint16_t) * RS_DECODE_NUM_BUFFERS * (nroots + 1);
237*4882a593Smuzhiyun rs = kzalloc(sizeof(*rs) + bsize, gfp);
238*4882a593Smuzhiyun if (!rs)
239*4882a593Smuzhiyun return NULL;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun mutex_lock(&rslistlock);
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun /* Walk through the list and look for a matching entry */
244*4882a593Smuzhiyun list_for_each(tmp, &codec_list) {
245*4882a593Smuzhiyun struct rs_codec *cd = list_entry(tmp, struct rs_codec, list);
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun if (symsize != cd->mm)
248*4882a593Smuzhiyun continue;
249*4882a593Smuzhiyun if (gfpoly != cd->gfpoly)
250*4882a593Smuzhiyun continue;
251*4882a593Smuzhiyun if (gffunc != cd->gffunc)
252*4882a593Smuzhiyun continue;
253*4882a593Smuzhiyun if (fcr != cd->fcr)
254*4882a593Smuzhiyun continue;
255*4882a593Smuzhiyun if (prim != cd->prim)
256*4882a593Smuzhiyun continue;
257*4882a593Smuzhiyun if (nroots != cd->nroots)
258*4882a593Smuzhiyun continue;
259*4882a593Smuzhiyun /* We have a matching one already */
260*4882a593Smuzhiyun cd->users++;
261*4882a593Smuzhiyun rs->codec = cd;
262*4882a593Smuzhiyun goto out;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun /* Create a new one */
266*4882a593Smuzhiyun rs->codec = codec_init(symsize, gfpoly, gffunc, fcr, prim, nroots, gfp);
267*4882a593Smuzhiyun if (!rs->codec) {
268*4882a593Smuzhiyun kfree(rs);
269*4882a593Smuzhiyun rs = NULL;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun out:
272*4882a593Smuzhiyun mutex_unlock(&rslistlock);
273*4882a593Smuzhiyun return rs;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun /**
277*4882a593Smuzhiyun * init_rs_gfp - Create a RS control struct and initialize it
278*4882a593Smuzhiyun * @symsize: the symbol size (number of bits)
279*4882a593Smuzhiyun * @gfpoly: the extended Galois field generator polynomial coefficients,
280*4882a593Smuzhiyun * with the 0th coefficient in the low order bit. The polynomial
281*4882a593Smuzhiyun * must be primitive;
282*4882a593Smuzhiyun * @fcr: the first consecutive root of the rs code generator polynomial
283*4882a593Smuzhiyun * in index form
284*4882a593Smuzhiyun * @prim: primitive element to generate polynomial roots
285*4882a593Smuzhiyun * @nroots: RS code generator polynomial degree (number of roots)
286*4882a593Smuzhiyun * @gfp: Memory allocation flags.
287*4882a593Smuzhiyun */
init_rs_gfp(int symsize,int gfpoly,int fcr,int prim,int nroots,gfp_t gfp)288*4882a593Smuzhiyun struct rs_control *init_rs_gfp(int symsize, int gfpoly, int fcr, int prim,
289*4882a593Smuzhiyun int nroots, gfp_t gfp)
290*4882a593Smuzhiyun {
291*4882a593Smuzhiyun return init_rs_internal(symsize, gfpoly, NULL, fcr, prim, nroots, gfp);
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(init_rs_gfp);
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun /**
296*4882a593Smuzhiyun * init_rs_non_canonical - Allocate rs control struct for fields with
297*4882a593Smuzhiyun * non-canonical representation
298*4882a593Smuzhiyun * @symsize: the symbol size (number of bits)
299*4882a593Smuzhiyun * @gffunc: pointer to function to generate the next field element,
300*4882a593Smuzhiyun * or the multiplicative identity element if given 0. Used
301*4882a593Smuzhiyun * instead of gfpoly if gfpoly is 0
302*4882a593Smuzhiyun * @fcr: the first consecutive root of the rs code generator polynomial
303*4882a593Smuzhiyun * in index form
304*4882a593Smuzhiyun * @prim: primitive element to generate polynomial roots
305*4882a593Smuzhiyun * @nroots: RS code generator polynomial degree (number of roots)
306*4882a593Smuzhiyun */
init_rs_non_canonical(int symsize,int (* gffunc)(int),int fcr,int prim,int nroots)307*4882a593Smuzhiyun struct rs_control *init_rs_non_canonical(int symsize, int (*gffunc)(int),
308*4882a593Smuzhiyun int fcr, int prim, int nroots)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun return init_rs_internal(symsize, 0, gffunc, fcr, prim, nroots,
311*4882a593Smuzhiyun GFP_KERNEL);
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(init_rs_non_canonical);
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun #ifdef CONFIG_REED_SOLOMON_ENC8
316*4882a593Smuzhiyun /**
317*4882a593Smuzhiyun * encode_rs8 - Calculate the parity for data values (8bit data width)
318*4882a593Smuzhiyun * @rsc: the rs control structure
319*4882a593Smuzhiyun * @data: data field of a given type
320*4882a593Smuzhiyun * @len: data length
321*4882a593Smuzhiyun * @par: parity data, must be initialized by caller (usually all 0)
322*4882a593Smuzhiyun * @invmsk: invert data mask (will be xored on data)
323*4882a593Smuzhiyun *
324*4882a593Smuzhiyun * The parity uses a uint16_t data type to enable
325*4882a593Smuzhiyun * symbol size > 8. The calling code must take care of encoding of the
326*4882a593Smuzhiyun * syndrome result for storage itself.
327*4882a593Smuzhiyun */
encode_rs8(struct rs_control * rsc,uint8_t * data,int len,uint16_t * par,uint16_t invmsk)328*4882a593Smuzhiyun int encode_rs8(struct rs_control *rsc, uint8_t *data, int len, uint16_t *par,
329*4882a593Smuzhiyun uint16_t invmsk)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun #include "encode_rs.c"
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(encode_rs8);
334*4882a593Smuzhiyun #endif
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun #ifdef CONFIG_REED_SOLOMON_DEC8
337*4882a593Smuzhiyun /**
338*4882a593Smuzhiyun * decode_rs8 - Decode codeword (8bit data width)
339*4882a593Smuzhiyun * @rsc: the rs control structure
340*4882a593Smuzhiyun * @data: data field of a given type
341*4882a593Smuzhiyun * @par: received parity data field
342*4882a593Smuzhiyun * @len: data length
343*4882a593Smuzhiyun * @s: syndrome data field, must be in index form
344*4882a593Smuzhiyun * (if NULL, syndrome is calculated)
345*4882a593Smuzhiyun * @no_eras: number of erasures
346*4882a593Smuzhiyun * @eras_pos: position of erasures, can be NULL
347*4882a593Smuzhiyun * @invmsk: invert data mask (will be xored on data, not on parity!)
348*4882a593Smuzhiyun * @corr: buffer to store correction bitmask on eras_pos
349*4882a593Smuzhiyun *
350*4882a593Smuzhiyun * The syndrome and parity uses a uint16_t data type to enable
351*4882a593Smuzhiyun * symbol size > 8. The calling code must take care of decoding of the
352*4882a593Smuzhiyun * syndrome result and the received parity before calling this code.
353*4882a593Smuzhiyun *
354*4882a593Smuzhiyun * Note: The rs_control struct @rsc contains buffers which are used for
355*4882a593Smuzhiyun * decoding, so the caller has to ensure that decoder invocations are
356*4882a593Smuzhiyun * serialized.
357*4882a593Smuzhiyun *
358*4882a593Smuzhiyun * Returns the number of corrected symbols or -EBADMSG for uncorrectable
359*4882a593Smuzhiyun * errors. The count includes errors in the parity.
360*4882a593Smuzhiyun */
decode_rs8(struct rs_control * rsc,uint8_t * data,uint16_t * par,int len,uint16_t * s,int no_eras,int * eras_pos,uint16_t invmsk,uint16_t * corr)361*4882a593Smuzhiyun int decode_rs8(struct rs_control *rsc, uint8_t *data, uint16_t *par, int len,
362*4882a593Smuzhiyun uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk,
363*4882a593Smuzhiyun uint16_t *corr)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun #include "decode_rs.c"
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(decode_rs8);
368*4882a593Smuzhiyun #endif
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun #ifdef CONFIG_REED_SOLOMON_ENC16
371*4882a593Smuzhiyun /**
372*4882a593Smuzhiyun * encode_rs16 - Calculate the parity for data values (16bit data width)
373*4882a593Smuzhiyun * @rsc: the rs control structure
374*4882a593Smuzhiyun * @data: data field of a given type
375*4882a593Smuzhiyun * @len: data length
376*4882a593Smuzhiyun * @par: parity data, must be initialized by caller (usually all 0)
377*4882a593Smuzhiyun * @invmsk: invert data mask (will be xored on data, not on parity!)
378*4882a593Smuzhiyun *
379*4882a593Smuzhiyun * Each field in the data array contains up to symbol size bits of valid data.
380*4882a593Smuzhiyun */
encode_rs16(struct rs_control * rsc,uint16_t * data,int len,uint16_t * par,uint16_t invmsk)381*4882a593Smuzhiyun int encode_rs16(struct rs_control *rsc, uint16_t *data, int len, uint16_t *par,
382*4882a593Smuzhiyun uint16_t invmsk)
383*4882a593Smuzhiyun {
384*4882a593Smuzhiyun #include "encode_rs.c"
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(encode_rs16);
387*4882a593Smuzhiyun #endif
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun #ifdef CONFIG_REED_SOLOMON_DEC16
390*4882a593Smuzhiyun /**
391*4882a593Smuzhiyun * decode_rs16 - Decode codeword (16bit data width)
392*4882a593Smuzhiyun * @rsc: the rs control structure
393*4882a593Smuzhiyun * @data: data field of a given type
394*4882a593Smuzhiyun * @par: received parity data field
395*4882a593Smuzhiyun * @len: data length
396*4882a593Smuzhiyun * @s: syndrome data field, must be in index form
397*4882a593Smuzhiyun * (if NULL, syndrome is calculated)
398*4882a593Smuzhiyun * @no_eras: number of erasures
399*4882a593Smuzhiyun * @eras_pos: position of erasures, can be NULL
400*4882a593Smuzhiyun * @invmsk: invert data mask (will be xored on data, not on parity!)
401*4882a593Smuzhiyun * @corr: buffer to store correction bitmask on eras_pos
402*4882a593Smuzhiyun *
403*4882a593Smuzhiyun * Each field in the data array contains up to symbol size bits of valid data.
404*4882a593Smuzhiyun *
405*4882a593Smuzhiyun * Note: The rc_control struct @rsc contains buffers which are used for
406*4882a593Smuzhiyun * decoding, so the caller has to ensure that decoder invocations are
407*4882a593Smuzhiyun * serialized.
408*4882a593Smuzhiyun *
409*4882a593Smuzhiyun * Returns the number of corrected symbols or -EBADMSG for uncorrectable
410*4882a593Smuzhiyun * errors. The count includes errors in the parity.
411*4882a593Smuzhiyun */
decode_rs16(struct rs_control * rsc,uint16_t * data,uint16_t * par,int len,uint16_t * s,int no_eras,int * eras_pos,uint16_t invmsk,uint16_t * corr)412*4882a593Smuzhiyun int decode_rs16(struct rs_control *rsc, uint16_t *data, uint16_t *par, int len,
413*4882a593Smuzhiyun uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk,
414*4882a593Smuzhiyun uint16_t *corr)
415*4882a593Smuzhiyun {
416*4882a593Smuzhiyun #include "decode_rs.c"
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(decode_rs16);
419*4882a593Smuzhiyun #endif
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun MODULE_LICENSE("GPL");
422*4882a593Smuzhiyun MODULE_DESCRIPTION("Reed Solomon encoder/decoder");
423*4882a593Smuzhiyun MODULE_AUTHOR("Phil Karn, Thomas Gleixner");
424*4882a593Smuzhiyun
425