Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 25d80be8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull reed-salomon library updates from Kees Cook:
 "Refactors rslib and callers to provide a per-instance allocation area
  instead of performing VLAs on the stack"

* tag 'rslib-v4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  rslib: Allocate decoder buffers to avoid VLAs
  mtd: rawnand: diskonchip: Allocate rs control per instance
  rslib: Split rs control struct
  rslib: Simplify error path
  rslib: Remove GPL boilerplate
  rslib: Add SPDX identifiers
  rslib: Cleanup top level comments
  rslib: Cleanup whitespace damage
  dm/verity_fec: Use GFP aware reed solomon init
  rslib: Add GFP aware init function
parents a74e0c4c 45888b40
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -570,7 +570,7 @@ static void *fec_rs_alloc(gfp_t gfp_mask, void *pool_data)
{
	struct dm_verity *v = (struct dm_verity *)pool_data;

	return init_rs(8, 0x11d, 0, 1, v->fec->roots);
	return init_rs_gfp(8, 0x11d, 0, 1, v->fec->roots, gfp_mask);
}

static void fec_rs_free(void *element, void *pool_data)
+4 −3
Original line number Diff line number Diff line
@@ -394,8 +394,9 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,

		for (i=0; i<8; i+=2) {
			uint32_t tmp = cafe_readl(cafe, NAND_ECC_SYN01 + (i*2));
			syn[i] = cafe->rs->index_of[tmp & 0xfff];
			syn[i+1] = cafe->rs->index_of[(tmp >> 16) & 0xfff];

			syn[i] = cafe->rs->codec->index_of[tmp & 0xfff];
			syn[i+1] = cafe->rs->codec->index_of[(tmp >> 16) & 0xfff];
		}

		n = decode_rs16(cafe->rs, NULL, NULL, 1367, syn, 0, pos, 0,
+31 −36
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ struct doc_priv {
	int curchip;
	int mh0_page;
	int mh1_page;
	struct rs_control *rs_decoder;
	struct mtd_info *nextdoc;

	/* Handle the last stage of initialization (BBT scan, partitioning) */
@@ -123,9 +124,6 @@ MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe
/* Number of symbols */
#define NN 1023

/* the Reed Solomon control structure */
static struct rs_control *rs_decoder;

/*
 * The HW decoder in the DoC ASIC's provides us a error syndrome,
 * which we must convert to a standard syndrome usable by the generic
@@ -140,6 +138,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
	int i, j, nerr, errpos[8];
	uint8_t parity;
	uint16_t ds[4], s[5], tmp, errval[8], syn[4];
	struct rs_codec *cd = rs->codec;

	memset(syn, 0, sizeof(syn));
	/* Convert the ecc bytes into words */
@@ -160,15 +159,15 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
	for (j = 1; j < NROOTS; j++) {
		if (ds[j] == 0)
			continue;
		tmp = rs->index_of[ds[j]];
		tmp = cd->index_of[ds[j]];
		for (i = 0; i < NROOTS; i++)
			s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)];
			s[i] ^= cd->alpha_to[rs_modnn(cd, tmp + (FCR + i) * j)];
	}

	/* Calc syn[i] = s[i] / alpha^(v + i) */
	for (i = 0; i < NROOTS; i++) {
		if (s[i])
			syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i));
			syn[i] = rs_modnn(cd, cd->index_of[s[i]] + (NN - FCR - i));
	}
	/* Call the decoder library */
	nerr = decode_rs16(rs, NULL, NULL, 1019, syn, 0, errpos, 0, errval);
@@ -930,7 +929,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,
				calc_ecc[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i);
		}

		ret = doc_ecc_decode(rs_decoder, dat, calc_ecc);
		ret = doc_ecc_decode(doc->rs_decoder, dat, calc_ecc);
		if (ret > 0)
			pr_err("doc200x_correct_data corrected %d errors\n",
			       ret);
@@ -1421,10 +1420,10 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd)

