reed_solomon.c 12 KB

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