VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300   1) // SPDX-License-Identifier: GPL-2.0
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300   2) /*
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300   3)  * Tests for Generic Reed Solomon encoder / decoder library
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300   4)  *
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300   5)  * Written by Ferdinand Blomqvist
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300   6)  * Based on previous work by Phil Karn, KA9Q
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300   7)  */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300   8) #include <linux/rslib.h>
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300   9) #include <linux/kernel.h>
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  10) #include <linux/module.h>
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  11) #include <linux/moduleparam.h>
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  12) #include <linux/random.h>
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  13) #include <linux/slab.h>
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  14) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  15) enum verbosity {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  16) 	V_SILENT,
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  17) 	V_PROGRESS,
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  18) 	V_CSUMMARY
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  19) };
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  20) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  21) enum method {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  22) 	CORR_BUFFER,
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  23) 	CALLER_SYNDROME,
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  24) 	IN_PLACE
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  25) };
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  26) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  27) #define __param(type, name, init, msg)		\
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  28) 	static type name = init;		\
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  29) 	module_param(name, type, 0444);		\
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  30) 	MODULE_PARM_DESC(name, msg)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  31) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  32) __param(int, v, V_PROGRESS, "Verbosity level");
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  33) __param(int, ewsc, 1, "Erasures without symbol corruption");
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  34) __param(int, bc, 1, "Test for correct behaviour beyond error correction capacity");
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  35) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  36) struct etab {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  37) 	int	symsize;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  38) 	int	genpoly;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  39) 	int	fcs;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  40) 	int	prim;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  41) 	int	nroots;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  42) 	int	ntrials;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  43) };
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  44) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  45) /* List of codes to test */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  46) static struct etab Tab[] = {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  47) 	{2,	0x7,	1,	1,	1,	100000	},
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  48) 	{3,	0xb,	1,	1,	2,	100000	},
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  49) 	{3,	0xb,	1,	1,	3,	100000	},
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  50) 	{3,	0xb,	2,	1,	4,	100000	},
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  51) 	{4,	0x13,	1,	1,	4,	10000	},
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  52) 	{5,	0x25,	1,	1,	6,	1000	},
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  53) 	{6,	0x43,	3,	1,	8,	1000	},
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  54) 	{7,	0x89,	1,	1,	14,	500	},
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  55) 	{8,	0x11d,	1,	1,	30,	100	},
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  56) 	{8,	0x187,	112,	11,	32,	100	},
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  57) 	{9,	0x211,	1,	1,	33,	80	},
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  58) 	{0, 0, 0, 0, 0, 0},
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  59) };
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  60) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  61) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  62) struct estat {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  63) 	int	dwrong;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  64) 	int	irv;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  65) 	int	wepos;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  66) 	int	nwords;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  67) };
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  68) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  69) struct bcstat {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  70) 	int	rfail;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  71) 	int	rsuccess;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  72) 	int	noncw;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  73) 	int	nwords;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  74) };
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  75) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  76) struct wspace {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  77) 	uint16_t	*c;		/* sent codeword */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  78) 	uint16_t	*r;		/* received word */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  79) 	uint16_t	*s;		/* syndrome */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  80) 	uint16_t	*corr;		/* correction buffer */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  81) 	int		*errlocs;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  82) 	int		*derrlocs;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  83) };
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  84) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  85) struct pad {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  86) 	int	mult;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  87) 	int	shift;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  88) };
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  89) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  90) static struct pad pad_coef[] = {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  91) 	{ 0, 0 },
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  92) 	{ 1, 2 },
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  93) 	{ 1, 1 },
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  94) 	{ 3, 2 },
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  95) 	{ 1, 0 },
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  96) };
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  97) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  98) static void free_ws(struct wspace *ws)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300  99) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 100) 	if (!ws)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 101) 		return;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 102) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 103) 	kfree(ws->errlocs);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 104) 	kfree(ws->c);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 105) 	kfree(ws);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 106) }
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 107) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 108) static struct wspace *alloc_ws(struct rs_codec *rs)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 109) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 110) 	int nroots = rs->nroots;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 111) 	struct wspace *ws;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 112) 	int nn = rs->nn;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 113) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 114) 	ws = kzalloc(sizeof(*ws), GFP_KERNEL);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 115) 	if (!ws)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 116) 		return NULL;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 117) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 118) 	ws->c = kmalloc_array(2 * (nn + nroots),
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 119) 				sizeof(uint16_t), GFP_KERNEL);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 120) 	if (!ws->c)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 121) 		goto err;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 122) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 123) 	ws->r = ws->c + nn;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 124) 	ws->s = ws->r + nn;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 125) 	ws->corr = ws->s + nroots;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 126) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 127) 	ws->errlocs = kmalloc_array(nn + nroots, sizeof(int), GFP_KERNEL);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 128) 	if (!ws->errlocs)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 129) 		goto err;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 130) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 131) 	ws->derrlocs = ws->errlocs + nn;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 132) 	return ws;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 133) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 134) err:
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 135) 	free_ws(ws);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 136) 	return NULL;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 137) }
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 138) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 139) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 140) /*
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 141)  * Generates a random codeword and stores it in c. Generates random errors and
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 142)  * erasures, and stores the random word with errors in r. Erasure positions are
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 143)  * stored in derrlocs, while errlocs has one of three values in every position:
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 144)  *
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 145)  * 0 if there is no error in this position;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 146)  * 1 if there is a symbol error in this position;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 147)  * 2 if there is an erasure without symbol corruption.
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 148)  *
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 149)  * Returns the number of corrupted symbols.
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 150)  */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 151) static int get_rcw_we(struct rs_control *rs, struct wspace *ws,
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 152) 			int len, int errs, int eras)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 153) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 154) 	int nroots = rs->codec->nroots;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 155) 	int *derrlocs = ws->derrlocs;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 156) 	int *errlocs = ws->errlocs;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 157) 	int dlen = len - nroots;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 158) 	int nn = rs->codec->nn;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 159) 	uint16_t *c = ws->c;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 160) 	uint16_t *r = ws->r;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 161) 	int errval;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 162) 	int errloc;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 163) 	int i;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 164) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 165) 	/* Load c with random data and encode */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 166) 	for (i = 0; i < dlen; i++)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 167) 		c[i] = prandom_u32() & nn;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 168) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 169) 	memset(c + dlen, 0, nroots * sizeof(*c));
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 170) 	encode_rs16(rs, c, dlen, c + dlen, 0);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 171) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 172) 	/* Make copyand add errors and erasures */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 173) 	memcpy(r, c, len * sizeof(*r));
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 174) 	memset(errlocs, 0, len * sizeof(*errlocs));
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 175) 	memset(derrlocs, 0, nroots * sizeof(*derrlocs));
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 176) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 177) 	/* Generating random errors */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 178) 	for (i = 0; i < errs; i++) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 179) 		do {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 180) 			/* Error value must be nonzero */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 181) 			errval = prandom_u32() & nn;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 182) 		} while (errval == 0);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 183) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 184) 		do {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 185) 			/* Must not choose the same location twice */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 186) 			errloc = prandom_u32() % len;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 187) 		} while (errlocs[errloc] != 0);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 188) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 189) 		errlocs[errloc] = 1;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 190) 		r[errloc] ^= errval;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 191) 	}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 192) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 193) 	/* Generating random erasures */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 194) 	for (i = 0; i < eras; i++) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 195) 		do {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 196) 			/* Must not choose the same location twice */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 197) 			errloc = prandom_u32() % len;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 198) 		} while (errlocs[errloc] != 0);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 199) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 200) 		derrlocs[i] = errloc;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 201) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 202) 		if (ewsc && (prandom_u32() & 1)) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 203) 			/* Erasure with the symbol intact */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 204) 			errlocs[errloc] = 2;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 205) 		} else {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 206) 			/* Erasure with corrupted symbol */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 207) 			do {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 208) 				/* Error value must be nonzero */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 209) 				errval = prandom_u32() & nn;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 210) 			} while (errval == 0);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 211) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 212) 			errlocs[errloc] = 1;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 213) 			r[errloc] ^= errval;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 214) 			errs++;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 215) 		}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 216) 	}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 217) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 218) 	return errs;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 219) }
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 220) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 221) static void fix_err(uint16_t *data, int nerrs, uint16_t *corr, int *errlocs)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 222) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 223) 	int i;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 224) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 225) 	for (i = 0; i < nerrs; i++)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 226) 		data[errlocs[i]] ^= corr[i];
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 227) }
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 228) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 229) static void compute_syndrome(struct rs_control *rsc, uint16_t *data,
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 230) 				int len, uint16_t *syn)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 231) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 232) 	struct rs_codec *rs = rsc->codec;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 233) 	uint16_t *alpha_to = rs->alpha_to;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 234) 	uint16_t *index_of = rs->index_of;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 235) 	int nroots = rs->nroots;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 236) 	int prim = rs->prim;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 237) 	int fcr = rs->fcr;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 238) 	int i, j;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 239) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 240) 	/* Calculating syndrome */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 241) 	for (i = 0; i < nroots; i++) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 242) 		syn[i] = data[0];
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 243) 		for (j = 1; j < len; j++) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 244) 			if (syn[i] == 0) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 245) 				syn[i] = data[j];
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 246) 			} else {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 247) 				syn[i] = data[j] ^
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 248) 					alpha_to[rs_modnn(rs, index_of[syn[i]]
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 249) 						+ (fcr + i) * prim)];
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 250) 			}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 251) 		}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 252) 	}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 253) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 254) 	/* Convert to index form */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 255) 	for (i = 0; i < nroots; i++)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 256) 		syn[i] = rs->index_of[syn[i]];
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 257) }
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 258) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 259) /* Test up to error correction capacity */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 260) static void test_uc(struct rs_control *rs, int len, int errs,
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 261) 		int eras, int trials, struct estat *stat,
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 262) 		struct wspace *ws, int method)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 263) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 264) 	int dlen = len - rs->codec->nroots;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 265) 	int *derrlocs = ws->derrlocs;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 266) 	int *errlocs = ws->errlocs;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 267) 	uint16_t *corr = ws->corr;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 268) 	uint16_t *c = ws->c;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 269) 	uint16_t *r = ws->r;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 270) 	uint16_t *s = ws->s;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 271) 	int derrs, nerrs;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 272) 	int i, j;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 273) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 274) 	for (j = 0; j < trials; j++) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 275) 		nerrs = get_rcw_we(rs, ws, len, errs, eras);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 276) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 277) 		switch (method) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 278) 		case CORR_BUFFER:
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 279) 			derrs = decode_rs16(rs, r, r + dlen, dlen,
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 280) 					NULL, eras, derrlocs, 0, corr);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 281) 			fix_err(r, derrs, corr, derrlocs);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 282) 			break;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 283) 		case CALLER_SYNDROME:
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 284) 			compute_syndrome(rs, r, len, s);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 285) 			derrs = decode_rs16(rs, NULL, NULL, dlen,
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 286) 					s, eras, derrlocs, 0, corr);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 287) 			fix_err(r, derrs, corr, derrlocs);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 288) 			break;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 289) 		case IN_PLACE:
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 290) 			derrs = decode_rs16(rs, r, r + dlen, dlen,
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 291) 					NULL, eras, derrlocs, 0, NULL);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 292) 			break;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 293) 		default:
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 294) 			continue;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 295) 		}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 296) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 297) 		if (derrs != nerrs)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 298) 			stat->irv++;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 299) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 300) 		if (method != IN_PLACE) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 301) 			for (i = 0; i < derrs; i++) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 302) 				if (errlocs[derrlocs[i]] != 1)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 303) 					stat->wepos++;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 304) 			}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 305) 		}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 306) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 307) 		if (memcmp(r, c, len * sizeof(*r)))
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 308) 			stat->dwrong++;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 309) 	}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 310) 	stat->nwords += trials;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 311) }
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 312) 
ede7c247abfae (YueHaibing          2019-07-02 14:18:47 +0800 313) static int ex_rs_helper(struct rs_control *rs, struct wspace *ws,
ede7c247abfae (YueHaibing          2019-07-02 14:18:47 +0800 314) 			int len, int trials, int method)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 315) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 316) 	static const char * const desc[] = {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 317) 		"Testing correction buffer interface...",
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 318) 		"Testing with caller provided syndrome...",
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 319) 		"Testing in-place interface..."
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 320) 	};
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 321) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 322) 	struct estat stat = {0, 0, 0, 0};
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 323) 	int nroots = rs->codec->nroots;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 324) 	int errs, eras, retval;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 325) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 326) 	if (v >= V_PROGRESS)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 327) 		pr_info("  %s\n", desc[method]);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 328) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 329) 	for (errs = 0; errs <= nroots / 2; errs++)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 330) 		for (eras = 0; eras <= nroots - 2 * errs; eras++)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 331) 			test_uc(rs, len, errs, eras, trials, &stat, ws, method);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 332) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 333) 	if (v >= V_CSUMMARY) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 334) 		pr_info("    Decodes wrong:        %d / %d\n",
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 335) 				stat.dwrong, stat.nwords);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 336) 		pr_info("    Wrong return value:   %d / %d\n",
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 337) 				stat.irv, stat.nwords);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 338) 		if (method != IN_PLACE)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 339) 			pr_info("    Wrong error position: %d\n", stat.wepos);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 340) 	}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 341) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 342) 	retval = stat.dwrong + stat.wepos + stat.irv;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 343) 	if (retval && v >= V_PROGRESS)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 344) 		pr_warn("    FAIL: %d decoding failures!\n", retval);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 345) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 346) 	return retval;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 347) }
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 348) 
ede7c247abfae (YueHaibing          2019-07-02 14:18:47 +0800 349) static int exercise_rs(struct rs_control *rs, struct wspace *ws,
ede7c247abfae (YueHaibing          2019-07-02 14:18:47 +0800 350) 		       int len, int trials)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 351) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 352) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 353) 	int retval = 0;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 354) 	int i;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 355) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 356) 	if (v >= V_PROGRESS)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 357) 		pr_info("Testing up to error correction capacity...\n");
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 358) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 359) 	for (i = 0; i <= IN_PLACE; i++)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 360) 		retval |= ex_rs_helper(rs, ws, len, trials, i);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 361) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 362) 	return retval;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 363) }
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 364) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 365) /* Tests for correct behaviour beyond error correction capacity */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 366) static void test_bc(struct rs_control *rs, int len, int errs,
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 367) 		int eras, int trials, struct bcstat *stat,
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 368) 		struct wspace *ws)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 369) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 370) 	int nroots = rs->codec->nroots;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 371) 	int dlen = len - nroots;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 372) 	int *derrlocs = ws->derrlocs;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 373) 	uint16_t *corr = ws->corr;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 374) 	uint16_t *r = ws->r;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 375) 	int derrs, j;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 376) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 377) 	for (j = 0; j < trials; j++) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 378) 		get_rcw_we(rs, ws, len, errs, eras);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 379) 		derrs = decode_rs16(rs, r, r + dlen, dlen,
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 380) 				NULL, eras, derrlocs, 0, corr);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 381) 		fix_err(r, derrs, corr, derrlocs);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 382) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 383) 		if (derrs >= 0) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 384) 			stat->rsuccess++;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 385) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 386) 			/*
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 387) 			 * We check that the returned word is actually a
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 388) 			 * codeword. The obious way to do this would be to
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 389) 			 * compute the syndrome, but we don't want to replicate
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 390) 			 * that code here. However, all the codes are in
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 391) 			 * systematic form, and therefore we can encode the
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 392) 			 * returned word, and see whether the parity changes or
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 393) 			 * not.
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 394) 			 */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 395) 			memset(corr, 0, nroots * sizeof(*corr));
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 396) 			encode_rs16(rs, r, dlen, corr, 0);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 397) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 398) 			if (memcmp(r + dlen, corr, nroots * sizeof(*corr)))
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 399) 				stat->noncw++;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 400) 		} else {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 401) 			stat->rfail++;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 402) 		}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 403) 	}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 404) 	stat->nwords += trials;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 405) }
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 406) 
ede7c247abfae (YueHaibing          2019-07-02 14:18:47 +0800 407) static int exercise_rs_bc(struct rs_control *rs, struct wspace *ws,
ede7c247abfae (YueHaibing          2019-07-02 14:18:47 +0800 408) 			  int len, int trials)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 409) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 410) 	struct bcstat stat = {0, 0, 0, 0};
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 411) 	int nroots = rs->codec->nroots;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 412) 	int errs, eras, cutoff;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 413) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 414) 	if (v >= V_PROGRESS)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 415) 		pr_info("Testing beyond error correction capacity...\n");
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 416) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 417) 	for (errs = 1; errs <= nroots; errs++) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 418) 		eras = nroots - 2 * errs + 1;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 419) 		if (eras < 0)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 420) 			eras = 0;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 421) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 422) 		cutoff = nroots <= len - errs ? nroots : len - errs;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 423) 		for (; eras <= cutoff; eras++)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 424) 			test_bc(rs, len, errs, eras, trials, &stat, ws);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 425) 	}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 426) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 427) 	if (v >= V_CSUMMARY) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 428) 		pr_info("  decoder gives up:        %d / %d\n",
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 429) 				stat.rfail, stat.nwords);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 430) 		pr_info("  decoder returns success: %d / %d\n",
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 431) 				stat.rsuccess, stat.nwords);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 432) 		pr_info("    not a codeword:        %d / %d\n",
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 433) 				stat.noncw, stat.rsuccess);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 434) 	}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 435) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 436) 	if (stat.noncw && v >= V_PROGRESS)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 437) 		pr_warn("    FAIL: %d silent failures!\n", stat.noncw);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 438) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 439) 	return stat.noncw;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 440) }
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 441) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 442) static int run_exercise(struct etab *e)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 443) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 444) 	int nn = (1 << e->symsize) - 1;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 445) 	int kk = nn - e->nroots;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 446) 	struct rs_control *rsc;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 447) 	int retval = -ENOMEM;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 448) 	int max_pad = kk - 1;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 449) 	int prev_pad = -1;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 450) 	struct wspace *ws;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 451) 	int i;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 452) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 453) 	rsc = init_rs(e->symsize, e->genpoly, e->fcs, e->prim, e->nroots);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 454) 	if (!rsc)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 455) 		return retval;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 456) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 457) 	ws = alloc_ws(rsc->codec);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 458) 	if (!ws)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 459) 		goto err;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 460) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 461) 	retval = 0;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 462) 	for (i = 0; i < ARRAY_SIZE(pad_coef); i++) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 463) 		int pad = (pad_coef[i].mult * max_pad) >> pad_coef[i].shift;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 464) 		int len = nn - pad;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 465) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 466) 		if (pad == prev_pad)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 467) 			continue;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 468) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 469) 		prev_pad = pad;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 470) 		if (v >= V_PROGRESS) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 471) 			pr_info("Testing (%d,%d)_%d code...\n",
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 472) 					len, kk - pad, nn + 1);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 473) 		}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 474) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 475) 		retval |= exercise_rs(rsc, ws, len, e->ntrials);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 476) 		if (bc)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 477) 			retval |= exercise_rs_bc(rsc, ws, len, e->ntrials);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 478) 	}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 479) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 480) 	free_ws(ws);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 481) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 482) err:
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 483) 	free_rs(rsc);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 484) 	return retval;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 485) }
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 486) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 487) static int __init test_rslib_init(void)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 488) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 489) 	int i, fail = 0;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 490) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 491) 	for (i = 0; Tab[i].symsize != 0 ; i++) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 492) 		int retval;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 493) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 494) 		retval = run_exercise(Tab + i);
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 495) 		if (retval < 0)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 496) 			return -ENOMEM;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 497) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 498) 		fail |= retval;
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 499) 	}
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 500) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 501) 	if (fail)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 502) 		pr_warn("rslib: test failed\n");
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 503) 	else
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 504) 		pr_info("rslib: test ok\n");
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 505) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 506) 	return -EAGAIN; /* Fail will directly unload the module */
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 507) }
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 508) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 509) static void __exit test_rslib_exit(void)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 510) {
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 511) }
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 512) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 513) module_init(test_rslib_init)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 514) module_exit(test_rslib_exit)
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 515) 
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 516) MODULE_LICENSE("GPL");
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 517) MODULE_AUTHOR("Ferdinand Blomqvist");
4b4f3accd8030 (Ferdinand Blomqvist 2019-06-20 17:10:33 +0300 518) MODULE_DESCRIPTION("Reed-Solomon library test");