reed_solomon.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * lib/reed_solomon/rslib.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. *
  55. * @symsize: symbol size, bits (1-8)
  56. * @gfpoly: Field generator polynomial coefficients
  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 fcr,
  65. 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. /* 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. sr = 1;
  94. for (i = 0; i < rs->nn; i++) {
  95. rs->index_of[sr] = i;
  96. rs->alpha_to[i] = sr;
  97. sr <<= 1;
  98. if (sr & (1 << symsize))
  99. sr ^= gfpoly;
  100. sr &= rs->nn;
  101. }
  102. /* If it's not primitive, exit */
  103. if(sr != 1)
  104. goto errpol;
  105. /* Find prim-th root of 1, used in decoding */
  106. for(iprim = 1; (iprim % prim) != 0; iprim += rs->nn);
  107. /* prim-th root of 1, index form */
  108. rs->iprim = iprim / prim;
  109. /* Form RS code generator polynomial from its roots */
  110. rs->genpoly[0] = 1;
  111. for (i = 0, root = fcr * prim; i < nroots; i++, root += prim) {
  112. rs->genpoly[i + 1] = 1;
  113. /* Multiply rs->genpoly[] by @**(root + x) */
  114. for (j = i; j > 0; j--) {
  115. if (rs->genpoly[j] != 0) {
  116. rs->genpoly[j] = rs->genpoly[j -1] ^
  117. rs->alpha_to[rs_modnn(rs,
  118. rs->index_of[rs->genpoly[j]] + root)];
  119. } else
  120. rs->genpoly[j] = rs->genpoly[j - 1];
  121. }
  122. /* rs->genpoly[0] can never be zero */
  123. rs->genpoly[0] =
  124. rs->alpha_to[rs_modnn(rs,
  125. rs->index_of[rs->genpoly[0]] + root)];
  126. }
  127. /* convert rs->genpoly[] to index form for quicker encoding */
  128. for (i = 0; i <= nroots; i++)
  129. rs->genpoly[i] = rs->index_of[rs->genpoly[i]];
  130. return rs;
  131. /* Error exit */
  132. errpol:
  133. kfree(rs->genpoly);
  134. erridx:
  135. kfree(rs->index_of);
  136. erralp:
  137. kfree(rs->alpha_to);
  138. errrs:
  139. kfree(rs);
  140. return NULL;
  141. }
  142. /**
  143. * free_rs - Free the rs control structure, if its not longer used
  144. *
  145. * @rs: the control structure which is not longer used by the
  146. * caller
  147. */
  148. void free_rs(struct rs_control *rs)
  149. {
  150. mutex_lock(&rslistlock);
  151. rs->users--;
  152. if(!rs->users) {
  153. list_del(&rs->list);
  154. kfree(rs->alpha_to);
  155. kfree(rs->index_of);
  156. kfree(rs->genpoly);
  157. kfree(rs);
  158. }
  159. mutex_unlock(&rslistlock);
  160. }
  161. /**
  162. * init_rs - Find a matching or allocate a new rs control structure
  163. *
  164. * @symsize: the symbol size (number of bits)
  165. * @gfpoly: the extended Galois field generator polynomial coefficients,
  166. * with the 0th coefficient in the low order bit. The polynomial
  167. * must be primitive;
  168. * @fcr: the first consecutive root of the rs code generator polynomial
  169. * in index form
  170. * @prim: primitive element to generate polynomial roots
  171. * @nroots: RS code generator polynomial degree (number of roots)
  172. */
  173. struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim,
  174. int nroots)
  175. {
  176. struct list_head *tmp;
  177. struct rs_control *rs;
  178. /* Sanity checks */
  179. if (symsize < 1)
  180. return NULL;
  181. if (fcr < 0 || fcr >= (1<<symsize))
  182. return NULL;
  183. if (prim <= 0 || prim >= (1<<symsize))
  184. return NULL;
  185. if (nroots < 0 || nroots >= (1<<symsize))
  186. return NULL;
  187. mutex_lock(&rslistlock);
  188. /* Walk through the list and look for a matching entry */
  189. list_for_each(tmp, &rslist) {
  190. rs = list_entry(tmp, struct rs_control, list);
  191. if (symsize != rs->mm)
  192. continue;
  193. if (gfpoly != rs->gfpoly)
  194. continue;
  195. if (fcr != rs->fcr)
  196. continue;
  197. if (prim != rs->prim)
  198. continue;
  199. if (nroots != rs->nroots)
  200. continue;
  201. /* We have a matching one already */
  202. rs->users++;
  203. goto out;
  204. }
  205. /* Create a new one */
  206. rs = rs_init(symsize, gfpoly, fcr, prim, nroots);
  207. if (rs) {
  208. rs->users = 1;
  209. list_add(&rs->list, &rslist);
  210. }
  211. out:
  212. mutex_unlock(&rslistlock);
  213. return rs;
  214. }
  215. #ifdef CONFIG_REED_SOLOMON_ENC8
  216. /**
  217. * encode_rs8 - Calculate the parity for data values (8bit data width)
  218. *
  219. * @rs: the rs control structure
  220. * @data: data field of a given type
  221. * @len: data length
  222. * @par: parity data, must be initialized by caller (usually all 0)
  223. * @invmsk: invert data mask (will be xored on data)
  224. *
  225. * The parity uses a uint16_t data type to enable
  226. * symbol size > 8. The calling code must take care of encoding of the
  227. * syndrome result for storage itself.
  228. */
  229. int encode_rs8(struct rs_control *rs, uint8_t *data, int len, uint16_t *par,
  230. uint16_t invmsk)
  231. {
  232. #include "encode_rs.c"
  233. }
  234. EXPORT_SYMBOL_GPL(encode_rs8);
  235. #endif
  236. #ifdef CONFIG_REED_SOLOMON_DEC8
  237. /**
  238. * decode_rs8 - Decode codeword (8bit data width)
  239. *
  240. * @rs: the rs control structure
  241. * @data: data field of a given type
  242. * @par: received parity data field
  243. * @len: data length
  244. * @s: syndrome data field (if NULL, syndrome is calculated)
  245. * @no_eras: number of erasures
  246. * @eras_pos: position of erasures, can be NULL
  247. * @invmsk: invert data mask (will be xored on data, not on parity!)
  248. * @corr: buffer to store correction bitmask on eras_pos
  249. *
  250. * The syndrome and parity uses a uint16_t data type to enable
  251. * symbol size > 8. The calling code must take care of decoding of the
  252. * syndrome result and the received parity before calling this code.
  253. */
  254. int decode_rs8(struct rs_control *rs, uint8_t *data, uint16_t *par, int len,
  255. uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk,
  256. uint16_t *corr)
  257. {
  258. #include "decode_rs.c"
  259. }
  260. EXPORT_SYMBOL_GPL(decode_rs8);
  261. #endif
  262. #ifdef CONFIG_REED_SOLOMON_ENC16
  263. /**
  264. * encode_rs16 - Calculate the parity for data values (16bit data width)
  265. *
  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, not on parity!)
  271. *
  272. * Each field in the data array contains up to symbol size bits of valid data.
  273. */
  274. int encode_rs16(struct rs_control *rs, uint16_t *data, int len, uint16_t *par,
  275. uint16_t invmsk)
  276. {
  277. #include "encode_rs.c"
  278. }
  279. EXPORT_SYMBOL_GPL(encode_rs16);
  280. #endif
  281. #ifdef CONFIG_REED_SOLOMON_DEC16
  282. /**
  283. * decode_rs16 - Decode codeword (16bit data width)
  284. *
  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. * Each field in the data array contains up to symbol size bits of valid data.
  296. */
  297. int decode_rs16(struct rs_control *rs, uint16_t *data, uint16_t *par, int len,
  298. uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk,
  299. uint16_t *corr)
  300. {
  301. #include "decode_rs.c"
  302. }
  303. EXPORT_SYMBOL_GPL(decode_rs16);
  304. #endif
  305. EXPORT_SYMBOL_GPL(init_rs);
  306. EXPORT_SYMBOL_GPL(free_rs);
  307. MODULE_LICENSE("GPL");
  308. MODULE_DESCRIPTION("Reed Solomon encoder/decoder");
  309. MODULE_AUTHOR("Phil Karn, Thomas Gleixner");