Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[RSLIB] Support non-canonical GF representations

For the CAFÉ NAND controller, we need to support non-canonical
representations of the Galois field. Allow the caller to provide its own
function for generating the field, and CAFÉ can use rslib instead of its
own implementation.

Signed-off-by: Segher Boessenkool <segher@kernel.crashing.org>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>

authored by

Segher Boessenkool and committed by
David Woodhouse
d7e5a546 7c96b7a1

+73 -15
+4
include/linux/rslib.h
··· 34 34 * @prim: Primitive element, index form 35 35 * @iprim: prim-th root of 1, index form 36 36 * @gfpoly: The primitive generator polynominal 37 + * @gffunc: Function to generate the field, if non-canonical representation 37 38 * @users: Users of this structure 38 39 * @list: List entry for the rs control list 39 40 */ ··· 49 48 int prim; 50 49 int iprim; 51 50 int gfpoly; 51 + int (*gffunc)(int); 52 52 int users; 53 53 struct list_head list; 54 54 }; ··· 79 77 /* Create or get a matching rs control structure */ 80 78 struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, 81 79 int nroots); 80 + struct rs_control *init_rs_non_canonical(int symsize, int (*func)(int), 81 + int fcr, int prim, int nroots); 82 82 83 83 /* Release a rs control structure */ 84 84 void free_rs(struct rs_control *rs);
+69 -15
lib/reed_solomon/reed_solomon.c
··· 56 56 * rs_init - Initialize a Reed-Solomon codec 57 57 * @symsize: symbol size, bits (1-8) 58 58 * @gfpoly: Field generator polynomial coefficients 59 + * @gffunc: Field generator function 59 60 * @fcr: first root of RS code generator polynomial, index form 60 61 * @prim: primitive element to generate polynomial roots 61 62 * @nroots: RS code generator polynomial degree (number of roots) ··· 64 63 * Allocate a control structure and the polynom arrays for faster 65 64 * en/decoding. Fill the arrays according to the given parameters. 66 65 */ 67 - static struct rs_control *rs_init(int symsize, int gfpoly, int fcr, 68 - int prim, int nroots) 66 + static struct rs_control *rs_init(int symsize, int gfpoly, int (*gffunc)(int), 67 + int fcr, int prim, int nroots) 69 68 { 70 69 struct rs_control *rs; 71 70 int i, j, sr, root, iprim; ··· 83 82 rs->prim = prim; 84 83 rs->nroots = nroots; 85 84 rs->gfpoly = gfpoly; 85 + rs->gffunc = gffunc; 86 86 87 87 /* Allocate the arrays */ 88 88 rs->alpha_to = kmalloc(sizeof(uint16_t) * (rs->nn + 1), GFP_KERNEL); ··· 101 99 /* Generate Galois field lookup tables */ 102 100 rs->index_of[0] = rs->nn; /* log(zero) = -inf */ 103 101 rs->alpha_to[rs->nn] = 0; /* alpha**-inf = 0 */ 104 - sr = 1; 105 - for (i = 0; i < rs->nn; i++) { 106 - rs->index_of[sr] = i; 107 - rs->alpha_to[i] = sr; 108 - sr <<= 1; 109 - if (sr & (1 << symsize)) 110 - sr ^= gfpoly; 111 - sr &= rs->nn; 102 + if (gfpoly) { 103 + sr = 1; 104 + for (i = 0; i < rs->nn; i++) { 105 + rs->index_of[sr] = i; 106 + rs->alpha_to[i] = sr; 107 + sr <<= 1; 108 + if (sr & (1 << symsize)) 109 + sr ^= gfpoly; 110 + sr &= rs->nn; 111 + } 112 + } else { 113 + sr = gffunc(0); 114 + for (i = 0; i < rs->nn; i++) { 115 + rs->index_of[sr] = i; 116 + rs->alpha_to[i] = sr; 117 + sr = gffunc(sr); 118 + } 112 119 } 113 120 /* If it's not primitive, exit */ 114 - if(sr != 1) 121 + if(sr != rs->alpha_to[0]) 115 122 goto errpol; 116 123 117 124 /* Find prim-th root of 1, used in decoding */ ··· 184 173 } 185 174 186 175 /** 187 - * init_rs - Find a matching or allocate a new rs control structure 176 + * init_rs_internal - Find a matching or allocate a new rs control structure 188 177 * @symsize: the symbol size (number of bits) 189 178 * @gfpoly: the extended Galois field generator polynomial coefficients, 190 179 * with the 0th coefficient in the low order bit. The polynomial 191 180 * must be primitive; 181 + * @gffunc: pointer to function to generate the next field element, 182 + * or the multiplicative identity element if given 0. Used 183 + * instead of gfpoly if gfpoly is 0 192 184 * @fcr: the first consecutive root of the rs code generator polynomial 193 185 * in index form 194 186 * @prim: primitive element to generate polynomial roots 195 187 * @nroots: RS code generator polynomial degree (number of roots) 196 188 */ 197 - struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, 198 - int nroots) 189 + static struct rs_control *init_rs_internal(int symsize, int gfpoly, 190 + int (*gffunc)(int), int fcr, 191 + int prim, int nroots) 199 192 { 200 193 struct list_head *tmp; 201 194 struct rs_control *rs; ··· 223 208 continue; 224 209 if (gfpoly != rs->gfpoly) 225 210 continue; 211 + if (gffunc != rs->gffunc) 212 + continue; 226 213 if (fcr != rs->fcr) 227 214 continue; 228 215 if (prim != rs->prim) ··· 237 220 } 238 221 239 222 /* Create a new one */ 240 - rs = rs_init(symsize, gfpoly, fcr, prim, nroots); 223 + rs = rs_init(symsize, gfpoly, gffunc, fcr, prim, nroots); 241 224 if (rs) { 242 225 rs->users = 1; 243 226 list_add(&rs->list, &rslist); ··· 245 228 out: 246 229 mutex_unlock(&rslistlock); 247 230 return rs; 231 + } 232 + 233 + /** 234 + * init_rs - Find a matching or allocate a new rs control structure 235 + * @symsize: the symbol size (number of bits) 236 + * @gfpoly: the extended Galois field generator polynomial coefficients, 237 + * with the 0th coefficient in the low order bit. The polynomial 238 + * must be primitive; 239 + * @fcr: the first consecutive root of the rs code generator polynomial 240 + * in index form 241 + * @prim: primitive element to generate polynomial roots 242 + * @nroots: RS code generator polynomial degree (number of roots) 243 + */ 244 + struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, 245 + int nroots) 246 + { 247 + return init_rs_internal(symsize, gfpoly, NULL, fcr, prim, nroots); 248 + } 249 + 250 + /** 251 + * init_rs_non_canonical - Find a matching or allocate a new rs control 252 + * structure, for fields with non-canonical 253 + * representation 254 + * @symsize: the symbol size (number of bits) 255 + * @gffunc: pointer to function to generate the next field element, 256 + * or the multiplicative identity element if given 0. Used 257 + * instead of gfpoly if gfpoly is 0 258 + * @fcr: the first consecutive root of the rs code generator polynomial 259 + * in index form 260 + * @prim: primitive element to generate polynomial roots 261 + * @nroots: RS code generator polynomial degree (number of roots) 262 + */ 263 + struct rs_control *init_rs_non_canonical(int symsize, int (*gffunc)(int), 264 + int fcr, int prim, int nroots) 265 + { 266 + return init_rs_internal(symsize, 0, gffunc, fcr, prim, nroots); 248 267 } 249 268 250 269 #ifdef CONFIG_REED_SOLOMON_ENC8 ··· 374 321 #endif 375 322 376 323 EXPORT_SYMBOL_GPL(init_rs); 324 + EXPORT_SYMBOL_GPL(init_rs_non_canonical); 377 325 EXPORT_SYMBOL_GPL(free_rs); 378 326 379 327 MODULE_LICENSE("GPL");