static int __init doc_probe(unsigned long physadr)
{
	struct nand_chip *nand = NULL;
	struct doc_priv *doc = NULL;
	unsigned char ChipID;
	struct mtd_info *mtd;
	struct nand_chip *nand;
	struct doc_priv *doc;
	void __iomem *virtadr;
	unsigned char save_control;
	unsigned char tmp, tmpb, tmpc;
@@ -1561,8 +1560,25 @@ static int __init doc_probe(unsigned long physadr)
		goto fail;
	}

	mtd			= nand_to_mtd(nand);

	/*
	 * Allocate a RS codec instance
	 *
	 * Symbolsize is 10 (bits)
	 * Primitve polynomial is x^10+x^3+1
	 * First consecutive root is 510
	 * Primitve element to generate roots = 1
	 * Generator polinomial degree = 4
	 */
	doc = (struct doc_priv *) (nand + 1);
	doc->rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS);
	if (!doc->rs_decoder) {
		pr_err("DiskOnChip: Could not create a RS codec\n");
		ret = -ENOMEM;
		goto fail;
	}

	mtd			= nand_to_mtd(nand);
	nand->bbt_td		= (struct nand_bbt_descr *) (doc + 1);
	nand->bbt_md		= nand->bbt_td + 1;

@@ -1612,7 +1628,6 @@ static int __init doc_probe(unsigned long physadr)
		   haven't yet added it.  This is handled without incident by
		   mtd_device_unregister, as far as I can tell. */
		nand_release(mtd);
		kfree(nand);
		goto fail;
	}

@@ -1625,6 +1640,9 @@ static int __init doc_probe(unsigned long physadr)
	   actually a DiskOnChip.  */
	WriteDOC(save_control, virtadr, DOCControl);
 fail:
	if (doc)
		free_rs(doc->rs_decoder);
	kfree(nand);
	iounmap(virtadr);

