2018-04-22 16:23:50 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2005-11-07 11:15:37 +00:00
|
|
|
/*
|
2018-04-22 16:23:49 +00:00
|
|
|
* Generic Reed Solomon encoder / decoder library
|
2005-11-07 11:15:37 +00:00
|
|
|
*
|
2005-04-16 22:20:36 +00:00
|
|
|
* Copyright 2002, Phil Karn, KA9Q
|
|
|
|
* May be used under the terms of the GNU General Public License (GPL)
|
|
|
|
*
|
|
|
|
* Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de)
|
|
|
|
*
|
2018-04-22 16:23:49 +00:00
|
|
|
* Generic data width independent code which is included by the wrappers.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2005-11-07 11:15:37 +00:00
|
|
|
{
|
2018-04-22 16:23:53 +00:00
|
|
|
struct rs_codec *rs = rsc->codec;
|
2005-04-16 22:20:36 +00:00
|
|
|
int deg_lambda, el, deg_omega;
|
|
|
|
int i, j, r, k, pad;
|
|
|
|
int nn = rs->nn;
|
|
|
|
int nroots = rs->nroots;
|
|
|
|
int fcr = rs->fcr;
|
|
|
|
int prim = rs->prim;
|
|
|
|
int iprim = rs->iprim;
|
|
|
|
uint16_t *alpha_to = rs->alpha_to;
|
|
|
|
uint16_t *index_of = rs->index_of;
|
|
|
|
uint16_t u, q, tmp, num1, num2, den, discr_r, syn_error;
|
|
|
|
int count = 0;
|
rslib: Fix remaining decoder flaws
The decoder is flawed in the following ways:
- The decoder sometimes fails silently, i.e. it announces success but
returns a word that is not a codeword.
- The return value of the decoder is incoherent with respect to how
fixed erasures are counted. If the word to be decoded is a codeword,
then the decoder always returns zero even if some erasures are given.
On the other hand, if the word to be decoded contains errors, then the
number of erasures is always included in the count of corrected
symbols. So the decoder handles erasures without symbol corruption
inconsistently. This inconsistency probably doesn't affect anyone
using the decoder, but it is inconsistent with the documentation.
- The error positions returned in eras_pos include all erasures, but the
corrections are only set in the correction buffer if there actually is
a symbol error. So if there are erasures without symbol corruption,
then the correction buffer will contain errors (unless initialized to
zero before calling the decoder) or some values will be unset (if the
correction buffer is uninitialized).
- When correcting data in-place the decoder does not correct errors in
the parity. On the other hand, when returning the errors in correction
buffers, errors in the parity are included.
The respective fixed are:
- The syndrome of a codeword is always zero, and the syndrome is linear,
.i.e, S(x+e) = S(x) + S(e). So compute the syndrome for the error and
check whether it equals the syndrome of the received word. If it does,
then we have decoded to a valid codeword, otherwise we know that we
have an uncorrectable error. Fortunately, some unrecoverable error
conditions can be detected earlier in the decoding, which saves some
processing power.
- Simply count and return the number of symbols actually corrected.
- Make sure to only return positions where symbols were corrected.
- Also fix errors in parity when correcting in-place. Another option
would be to completely disregard errors in the parity, but then the
interface makes it impossible to write tests that test for silent
failures.
Other changes:
- Only fill the correction buffer and error position buffer if both of
them are provided. Otherwise correct in place. Previously the error
position buffer was always populated with the positions of the
corrected errors, irrespective of whether a correction buffer was
supplied or not. The rationale for this change is that there seems to
be two use cases for the decoder; correct in-place or use the
correction buffers. The caller does not need the positions of the
corrected errors when in-place correction is used. If in-place
correction is not used, then both the correction buffer and error
position buffer need to be populated.
Signed-off-by: Ferdinand Blomqvist <ferdinand.blomqvist@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20190620141039.9874-8-ferdinand.blomqvist@gmail.com
2019-06-20 14:10:39 +00:00
|
|
|
int num_corrected;
|
2005-04-16 22:20:36 +00:00
|
|
|
uint16_t msk = (uint16_t) rs->nn;
|
|
|
|
|
2018-04-22 16:23:55 +00:00
|
|
|
/*
|
|
|
|
* The decoder buffers are in the rs control struct. They are
|
|
|
|
* arrays sized [nroots + 1]
|
|
|
|
*/
|
|
|
|
uint16_t *lambda = rsc->buffers + RS_DECODE_LAMBDA * (nroots + 1);
|
|
|
|
uint16_t *syn = rsc->buffers + RS_DECODE_SYN * (nroots + 1);
|
|
|
|
uint16_t *b = rsc->buffers + RS_DECODE_B * (nroots + 1);
|
|
|
|
uint16_t *t = rsc->buffers + RS_DECODE_T * (nroots + 1);
|
|
|
|
uint16_t *omega = rsc->buffers + RS_DECODE_OMEGA * (nroots + 1);
|
|
|
|
uint16_t *root = rsc->buffers + RS_DECODE_ROOT * (nroots + 1);
|
|
|
|
uint16_t *reg = rsc->buffers + RS_DECODE_REG * (nroots + 1);
|
|
|
|
uint16_t *loc = rsc->buffers + RS_DECODE_LOC * (nroots + 1);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Check length parameter for validity */
|
|
|
|
pad = nn - nroots - len;
|
2019-06-20 14:10:35 +00:00
|
|
|
BUG_ON(pad < 0 || pad >= nn - nroots);
|
2005-11-07 11:15:37 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Does the caller provide the syndrome ? */
|
2019-06-20 14:10:37 +00:00
|
|
|
if (s != NULL) {
|
|
|
|
for (i = 0; i < nroots; i++) {
|
|
|
|
/* The syndrome is in index form,
|
|
|
|
* so nn represents zero
|
|
|
|
*/
|
|
|
|
if (s[i] != nn)
|
|
|
|
goto decode;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* syndrome is zero, no errors to correct */
|
|
|
|
return 0;
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* form the syndromes; i.e., evaluate data(x) at roots of
|
|
|
|
* g(x) */
|
|
|
|
for (i = 0; i < nroots; i++)
|
|
|
|
syn[i] = (((uint16_t) data[0]) ^ invmsk) & msk;
|
|
|
|
|
|
|
|
for (j = 1; j < len; j++) {
|
|
|
|
for (i = 0; i < nroots; i++) {
|
|
|
|
if (syn[i] == 0) {
|
2005-11-07 11:15:37 +00:00
|
|
|
syn[i] = (((uint16_t) data[j]) ^
|
2005-04-16 22:20:36 +00:00
|
|
|
invmsk) & msk;
|
|
|
|
} else {
|
|
|
|
syn[i] = ((((uint16_t) data[j]) ^
|
2005-11-07 11:15:37 +00:00
|
|
|
invmsk) & msk) ^
|
2005-04-16 22:20:36 +00:00
|
|
|
alpha_to[rs_modnn(rs, index_of[syn[i]] +
|
|
|
|
(fcr + i) * prim)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (j = 0; j < nroots; j++) {
|
|
|
|
for (i = 0; i < nroots; i++) {
|
|
|
|
if (syn[i] == 0) {
|
|
|
|
syn[i] = ((uint16_t) par[j]) & msk;
|
|
|
|
} else {
|
2005-11-07 11:15:37 +00:00
|
|
|
syn[i] = (((uint16_t) par[j]) & msk) ^
|
2005-04-16 22:20:36 +00:00
|
|
|
alpha_to[rs_modnn(rs, index_of[syn[i]] +
|
|
|
|
(fcr+i)*prim)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
s = syn;
|
|
|
|
|
|
|
|
/* Convert syndromes to index form, checking for nonzero condition */
|
|
|
|
syn_error = 0;
|
|
|
|
for (i = 0; i < nroots; i++) {
|
|
|
|
syn_error |= s[i];
|
|
|
|
s[i] = index_of[s[i]];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!syn_error) {
|
|
|
|
/* if syndrome is zero, data[] is a codeword and there are no
|
|
|
|
* errors to correct. So return data[] unmodified
|
|
|
|
*/
|
2019-06-20 14:10:36 +00:00
|
|
|
return 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
decode:
|
|
|
|
memset(&lambda[1], 0, nroots * sizeof(lambda[0]));
|
|
|
|
lambda[0] = 1;
|
|
|
|
|
|
|
|
if (no_eras > 0) {
|
|
|
|
/* Init lambda to be the erasure locator polynomial */
|
2005-11-07 11:15:37 +00:00
|
|
|
lambda[1] = alpha_to[rs_modnn(rs,
|
2019-06-20 14:10:34 +00:00
|
|
|
prim * (nn - 1 - (eras_pos[0] + pad)))];
|
2005-04-16 22:20:36 +00:00
|
|
|
for (i = 1; i < no_eras; i++) {
|
2019-06-20 14:10:34 +00:00
|
|
|
u = rs_modnn(rs, prim * (nn - 1 - (eras_pos[i] + pad)));
|
2005-04-16 22:20:36 +00:00
|
|
|
for (j = i + 1; j > 0; j--) {
|
|
|
|
tmp = index_of[lambda[j - 1]];
|
|
|
|
if (tmp != nn) {
|
2005-11-07 11:15:37 +00:00
|
|
|
lambda[j] ^=
|
2005-04-16 22:20:36 +00:00
|
|
|
alpha_to[rs_modnn(rs, u + tmp)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < nroots + 1; i++)
|
|
|
|
b[i] = index_of[lambda[i]];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Begin Berlekamp-Massey algorithm to determine error+erasure
|
|
|
|
* locator polynomial
|
|
|
|
*/
|
|
|
|
r = no_eras;
|
|
|
|
el = no_eras;
|
|
|
|
while (++r <= nroots) { /* r is the step number */
|
|
|
|
/* Compute discrepancy at the r-th step in poly-form */
|
|
|
|
discr_r = 0;
|
|
|
|
for (i = 0; i < r; i++) {
|
|
|
|
if ((lambda[i] != 0) && (s[r - i - 1] != nn)) {
|
2005-11-07 11:15:37 +00:00
|
|
|
discr_r ^=
|
|
|
|
alpha_to[rs_modnn(rs,
|
2005-04-16 22:20:36 +00:00
|
|
|
index_of[lambda[i]] +
|
|
|
|
s[r - i - 1])];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
discr_r = index_of[discr_r]; /* Index form */
|
|
|
|
if (discr_r == nn) {
|
|
|
|
/* 2 lines below: B(x) <-- x*B(x) */
|
|
|
|
memmove (&b[1], b, nroots * sizeof (b[0]));
|
|
|
|
b[0] = nn;
|
|
|
|
} else {
|
|
|
|
/* 7 lines below: T(x) <-- lambda(x)-discr_r*x*b(x) */
|
|
|
|
t[0] = lambda[0];
|
|
|
|
for (i = 0; i < nroots; i++) {
|
|
|
|
if (b[i] != nn) {
|
2005-11-07 11:15:37 +00:00
|
|
|
t[i + 1] = lambda[i + 1] ^
|
2005-04-16 22:20:36 +00:00
|
|
|
alpha_to[rs_modnn(rs, discr_r +
|
|
|
|
b[i])];
|
|
|
|
} else
|
|
|
|
t[i + 1] = lambda[i + 1];
|
|
|
|
}
|
|
|
|
if (2 * el <= r + no_eras - 1) {
|
|
|
|
el = r + no_eras - el;
|
|
|
|
/*
|
|
|
|
* 2 lines below: B(x) <-- inv(discr_r) *
|
|
|
|
* lambda(x)
|
|
|
|
*/
|
|
|
|
for (i = 0; i <= nroots; i++) {
|
|
|
|
b[i] = (lambda[i] == 0) ? nn :
|
|
|
|
rs_modnn(rs, index_of[lambda[i]]
|
|
|
|
- discr_r + nn);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* 2 lines below: B(x) <-- x*B(x) */
|
|
|
|
memmove(&b[1], b, nroots * sizeof(b[0]));
|
|
|
|
b[0] = nn;
|
|
|
|
}
|
|
|
|
memcpy(lambda, t, (nroots + 1) * sizeof(t[0]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Convert lambda to index form and compute deg(lambda(x)) */
|
|
|
|
deg_lambda = 0;
|
|
|
|
for (i = 0; i < nroots + 1; i++) {
|
|
|
|
lambda[i] = index_of[lambda[i]];
|
|
|
|
if (lambda[i] != nn)
|
|
|
|
deg_lambda = i;
|
|
|
|
}
|
rslib: Fix remaining decoder flaws
The decoder is flawed in the following ways:
- The decoder sometimes fails silently, i.e. it announces success but
returns a word that is not a codeword.
- The return value of the decoder is incoherent with respect to how
fixed erasures are counted. If the word to be decoded is a codeword,
then the decoder always returns zero even if some erasures are given.
On the other hand, if the word to be decoded contains errors, then the
number of erasures is always included in the count of corrected
symbols. So the decoder handles erasures without symbol corruption
inconsistently. This inconsistency probably doesn't affect anyone
using the decoder, but it is inconsistent with the documentation.
- The error positions returned in eras_pos include all erasures, but the
corrections are only set in the correction buffer if there actually is
a symbol error. So if there are erasures without symbol corruption,
then the correction buffer will contain errors (unless initialized to
zero before calling the decoder) or some values will be unset (if the
correction buffer is uninitialized).
- When correcting data in-place the decoder does not correct errors in
the parity. On the other hand, when returning the errors in correction
buffers, errors in the parity are included.
The respective fixed are:
- The syndrome of a codeword is always zero, and the syndrome is linear,
.i.e, S(x+e) = S(x) + S(e). So compute the syndrome for the error and
check whether it equals the syndrome of the received word. If it does,
then we have decoded to a valid codeword, otherwise we know that we
have an uncorrectable error. Fortunately, some unrecoverable error
conditions can be detected earlier in the decoding, which saves some
processing power.
- Simply count and return the number of symbols actually corrected.
- Make sure to only return positions where symbols were corrected.
- Also fix errors in parity when correcting in-place. Another option
would be to completely disregard errors in the parity, but then the
interface makes it impossible to write tests that test for silent
failures.
Other changes:
- Only fill the correction buffer and error position buffer if both of
them are provided. Otherwise correct in place. Previously the error
position buffer was always populated with the positions of the
corrected errors, irrespective of whether a correction buffer was
supplied or not. The rationale for this change is that there seems to
be two use cases for the decoder; correct in-place or use the
correction buffers. The caller does not need the positions of the
corrected errors when in-place correction is used. If in-place
correction is not used, then both the correction buffer and error
position buffer need to be populated.
Signed-off-by: Ferdinand Blomqvist <ferdinand.blomqvist@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20190620141039.9874-8-ferdinand.blomqvist@gmail.com
2019-06-20 14:10:39 +00:00
|
|
|
|
|
|
|
if (deg_lambda == 0) {
|
|
|
|
/*
|
|
|
|
* deg(lambda) is zero even though the syndrome is non-zero
|
|
|
|
* => uncorrectable error detected
|
|
|
|
*/
|
|
|
|
return -EBADMSG;
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Find roots of error+erasure locator polynomial by Chien search */
|
|
|
|
memcpy(®[1], &lambda[1], nroots * sizeof(reg[0]));
|
|
|
|
count = 0; /* Number of roots of lambda(x) */
|
|
|
|
for (i = 1, k = iprim - 1; i <= nn; i++, k = rs_modnn(rs, k + iprim)) {
|
|
|
|
q = 1; /* lambda[0] is always 0 */
|
|
|
|
for (j = deg_lambda; j > 0; j--) {
|
|
|
|
if (reg[j] != nn) {
|
|
|
|
reg[j] = rs_modnn(rs, reg[j] + j);
|
|
|
|
q ^= alpha_to[reg[j]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (q != 0)
|
|
|
|
continue; /* Not a root */
|
rslib: Fix remaining decoder flaws
The decoder is flawed in the following ways:
- The decoder sometimes fails silently, i.e. it announces success but
returns a word that is not a codeword.
- The return value of the decoder is incoherent with respect to how
fixed erasures are counted. If the word to be decoded is a codeword,
then the decoder always returns zero even if some erasures are given.
On the other hand, if the word to be decoded contains errors, then the
number of erasures is always included in the count of corrected
symbols. So the decoder handles erasures without symbol corruption
inconsistently. This inconsistency probably doesn't affect anyone
using the decoder, but it is inconsistent with the documentation.
- The error positions returned in eras_pos include all erasures, but the
corrections are only set in the correction buffer if there actually is
a symbol error. So if there are erasures without symbol corruption,
then the correction buffer will contain errors (unless initialized to
zero before calling the decoder) or some values will be unset (if the
correction buffer is uninitialized).
- When correcting data in-place the decoder does not correct errors in
the parity. On the other hand, when returning the errors in correction
buffers, errors in the parity are included.
The respective fixed are:
- The syndrome of a codeword is always zero, and the syndrome is linear,
.i.e, S(x+e) = S(x) + S(e). So compute the syndrome for the error and
check whether it equals the syndrome of the received word. If it does,
then we have decoded to a valid codeword, otherwise we know that we
have an uncorrectable error. Fortunately, some unrecoverable error
conditions can be detected earlier in the decoding, which saves some
processing power.
- Simply count and return the number of symbols actually corrected.
- Make sure to only return positions where symbols were corrected.
- Also fix errors in parity when correcting in-place. Another option
would be to completely disregard errors in the parity, but then the
interface makes it impossible to write tests that test for silent
failures.
Other changes:
- Only fill the correction buffer and error position buffer if both of
them are provided. Otherwise correct in place. Previously the error
position buffer was always populated with the positions of the
corrected errors, irrespective of whether a correction buffer was
supplied or not. The rationale for this change is that there seems to
be two use cases for the decoder; correct in-place or use the
correction buffers. The caller does not need the positions of the
corrected errors when in-place correction is used. If in-place
correction is not used, then both the correction buffer and error
position buffer need to be populated.
Signed-off-by: Ferdinand Blomqvist <ferdinand.blomqvist@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20190620141039.9874-8-ferdinand.blomqvist@gmail.com
2019-06-20 14:10:39 +00:00
|
|
|
|
|
|
|
if (k < pad) {
|
|
|
|
/* Impossible error location. Uncorrectable error. */
|
|
|
|
return -EBADMSG;
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* store root (index-form) and error location number */
|
|
|
|
root[count] = i;
|
|
|
|
loc[count] = k;
|
|
|
|
/* If we've already found max possible roots,
|
|
|
|
* abort the search to save time
|
|
|
|
*/
|
|
|
|
if (++count == deg_lambda)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (deg_lambda != count) {
|
|
|
|
/*
|
|
|
|
* deg(lambda) unequal to number of roots => uncorrectable
|
|
|
|
* error detected
|
|
|
|
*/
|
2019-06-20 14:10:36 +00:00
|
|
|
return -EBADMSG;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
|
|
|
|
* x**nroots). in index form. Also find deg(omega).
|
|
|
|
*/
|
|
|
|
deg_omega = deg_lambda - 1;
|
|
|
|
for (i = 0; i <= deg_omega; i++) {
|
|
|
|
tmp = 0;
|
|
|
|
for (j = i; j >= 0; j--) {
|
|
|
|
if ((s[i - j] != nn) && (lambda[j] != nn))
|
|
|
|
tmp ^=
|
|
|
|
alpha_to[rs_modnn(rs, s[i - j] + lambda[j])];
|
|
|
|
}
|
|
|
|
omega[i] = index_of[tmp];
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
|
|
|
|
* inv(X(l))**(fcr-1) and den = lambda_pr(inv(X(l))) all in poly-form
|
rslib: Fix remaining decoder flaws
The decoder is flawed in the following ways:
- The decoder sometimes fails silently, i.e. it announces success but
returns a word that is not a codeword.
- The return value of the decoder is incoherent with respect to how
fixed erasures are counted. If the word to be decoded is a codeword,
then the decoder always returns zero even if some erasures are given.
On the other hand, if the word to be decoded contains errors, then the
number of erasures is always included in the count of corrected
symbols. So the decoder handles erasures without symbol corruption
inconsistently. This inconsistency probably doesn't affect anyone
using the decoder, but it is inconsistent with the documentation.
- The error positions returned in eras_pos include all erasures, but the
corrections are only set in the correction buffer if there actually is
a symbol error. So if there are erasures without symbol corruption,
then the correction buffer will contain errors (unless initialized to
zero before calling the decoder) or some values will be unset (if the
correction buffer is uninitialized).
- When correcting data in-place the decoder does not correct errors in
the parity. On the other hand, when returning the errors in correction
buffers, errors in the parity are included.
The respective fixed are:
- The syndrome of a codeword is always zero, and the syndrome is linear,
.i.e, S(x+e) = S(x) + S(e). So compute the syndrome for the error and
check whether it equals the syndrome of the received word. If it does,
then we have decoded to a valid codeword, otherwise we know that we
have an uncorrectable error. Fortunately, some unrecoverable error
conditions can be detected earlier in the decoding, which saves some
processing power.
- Simply count and return the number of symbols actually corrected.
- Make sure to only return positions where symbols were corrected.
- Also fix errors in parity when correcting in-place. Another option
would be to completely disregard errors in the parity, but then the
interface makes it impossible to write tests that test for silent
failures.
Other changes:
- Only fill the correction buffer and error position buffer if both of
them are provided. Otherwise correct in place. Previously the error
position buffer was always populated with the positions of the
corrected errors, irrespective of whether a correction buffer was
supplied or not. The rationale for this change is that there seems to
be two use cases for the decoder; correct in-place or use the
correction buffers. The caller does not need the positions of the
corrected errors when in-place correction is used. If in-place
correction is not used, then both the correction buffer and error
position buffer need to be populated.
Signed-off-by: Ferdinand Blomqvist <ferdinand.blomqvist@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20190620141039.9874-8-ferdinand.blomqvist@gmail.com
2019-06-20 14:10:39 +00:00
|
|
|
* Note: we reuse the buffer for b to store the correction pattern
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
rslib: Fix remaining decoder flaws
The decoder is flawed in the following ways:
- The decoder sometimes fails silently, i.e. it announces success but
returns a word that is not a codeword.
- The return value of the decoder is incoherent with respect to how
fixed erasures are counted. If the word to be decoded is a codeword,
then the decoder always returns zero even if some erasures are given.
On the other hand, if the word to be decoded contains errors, then the
number of erasures is always included in the count of corrected
symbols. So the decoder handles erasures without symbol corruption
inconsistently. This inconsistency probably doesn't affect anyone
using the decoder, but it is inconsistent with the documentation.
- The error positions returned in eras_pos include all erasures, but the
corrections are only set in the correction buffer if there actually is
a symbol error. So if there are erasures without symbol corruption,
then the correction buffer will contain errors (unless initialized to
zero before calling the decoder) or some values will be unset (if the
correction buffer is uninitialized).
- When correcting data in-place the decoder does not correct errors in
the parity. On the other hand, when returning the errors in correction
buffers, errors in the parity are included.
The respective fixed are:
- The syndrome of a codeword is always zero, and the syndrome is linear,
.i.e, S(x+e) = S(x) + S(e). So compute the syndrome for the error and
check whether it equals the syndrome of the received word. If it does,
then we have decoded to a valid codeword, otherwise we know that we
have an uncorrectable error. Fortunately, some unrecoverable error
conditions can be detected earlier in the decoding, which saves some
processing power.
- Simply count and return the number of symbols actually corrected.
- Make sure to only return positions where symbols were corrected.
- Also fix errors in parity when correcting in-place. Another option
would be to completely disregard errors in the parity, but then the
interface makes it impossible to write tests that test for silent
failures.
Other changes:
- Only fill the correction buffer and error position buffer if both of
them are provided. Otherwise correct in place. Previously the error
position buffer was always populated with the positions of the
corrected errors, irrespective of whether a correction buffer was
supplied or not. The rationale for this change is that there seems to
be two use cases for the decoder; correct in-place or use the
correction buffers. The caller does not need the positions of the
corrected errors when in-place correction is used. If in-place
correction is not used, then both the correction buffer and error
position buffer need to be populated.
Signed-off-by: Ferdinand Blomqvist <ferdinand.blomqvist@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20190620141039.9874-8-ferdinand.blomqvist@gmail.com
2019-06-20 14:10:39 +00:00
|
|
|
num_corrected = 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
for (j = count - 1; j >= 0; j--) {
|
|
|
|
num1 = 0;
|
|
|
|
for (i = deg_omega; i >= 0; i--) {
|
|
|
|
if (omega[i] != nn)
|
2005-11-07 11:15:37 +00:00
|
|
|
num1 ^= alpha_to[rs_modnn(rs, omega[i] +
|
2005-04-16 22:20:36 +00:00
|
|
|
i * root[j])];
|
|
|
|
}
|
rslib: Fix remaining decoder flaws
The decoder is flawed in the following ways:
- The decoder sometimes fails silently, i.e. it announces success but
returns a word that is not a codeword.
- The return value of the decoder is incoherent with respect to how
fixed erasures are counted. If the word to be decoded is a codeword,
then the decoder always returns zero even if some erasures are given.
On the other hand, if the word to be decoded contains errors, then the
number of erasures is always included in the count of corrected
symbols. So the decoder handles erasures without symbol corruption
inconsistently. This inconsistency probably doesn't affect anyone
using the decoder, but it is inconsistent with the documentation.
- The error positions returned in eras_pos include all erasures, but the
corrections are only set in the correction buffer if there actually is
a symbol error. So if there are erasures without symbol corruption,
then the correction buffer will contain errors (unless initialized to
zero before calling the decoder) or some values will be unset (if the
correction buffer is uninitialized).
- When correcting data in-place the decoder does not correct errors in
the parity. On the other hand, when returning the errors in correction
buffers, errors in the parity are included.
The respective fixed are:
- The syndrome of a codeword is always zero, and the syndrome is linear,
.i.e, S(x+e) = S(x) + S(e). So compute the syndrome for the error and
check whether it equals the syndrome of the received word. If it does,
then we have decoded to a valid codeword, otherwise we know that we
have an uncorrectable error. Fortunately, some unrecoverable error
conditions can be detected earlier in the decoding, which saves some
processing power.
- Simply count and return the number of symbols actually corrected.
- Make sure to only return positions where symbols were corrected.
- Also fix errors in parity when correcting in-place. Another option
would be to completely disregard errors in the parity, but then the
interface makes it impossible to write tests that test for silent
failures.
Other changes:
- Only fill the correction buffer and error position buffer if both of
them are provided. Otherwise correct in place. Previously the error
position buffer was always populated with the positions of the
corrected errors, irrespective of whether a correction buffer was
supplied or not. The rationale for this change is that there seems to
be two use cases for the decoder; correct in-place or use the
correction buffers. The caller does not need the positions of the
corrected errors when in-place correction is used. If in-place
correction is not used, then both the correction buffer and error
position buffer need to be populated.
Signed-off-by: Ferdinand Blomqvist <ferdinand.blomqvist@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20190620141039.9874-8-ferdinand.blomqvist@gmail.com
2019-06-20 14:10:39 +00:00
|
|
|
|
|
|
|
if (num1 == 0) {
|
|
|
|
/* Nothing to correct at this position */
|
|
|
|
b[j] = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
num2 = alpha_to[rs_modnn(rs, root[j] * (fcr - 1) + nn)];
|
|
|
|
den = 0;
|
|
|
|
|
|
|
|
/* lambda[i+1] for i even is the formal derivative
|
|
|
|
* lambda_pr of lambda[i] */
|
|
|
|
for (i = min(deg_lambda, nroots - 1) & ~1; i >= 0; i -= 2) {
|
|
|
|
if (lambda[i + 1] != nn) {
|
2005-11-07 11:15:37 +00:00
|
|
|
den ^= alpha_to[rs_modnn(rs, lambda[i + 1] +
|
2005-04-16 22:20:36 +00:00
|
|
|
i * root[j])];
|
|
|
|
}
|
|
|
|
}
|
rslib: Fix remaining decoder flaws
The decoder is flawed in the following ways:
- The decoder sometimes fails silently, i.e. it announces success but
returns a word that is not a codeword.
- The return value of the decoder is incoherent with respect to how
fixed erasures are counted. If the word to be decoded is a codeword,
then the decoder always returns zero even if some erasures are given.
On the other hand, if the word to be decoded contains errors, then the
number of erasures is always included in the count of corrected
symbols. So the decoder handles erasures without symbol corruption
inconsistently. This inconsistency probably doesn't affect anyone
using the decoder, but it is inconsistent with the documentation.
- The error positions returned in eras_pos include all erasures, but the
corrections are only set in the correction buffer if there actually is
a symbol error. So if there are erasures without symbol corruption,
then the correction buffer will contain errors (unless initialized to
zero before calling the decoder) or some values will be unset (if the
correction buffer is uninitialized).
- When correcting data in-place the decoder does not correct errors in
the parity. On the other hand, when returning the errors in correction
buffers, errors in the parity are included.
The respective fixed are:
- The syndrome of a codeword is always zero, and the syndrome is linear,
.i.e, S(x+e) = S(x) + S(e). So compute the syndrome for the error and
check whether it equals the syndrome of the received word. If it does,
then we have decoded to a valid codeword, otherwise we know that we
have an uncorrectable error. Fortunately, some unrecoverable error
conditions can be detected earlier in the decoding, which saves some
processing power.
- Simply count and return the number of symbols actually corrected.
- Make sure to only return positions where symbols were corrected.
- Also fix errors in parity when correcting in-place. Another option
would be to completely disregard errors in the parity, but then the
interface makes it impossible to write tests that test for silent
failures.
Other changes:
- Only fill the correction buffer and error position buffer if both of
them are provided. Otherwise correct in place. Previously the error
position buffer was always populated with the positions of the
corrected errors, irrespective of whether a correction buffer was
supplied or not. The rationale for this change is that there seems to
be two use cases for the decoder; correct in-place or use the
correction buffers. The caller does not need the positions of the
corrected errors when in-place correction is used. If in-place
correction is not used, then both the correction buffer and error
position buffer need to be populated.
Signed-off-by: Ferdinand Blomqvist <ferdinand.blomqvist@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20190620141039.9874-8-ferdinand.blomqvist@gmail.com
2019-06-20 14:10:39 +00:00
|
|
|
|
|
|
|
b[j] = alpha_to[rs_modnn(rs, index_of[num1] +
|
|
|
|
index_of[num2] +
|
|
|
|
nn - index_of[den])];
|
|
|
|
num_corrected++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We compute the syndrome of the 'error' and check that it matches
|
|
|
|
* the syndrome of the received word
|
|
|
|
*/
|
|
|
|
for (i = 0; i < nroots; i++) {
|
|
|
|
tmp = 0;
|
|
|
|
for (j = 0; j < count; j++) {
|
|
|
|
if (b[j] == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
k = (fcr + i) * prim * (nn-loc[j]-1);
|
|
|
|
tmp ^= alpha_to[rs_modnn(rs, index_of[b[j]] + k)];
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
rslib: Fix remaining decoder flaws
The decoder is flawed in the following ways:
- The decoder sometimes fails silently, i.e. it announces success but
returns a word that is not a codeword.
- The return value of the decoder is incoherent with respect to how
fixed erasures are counted. If the word to be decoded is a codeword,
then the decoder always returns zero even if some erasures are given.
On the other hand, if the word to be decoded contains errors, then the
number of erasures is always included in the count of corrected
symbols. So the decoder handles erasures without symbol corruption
inconsistently. This inconsistency probably doesn't affect anyone
using the decoder, but it is inconsistent with the documentation.
- The error positions returned in eras_pos include all erasures, but the
corrections are only set in the correction buffer if there actually is
a symbol error. So if there are erasures without symbol corruption,
then the correction buffer will contain errors (unless initialized to
zero before calling the decoder) or some values will be unset (if the
correction buffer is uninitialized).
- When correcting data in-place the decoder does not correct errors in
the parity. On the other hand, when returning the errors in correction
buffers, errors in the parity are included.
The respective fixed are:
- The syndrome of a codeword is always zero, and the syndrome is linear,
.i.e, S(x+e) = S(x) + S(e). So compute the syndrome for the error and
check whether it equals the syndrome of the received word. If it does,
then we have decoded to a valid codeword, otherwise we know that we
have an uncorrectable error. Fortunately, some unrecoverable error
conditions can be detected earlier in the decoding, which saves some
processing power.
- Simply count and return the number of symbols actually corrected.
- Make sure to only return positions where symbols were corrected.
- Also fix errors in parity when correcting in-place. Another option
would be to completely disregard errors in the parity, but then the
interface makes it impossible to write tests that test for silent
failures.
Other changes:
- Only fill the correction buffer and error position buffer if both of
them are provided. Otherwise correct in place. Previously the error
position buffer was always populated with the positions of the
corrected errors, irrespective of whether a correction buffer was
supplied or not. The rationale for this change is that there seems to
be two use cases for the decoder; correct in-place or use the
correction buffers. The caller does not need the positions of the
corrected errors when in-place correction is used. If in-place
correction is not used, then both the correction buffer and error
position buffer need to be populated.
Signed-off-by: Ferdinand Blomqvist <ferdinand.blomqvist@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20190620141039.9874-8-ferdinand.blomqvist@gmail.com
2019-06-20 14:10:39 +00:00
|
|
|
|
|
|
|
if (tmp != alpha_to[s[i]])
|
|
|
|
return -EBADMSG;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
rslib: Fix remaining decoder flaws
The decoder is flawed in the following ways:
- The decoder sometimes fails silently, i.e. it announces success but
returns a word that is not a codeword.
- The return value of the decoder is incoherent with respect to how
fixed erasures are counted. If the word to be decoded is a codeword,
then the decoder always returns zero even if some erasures are given.
On the other hand, if the word to be decoded contains errors, then the
number of erasures is always included in the count of corrected
symbols. So the decoder handles erasures without symbol corruption
inconsistently. This inconsistency probably doesn't affect anyone
using the decoder, but it is inconsistent with the documentation.
- The error positions returned in eras_pos include all erasures, but the
corrections are only set in the correction buffer if there actually is
a symbol error. So if there are erasures without symbol corruption,
then the correction buffer will contain errors (unless initialized to
zero before calling the decoder) or some values will be unset (if the
correction buffer is uninitialized).
- When correcting data in-place the decoder does not correct errors in
the parity. On the other hand, when returning the errors in correction
buffers, errors in the parity are included.
The respective fixed are:
- The syndrome of a codeword is always zero, and the syndrome is linear,
.i.e, S(x+e) = S(x) + S(e). So compute the syndrome for the error and
check whether it equals the syndrome of the received word. If it does,
then we have decoded to a valid codeword, otherwise we know that we
have an uncorrectable error. Fortunately, some unrecoverable error
conditions can be detected earlier in the decoding, which saves some
processing power.
- Simply count and return the number of symbols actually corrected.
- Make sure to only return positions where symbols were corrected.
- Also fix errors in parity when correcting in-place. Another option
would be to completely disregard errors in the parity, but then the
interface makes it impossible to write tests that test for silent
failures.
Other changes:
- Only fill the correction buffer and error position buffer if both of
them are provided. Otherwise correct in place. Previously the error
position buffer was always populated with the positions of the
corrected errors, irrespective of whether a correction buffer was
supplied or not. The rationale for this change is that there seems to
be two use cases for the decoder; correct in-place or use the
correction buffers. The caller does not need the positions of the
corrected errors when in-place correction is used. If in-place
correction is not used, then both the correction buffer and error
position buffer need to be populated.
Signed-off-by: Ferdinand Blomqvist <ferdinand.blomqvist@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20190620141039.9874-8-ferdinand.blomqvist@gmail.com
2019-06-20 14:10:39 +00:00
|
|
|
/*
|
|
|
|
* Store the error correction pattern, if a
|
|
|
|
* correction buffer is available
|
|
|
|
*/
|
|
|
|
if (corr && eras_pos) {
|
|
|
|
j = 0;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
if (b[i]) {
|
|
|
|
corr[j] = b[i];
|
|
|
|
eras_pos[j++] = loc[i] - pad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (data && par) {
|
|
|
|
/* Apply error to data and parity */
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
if (loc[i] < (nn - nroots))
|
|
|
|
data[loc[i] - pad] ^= b[i];
|
|
|
|
else
|
|
|
|
par[loc[i] - pad - len] ^= b[i];
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
rslib: Fix remaining decoder flaws
The decoder is flawed in the following ways:
- The decoder sometimes fails silently, i.e. it announces success but
returns a word that is not a codeword.
- The return value of the decoder is incoherent with respect to how
fixed erasures are counted. If the word to be decoded is a codeword,
then the decoder always returns zero even if some erasures are given.
On the other hand, if the word to be decoded contains errors, then the
number of erasures is always included in the count of corrected
symbols. So the decoder handles erasures without symbol corruption
inconsistently. This inconsistency probably doesn't affect anyone
using the decoder, but it is inconsistent with the documentation.
- The error positions returned in eras_pos include all erasures, but the
corrections are only set in the correction buffer if there actually is
a symbol error. So if there are erasures without symbol corruption,
then the correction buffer will contain errors (unless initialized to
zero before calling the decoder) or some values will be unset (if the
correction buffer is uninitialized).
- When correcting data in-place the decoder does not correct errors in
the parity. On the other hand, when returning the errors in correction
buffers, errors in the parity are included.
The respective fixed are:
- The syndrome of a codeword is always zero, and the syndrome is linear,
.i.e, S(x+e) = S(x) + S(e). So compute the syndrome for the error and
check whether it equals the syndrome of the received word. If it does,
then we have decoded to a valid codeword, otherwise we know that we
have an uncorrectable error. Fortunately, some unrecoverable error
conditions can be detected earlier in the decoding, which saves some
processing power.
- Simply count and return the number of symbols actually corrected.
- Make sure to only return positions where symbols were corrected.
- Also fix errors in parity when correcting in-place. Another option
would be to completely disregard errors in the parity, but then the
interface makes it impossible to write tests that test for silent
failures.
Other changes:
- Only fill the correction buffer and error position buffer if both of
them are provided. Otherwise correct in place. Previously the error
position buffer was always populated with the positions of the
corrected errors, irrespective of whether a correction buffer was
supplied or not. The rationale for this change is that there seems to
be two use cases for the decoder; correct in-place or use the
correction buffers. The caller does not need the positions of the
corrected errors when in-place correction is used. If in-place
correction is not used, then both the correction buffer and error
position buffer need to be populated.
Signed-off-by: Ferdinand Blomqvist <ferdinand.blomqvist@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20190620141039.9874-8-ferdinand.blomqvist@gmail.com
2019-06-20 14:10:39 +00:00
|
|
|
return num_corrected;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|