reed_solomon.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  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. #include <asm/semaphore.h>
  48. /* This list holds all currently allocated rs control structures */
  49. static LIST_HEAD (rslist);
  50. /* Protection for the list */
  51. static DEFINE_MUTEX(rslistlock);
  52. /**
  53. * rs_init - Initialize a Reed-Solomon codec
  54. * @symsize: symbol size, bits (1-8)
  55. * @gfpoly: Field generator polynomial coefficients
  56. * @gffunc: Field generator function
  57. * @fcr: first root of RS code generator polynomial, index form
  58. * @prim: primitive element to generate polynomial roots
  59. * @nroots: RS code generator polynomial degree (number of roots)
  60. *
  61. * Allocate a control structure and the polynom arrays for faster
  62. * en/decoding. Fill the arrays according to the given parameters.
  63. */
  64. static struct rs_control *rs_init(int symsize, int gfpoly, int (*gffunc)(int),
  65. int fcr, int prim, int nroots)
  66. {
  67. struct rs_control *rs;
  68. int i, j, sr, root, iprim;
  69. /* Allocate the control structure */
  70. rs = kmalloc(sizeof (struct rs_control), GFP_KERNEL);
  71. if (rs == NULL)
  72. return NULL;
  73. INIT_LIST_HEAD(&rs->list);
  74. rs->mm = symsize;
  75. rs->nn = (1 << symsize) - 1;
  76. rs->fcr = fcr;
  77. rs->prim = prim;
  78. rs->nroots = nroots;
  79. rs->gfpoly = gfpoly;
  80. rs->gffunc = gffunc;
  81. /* Allocate the arrays */
  82. rs->alpha_to = kmalloc(sizeof(uint16_t) * (rs->nn + 1), GFP_KERNEL);
  83. if (rs->alpha_to == NULL)
  84. goto errrs;
  85. rs->index_of = kmalloc(sizeof(uint16_t) * (rs->nn + 1), GFP_KERNEL);
  86. if (rs->index_of == NULL)
  87. goto erralp;
  88. rs->genpoly = kmalloc(sizeof(uint16_t) * (rs->nroots + 1), GFP_KERNEL);
  89. if(rs->genpoly == NULL)
  90. goto erridx;
  91. /* Generate Galois field lookup tables */
  92. rs->index_of[0] = rs->nn; /* log(zero) = -inf */
  93. rs->alpha_to[rs->nn] = 0; /* alpha**-inf = 0 */
  94. if (gfpoly) {
  95. sr = 1;
  96. for (i = 0; i < rs->nn; i++) {
  97. rs->index_of[sr] = i;
  98. rs->alpha_to[i] = sr;
  99. sr <<= 1;
  100. if (sr & (1 << symsize))
  101. sr ^= gfpoly;
  102. sr &= rs->nn;
  103. }
  104. } else {
  105. sr = gffunc(0);
  106. for (i = 0; i < rs->nn; i++) {
  107. rs->index_of[sr] = i;
  108. rs->alpha_to[i] = sr;
  109. sr = gffunc(sr);
  110. }
  111. }
  112. /* If it's not primitive, exit */
  113. if(sr != rs->alpha_to[0])
  114. goto errpol;
  115. /* Find prim-th root of 1, used in decoding */
  116. for(iprim = 1; (iprim % prim) != 0; iprim += rs->nn);
  117. /* prim-th root of 1, index form */
  118. rs->iprim = iprim / prim;
  119. /* Form RS code generator polynomial from its roots */
  120. rs->genpoly[0] = 1;
  121. for (i = 0, root = fcr * prim; i < nroots; i++, root += prim) {
  122. rs->genpoly[i + 1] = 1;
  123. /* Multiply rs->genpoly[] by @**(root + x) */
  124. for (j = i; j > 0; j--) {
  125. if (rs->genpoly[j] != 0) {
  126. rs->genpoly[j] = rs->genpoly[j -1] ^
  127. rs->alpha_to[rs_modnn(rs,
  128. rs->index_of[rs->genpoly[j]] + root)];
  129. } else
  130. rs->genpoly[j] = rs->genpoly[j - 1];
  131. }
  132. /* rs->genpoly[0] can never be zero */
  133. rs->genpoly[0] =
  134. rs->alpha_to[rs_modnn(rs,
  135. rs->index_of[rs->genpoly[0]] + root)];
  136. }
  137. /* convert rs->genpoly[] to index form for quicker encoding */
  138. for (i = 0; i <= nroots; i++)
  139. rs->genpoly[i] = rs->index_of[rs->genpoly[i]];
  140. return rs;
  141. /* Error exit */
  142. errpol:
  143. kfree(rs->genpoly);
  144. erridx:
  145. kfree(rs->index_of);
  146. erralp:
  147. kfree(rs->alpha_to);
  148. errrs:
  149. kfree(rs);
  150. return NULL;
  151. }
  152. /**
  153. * free_rs - Free the rs control structure, if it is no longer used
  154. * @rs: the control structure which is not longer used by the
  155. * caller
  156. */
  157. void free_rs(struct rs_control *rs)
  158. {
  159. mutex_lock(&rslistlock);
  160. rs->users--;
  161. if(!rs->users) {
  162. list_del(&rs->list);
  163. kfree(rs->alpha_to);
  164. kfree(rs->index_of);
  165. kfree(rs->genpoly);
  166. kfree(rs);
  167. }
  168. mutex_unlock(&rslistlock);
  169. }
  170. /**
  171. * init_rs_internal - Find a matching or allocate a new rs control structure
  172. * @symsize: the symbol size (number of bits)
  173. * @gfpoly: the extended Galois field generator polynomial coefficients,
  174. * with the 0th coefficient in the low order bit. The polynomial
  175. * must be primitive;
  176. * @gffunc: pointer to function to generate the next field element,
  177. * or the multiplicative identity element if given 0. Used
  178. * instead of gfpoly if gfpoly is 0
  179. * @fcr: the first consecutive root of the rs code generator polynomial
  180. * in index form
  181. * @prim: primitive element to generate polynomial roots
  182. * @nroots: RS code generator polynomial degree (number of roots)
  183. */
  184. static struct rs_control *init_rs_internal(int symsize, int gfpoly,
  185. int (*gffunc)(int), int fcr,
  186. int prim, int nroots)
  187. {
  188. struct list_head *tmp;
  189. struct rs_control *rs;
  190. /* Sanity checks */
  191. if (symsize < 1)
  192. return NULL;
  193. if (fcr < 0 || fcr >= (1<<symsize))
  194. return NULL;
  195. if (prim <= 0 || prim >= (1<<symsize))
  196. return NULL;
  197. if (nroots < 0 || nroots >= (1<<symsize))
  198. return NULL;
  199. mutex_lock(&rslistlock);
  200. /* Walk through the list and look for a matching entry */
  201. list_for_each(tmp, &rslist) {
  202. rs = list_entry(tmp, struct rs_control, list);
  203. if (symsize != rs->mm)
  204. continue;
  205. if (gfpoly != rs->gfpoly)
  206. continue;
  207. if (gffunc != rs->gffunc)
  208. continue;
  209. if (fcr != rs->fcr)
  210. continue;
  211. if (prim != rs->prim)
  212. continue;
  213. if (nroots != rs->nroots)
  214. continue;
  215. /* We have a matching one already */
  216. rs->users++;
  217. goto out;
  218. }
  219. /* Create a new one */
  220. rs = rs_init(symsize, gfpoly, gffunc, fcr, prim, nroots);
  221. if (rs) {
  222. rs->users = 1;
  223. list_add(&rs->list, &rslist);
  224. }
  225. out:
  226. mutex_unlock(&rslistlock);
  227. return rs;
  228. }
  229. /**
  230. * init_rs - Find a matching or allocate a new rs control structure
  231. * @symsize: the symbol size (number of bits)
  232. * @gfpoly: the extended Galois field generator polynomial coefficients,
  233. * with the 0th coefficient in the low order bit. The polynomial
  234. * must be primitive;
  235. * @fcr: the first consecutive root of the rs code generator polynomial
  236. * in index form
  237. * @prim: primitive element to generate polynomial roots
  238. * @nroots: RS code generator polynomial degree (number of roots)
  239. */
  240. struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim,
  241. int nroots)
  242. {
  243. return init_rs_internal(symsize, gfpoly, NULL, fcr, prim, nroots);
  244. }
  245. /**
  246. * init_rs_non_canonical - Find a matching or allocate a new rs control
  247. * structure, for fields with non-canonical
  248. * representation
  249. * @symsize: the symbol size (number of bits)
  250. * @gffunc: pointer to function to generate the next field element,
  251. * or the multiplicative identity element if given 0. Used
  252. * instead of gfpoly if gfpoly is 0
  253. * @fcr: the first consecutive root of the rs code generator polynomial
  254. * in index form
  255. * @prim: primitive element to generate polynomial roots
  256. * @nroots: RS code generator polynomial degree (number of roots)
  257. */
  258. struct rs_control *init_rs_non_canonical(int symsize, int (*gffunc)(int),
  259. int fcr, int prim, int nroots)
  260. {
  261. return init_rs_internal(symsize, 0, gffunc, fcr, prim, nroots);
  262. }
  263. #ifdef CONFIG_REED_SOLOMON_ENC8
  264. /**
  265. * encode_rs8 - Calculate the parity for data values (8bit data width)
  266. * @rs: the rs control structure
  267. * @data: data field of a given type
  268. * @len: data length
  269. * @par: parity data, must be initialized by caller (usually all 0)
  270. * @invmsk: invert data mask (will be xored on data)
  271. *
  272. * The parity uses a uint16_t data type to enable
  273. * symbol size > 8. The calling code must take care of encoding of the
  274. * syndrome result for storage itself.
  275. */
  276. int encode_rs8(struct rs_control *rs, uint8_t *data, int len, uint16_t *par,
  277. uint16_t invmsk)
  278. {
  279. #include "encode_rs.c"
  280. }
  281. EXPORT_SYMBOL_GPL(encode_rs8);
  282. #endif
  283. #ifdef CONFIG_REED_SOLOMON_DEC8
  284. /**
  285. * decode_rs8 - Decode codeword (8bit data width)
  286. * @rs: the rs control structure
  287. * @data: data field of a given type
  288. * @par: received parity data field
  289. * @len: data length
  290. * @s: syndrome data field (if NULL, syndrome is calculated)
  291. * @no_eras: number of erasures
  292. * @eras_pos: position of erasures, can be NULL
  293. * @invmsk: invert data mask (will be xored on data, not on parity!)
  294. * @corr: buffer to store correction bitmask on eras_pos
  295. *
  296. * The syndrome and parity uses a uint16_t data type to enable
  297. * symbol size > 8. The calling code must take care of decoding of the
  298. * syndrome result and the received parity before calling this code.
  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. */
  341. int decode_rs16(struct rs_control *rs, uint16_t *data, uint16_t *par, int len,
  342. uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk,
  343. uint16_t *corr)
  344. {
  345. #include "decode_rs.c"
  346. }
  347. EXPORT_SYMBOL_GPL(decode_rs16);
  348. #endif
  349. EXPORT_SYMBOL_GPL(init_rs);
  350. EXPORT_SYMBOL_GPL(init_rs_non_canonical);
  351. EXPORT_SYMBOL_GPL(free_rs);
  352. MODULE_LICENSE("GPL");
  353. MODULE_DESCRIPTION("Reed Solomon encoder/decoder");
  354. MODULE_AUTHOR("Phil Karn, Thomas Gleixner");