error_ioremap:
@@ -1647,6 +1665,7 @@ static void release_nanddoc(void)
		nand_release(mtd);
		iounmap(doc->virtadr);
		release_mem_region(doc->physadr, DOC_IOREMAP_LEN);
		free_rs(doc->rs_decoder);
		kfree(nand);
	}
}
@@ -1655,27 +1674,12 @@ static int __init init_nanddoc(void)
{
	int i, ret = 0;

	/* We could create the decoder on demand, if memory is a concern.
	 * This way we have it handy, if an error happens
	 *
	 * Symbolsize is 10 (bits)
	 * Primitve polynomial is x^10+x^3+1
	 * first consecutive root is 510
	 * primitve element to generate roots = 1
	 * generator polinomial degree = 4
	 */
	rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS);
	if (!rs_decoder) {
		pr_err("DiskOnChip: Could not create a RS decoder\n");
		return -ENOMEM;
	}

	if (doc_config_location) {
		pr_info("Using configured DiskOnChip probe address 0x%lx\n",
			doc_config_location);
		ret = doc_probe(doc_config_location);
		if (ret < 0)
			goto outerr;
			return ret;
	} else {
		for (i = 0; (doc_locations[i] != 0xffffffff); i++) {
			doc_probe(doc_locations[i]);
@@ -1686,11 +1690,7 @@ static int __init init_nanddoc(void)
	if (!doclist) {
		pr_info("No valid DiskOnChip devices found\n");
		ret = -ENODEV;
		goto outerr;
	}
	return 0;
 outerr:
	free_rs(rs_decoder);
	return ret;
}

@@ -1698,11 +1698,6 @@ static void __exit cleanup_nanddoc(void)
{
	/* Cleanup the nand/DoC resources */
	release_nanddoc();

	/* Free the reed solomon resources */
	if (rs_decoder) {
		free_rs(rs_decoder);
	}
}

module_init(init_nanddoc);
+48 −26
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * include/linux/rslib.h
 *
 * Overview:
 * Generic Reed Solomon encoder / decoder library
 *
 * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
 *
 * RS code lifted from reed solomon library written by Phil Karn
 * Copyright 2002 Phil Karn, KA9Q
 *
 * $Id: rslib.h,v 1.4 2005/11/07 11:14:52 gleixner Exp $
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#ifndef _RSLIB_H_
#define _RSLIB_H_

#include <linux/list.h>
#include <linux/types.h>	/* for gfp_t */
#include <linux/gfp.h>		/* for GFP_KERNEL */

/**
 * struct rs_control - rs control structure
 * struct rs_codec - rs codec data
 *
 * @mm:		Bits per symbol
 * @nn:		Symbols per block (= (1<<mm)-1)
@@ -36,9 +29,9 @@
 * @gfpoly:	The primitive generator polynominal
 * @gffunc:	Function to generate the field, if non-canonical representation
 * @users:	Users of this structure
 * @list:	List entry for the rs control list
 * @list:	List entry for the rs codec list
*/
struct rs_control {
struct rs_codec {
	int		mm;
	int		nn;
	uint16_t	*alpha_to;
@@ -54,6 +47,16 @@ struct rs_control {
	struct list_head list;
};

/**
 * struct rs_control - rs control structure per instance
 * @codec:	The codec used for this instance
 * @buffers:	Internal scratch buffers used in calls to decode_rs()
 */
struct rs_control {
	struct rs_codec	*codec;
	uint16_t	buffers[0];
};

/* General purpose RS codec, 8-bit data width, symbol width 1-15 bit  */
#ifdef CONFIG_REED_SOLOMON_ENC8
int encode_rs8(struct rs_control *rs, uint8_t *data, int len, uint16_t *par,
@@ -76,9 +79,28 @@ int decode_rs16(struct rs_control *rs, uint16_t *data, uint16_t *par, int len,
		uint16_t *corr);
#endif

/* Create or get a matching rs control structure */
struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim,
			   int nroots);
struct rs_control *init_rs_gfp(int symsize, int gfpoly, int fcr, int prim,
			       int nroots, gfp_t gfp);

/**
 * init_rs - Create a RS control struct and initialize it
 *  @symsize:	the symbol size (number of bits)
 *  @gfpoly:	the extended Galois field generator polynomial coefficients,
 *		with the 0th coefficient in the low order bit. The polynomial
 *		must be primitive;
 *  @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_rs(int symsize, int gfpoly, int fcr,
					 int prim, int nroots)
{
	return init_rs_gfp(symsize, gfpoly, fcr, prim, nroots, GFP_KERNEL);
}

struct rs_control *init_rs_non_canonical(int symsize, int (*func)(int),
					 int fcr, int prim, int nroots);

@@ -87,7 +109,7 @@ void free_rs(struct rs_control *rs);

/** modulo replacement for galois field arithmetics
 *
 *  @rs:	the rs control structure
 *  @rs:	Pointer to the RS codec
 *  @x:		the value to reduce
 *
 *  where
@@ -97,7 +119,7 @@ void free_rs(struct rs_control *rs);
 *  Simple arithmetic modulo would return a wrong result for values
 *  >= 3 * rs->nn
*/
static inline int rs_modnn(struct rs_control *rs, int x)
static inline int rs_modnn(struct rs_codec *rs, int x)
{
	while (x >= rs->nn) {
		x -= rs->nn;
+17 −17
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * lib/reed_solomon/decode_rs.c
 *
 * Overview:
 * Generic Reed Solomon encoder / decoder library
 *
 * Copyright 2002, Phil Karn, KA9Q
@@ -9,14 +7,10 @@
 *
 * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de)
 *
 * $Id: decode_rs.c,v 1.7 2005/11/07 11:14:59 gleixner Exp $
 *
 */

/* Generic data width independent code which is included by the
 * wrappers.
 * Generic data width independent code which is included by the wrappers.
 */
{
	struct rs_codec *rs = rsc->codec;
	int deg_lambda, el, deg_omega;
	int i, j, r, k, pad;
	int nn = rs->nn;
@@ -27,16 +21,22 @@
	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;
	/* Err+Eras Locator poly and syndrome poly The maximum value
	 * of nroots is 8. So the necessary stack size will be about
	 * 220 bytes max.
	 */
	uint16_t lambda[nroots + 1], syn[nroots];
	uint16_t b[nroots + 1], t[nroots + 1], omega[nroots + 1];
	uint16_t root[nroots], reg[nroots + 1], loc[nroots];
	int count = 0;
	uint16_t msk = (uint16_t) rs->nn;

	/*
	 * 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);

	/* Check length parameter for validity */
	pad = nn - nroots - len;
	BUG_ON(pad < 0 || pad >= nn);
Loading