Messages in this thread Patch in this message | | | From | Zhang Boyang <> | Subject | [PATCH 2/2] rslib: Introduce init_rs16() | Date | Mon, 6 Jun 2022 18:19:01 +0800 |
| |
This patch introduces init_rs16(). This function creates a RS coder for exactly 16 bit symbols and it provides a special parameter `bool gfswab' which indicates whether to treat symbols as foreign endian. If `gfswab' is true, the coder will act as if all reads/writes to symbols is byte-swapped. This is useful, for example, when a big-endian machine want to decode symbols generated on a little-endian machine.
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com> --- include/linux/rslib.h | 24 +++++++++++++++++ lib/reed_solomon/reed_solomon.c | 48 ++++++++++++++++++++++++++++----- lib/reed_solomon/test_rslib.c | 31 ++++++++++++--------- 3 files changed, 84 insertions(+), 19 deletions(-)
diff --git a/include/linux/rslib.h b/include/linux/rslib.h index 238bb85243d3..bd38e1285997 100644 --- a/include/linux/rslib.h +++ b/include/linux/rslib.h @@ -28,6 +28,7 @@ * @iprim: prim-th root of 1, index form * @gfpoly: The primitive generator polynominal * @gffunc: Function to generate the field, if non-canonical representation + * @gfswab: Treat symbols as foreign endian, may be true only if mm = 16 * @users: Users of this structure * @list: List entry for the rs codec list */ @@ -43,6 +44,7 @@ struct rs_codec { int iprim; int gfpoly; int (*gffunc)(int); + bool gfswab; int users; struct list_head list; }; @@ -101,6 +103,28 @@ static inline struct rs_control *init_rs(int symsize, int gfpoly, int fcr, return init_rs_gfp(symsize, gfpoly, fcr, prim, nroots, GFP_KERNEL); } +struct rs_control *init_rs16_gfp(int gfpoly, bool gfswab, int fcr, int prim, + int nroots, gfp_t gfp); + +/** + * init_rs16 - Allocate rs control struct for 16 bit symbols + * @gfpoly: the extended Galois field generator polynomial coefficients, + * with the 0th coefficient in the low order bit. The polynomial + * must be primitive; + * @gfswab: Treat symbols as foreign endian + * @fcr: the first consecutive root of the rs code generator polynomial + * in index form + * @prim: primitive element to generate polynomial roots + * @nroots: RS code generator polynomial degree (number of roots) + * + * Allocations use GFP_KERNEL. + */ +static inline struct rs_control *init_rs16(int gfpoly, bool gfswab, int fcr, + int prim, int nroots) +{ + return init_rs16_gfp(gfpoly, gfswab, fcr, prim, nroots, GFP_KERNEL); +} + struct rs_control *init_rs_non_canonical(int symsize, int (*func)(int), int fcr, int prim, int nroots); diff --git a/lib/reed_solomon/reed_solomon.c b/lib/reed_solomon/reed_solomon.c index bb4f44c8edba..8f25b539e3a5 100644 --- a/lib/reed_solomon/reed_solomon.c +++ b/lib/reed_solomon/reed_solomon.c @@ -56,9 +56,10 @@ static DEFINE_MUTEX(rslistlock); /** * codec_init - Initialize a Reed-Solomon codec - * @symsize: symbol size, bits (1-8) + * @symsize: the symbol size (number of bits) * @gfpoly: Field generator polynomial coefficients * @gffunc: Field generator function + * @gfswab: Treat symbols as foreign endian, may be true only if symsize=16 * @fcr: first root of RS code generator polynomial, index form * @prim: primitive element to generate polynomial roots * @nroots: RS code generator polynomial degree (number of roots) @@ -67,7 +68,8 @@ static DEFINE_MUTEX(rslistlock); * Allocate a codec structure and the polynom arrays for faster * en/decoding. Fill the arrays according to the given parameters. */ -static struct rs_codec *codec_init(int symsize, int gfpoly, int (*gffunc)(int), +static struct rs_codec *codec_init(int symsize, + int gfpoly, int (*gffunc)(int), bool gfswab, int fcr, int prim, int nroots, gfp_t gfp) { int i, j, sr, root, iprim; @@ -86,6 +88,7 @@ static struct rs_codec *codec_init(int symsize, int gfpoly, int (*gffunc)(int), rs->nroots = nroots; rs->gfpoly = gfpoly; rs->gffunc = gffunc; + rs->gfswab = gfswab; /* Allocate the arrays */ rs->alpha_to = kmalloc_array(rs->nn + 1, sizeof(uint16_t), gfp); @@ -105,13 +108,16 @@ static struct rs_codec *codec_init(int symsize, int gfpoly, int (*gffunc)(int), rs->alpha_to[rs->nn] = 0; /* alpha**-inf = 0 */ if (gfpoly) { sr = 1; + sr = gfswab ? swab16(sr) : sr; for (i = 0; i < rs->nn; i++) { rs->index_of[sr] = i; rs->alpha_to[i] = sr; + sr = gfswab ? swab16(sr) : sr; sr <<= 1; if (sr & (1 << symsize)) sr ^= gfpoly; sr &= rs->nn; + sr = gfswab ? swab16(sr) : sr; } } else { sr = gffunc(0); @@ -204,6 +210,7 @@ EXPORT_SYMBOL_GPL(free_rs); * @gffunc: pointer to function to generate the next field element, * or the multiplicative identity element if given 0. Used * instead of gfpoly if gfpoly is 0 + * @gfswab: Treat symbols as foreign endian, may be true only if symsize=16 * @fcr: the first consecutive root of the rs code generator polynomial * in index form * @prim: primitive element to generate polynomial roots @@ -211,8 +218,9 @@ EXPORT_SYMBOL_GPL(free_rs); * @gfp: GFP_ flags for allocations */ static struct rs_control *init_rs_internal(int symsize, int gfpoly, - int (*gffunc)(int), int fcr, - int prim, int nroots, gfp_t gfp) + int (*gffunc)(int), bool gfswab, + int fcr, int prim, int nroots, + gfp_t gfp) { struct list_head *tmp; struct rs_control *rs; @@ -227,6 +235,8 @@ static struct rs_control *init_rs_internal(int symsize, int gfpoly, return NULL; if (nroots < 0 || nroots >= (1<<symsize)) return NULL; + if (gfswab && symsize != 16) + return NULL; /* * The decoder needs buffers in each control struct instance to @@ -250,6 +260,8 @@ static struct rs_control *init_rs_internal(int symsize, int gfpoly, continue; if (gffunc != cd->gffunc) continue; + if (gfswab != cd->gfswab) + continue; if (fcr != cd->fcr) continue; if (prim != cd->prim) @@ -263,7 +275,8 @@ static struct rs_control *init_rs_internal(int symsize, int gfpoly, } /* Create a new one */ - rs->codec = codec_init(symsize, gfpoly, gffunc, fcr, prim, nroots, gfp); + rs->codec = codec_init(symsize, gfpoly, gffunc, gfswab, + fcr, prim, nroots, gfp); if (!rs->codec) { kfree(rs); rs = NULL; @@ -288,10 +301,31 @@ static struct rs_control *init_rs_internal(int symsize, int gfpoly, struct rs_control *init_rs_gfp(int symsize, int gfpoly, int fcr, int prim, int nroots, gfp_t gfp) { - return init_rs_internal(symsize, gfpoly, NULL, fcr, prim, nroots, gfp); + return init_rs_internal(symsize, gfpoly, NULL, false, + fcr, prim, nroots, gfp); } EXPORT_SYMBOL_GPL(init_rs_gfp); +/** + * init_rs16_gfp - Allocate rs control struct for 16 bit symbols + * @gfpoly: the extended Galois field generator polynomial coefficients, + * with the 0th coefficient in the low order bit. The polynomial + * must be primitive; + * @gfswab: Treat symbols as foreign endian + * @fcr: the first consecutive root of the rs code generator polynomial + * in index form + * @prim: primitive element to generate polynomial roots + * @nroots: RS code generator polynomial degree (number of roots) + * @gfp: Memory allocation flags. + */ +struct rs_control *init_rs16_gfp(int gfpoly, bool gfswab, int fcr, int prim, + int nroots, gfp_t gfp) +{ + return init_rs_internal(16, gfpoly, NULL, gfswab, + fcr, prim, nroots, gfp); +} +EXPORT_SYMBOL_GPL(init_rs16_gfp); + /** * init_rs_non_canonical - Allocate rs control struct for fields with * non-canonical representation @@ -307,7 +341,7 @@ EXPORT_SYMBOL_GPL(init_rs_gfp); struct rs_control *init_rs_non_canonical(int symsize, int (*gffunc)(int), int fcr, int prim, int nroots) { - return init_rs_internal(symsize, 0, gffunc, fcr, prim, nroots, + return init_rs_internal(symsize, 0, gffunc, false, fcr, prim, nroots, GFP_KERNEL); } EXPORT_SYMBOL_GPL(init_rs_non_canonical); diff --git a/lib/reed_solomon/test_rslib.c b/lib/reed_solomon/test_rslib.c index d9d1c33aebda..f1eba21ed6d8 100644 --- a/lib/reed_solomon/test_rslib.c +++ b/lib/reed_solomon/test_rslib.c @@ -36,6 +36,7 @@ __param(int, bc, 1, "Test for correct behaviour beyond error correction capacity struct etab { int symsize; int genpoly; + bool byteswap; int fcs; int prim; int nroots; @@ -44,17 +45,18 @@ struct etab { /* List of codes to test */ static struct etab Tab[] = { - {2, 0x7, 1, 1, 1, 100000 }, - {3, 0xb, 1, 1, 2, 100000 }, - {3, 0xb, 1, 1, 3, 100000 }, - {3, 0xb, 2, 1, 4, 100000 }, - {4, 0x13, 1, 1, 4, 10000 }, - {5, 0x25, 1, 1, 6, 1000 }, - {6, 0x43, 3, 1, 8, 1000 }, - {7, 0x89, 1, 1, 14, 500 }, - {8, 0x11d, 1, 1, 30, 100 }, - {8, 0x187, 112, 11, 32, 100 }, - {9, 0x211, 1, 1, 33, 80 }, + {2, 0x7, false, 1, 1, 1, 100000 }, + {3, 0xb, false, 1, 1, 2, 100000 }, + {3, 0xb, false, 1, 1, 3, 100000 }, + {3, 0xb, false, 2, 1, 4, 100000 }, + {4, 0x13, false, 1, 1, 4, 10000 }, + {5, 0x25, false, 1, 1, 6, 1000 }, + {6, 0x43, false, 3, 1, 8, 1000 }, + {7, 0x89, false, 1, 1, 14, 500 }, + {8, 0x11d, false, 1, 1, 30, 100 }, + {8, 0x187, false, 112, 11, 32, 100 }, + {9, 0x211, false, 1, 1, 33, 80 }, + {16, 0x1002d, true, 1, 1, 33, 5 }, {0, 0, 0, 0, 0, 0}, }; @@ -450,7 +452,12 @@ static int run_exercise(struct etab *e) struct wspace *ws; int i; - rsc = init_rs(e->symsize, e->genpoly, e->fcs, e->prim, e->nroots); + if (e->symsize != 16) + rsc = init_rs(e->symsize, e->genpoly, + e->fcs, e->prim, e->nroots); + else + rsc = init_rs16(e->genpoly, e->byteswap, + e->fcs, e->prim, e->nroots); if (!rsc) return retval; -- 2.30.2
| |