Skip to content

Commit

Permalink
mtd: nand: ecc-bch: Update the prototypes to be more generic
Browse files Browse the repository at this point in the history
These functions must be usable by the main NAND core, so their names
must be technology-agnostic as well as the parameters. Hence, we pass
a generic nand_device instead of a raw nand_chip structure.

As it seems that changing the raw NAND functions to always pass a
generic NAND device is a lost of time, we prefer to create dedicated
raw NAND wrappers that will be useful in the near future to do the
translation.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20200929230124.31491-8-miquel.raynal@bootlin.com
  • Loading branch information
Miquel Raynal committed Nov 30, 2020
1 parent 127aae6 commit ea146d7
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 67 deletions.
47 changes: 27 additions & 20 deletions drivers/mtd/nand/ecc-sw-bch.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/bitops.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand-ecc-sw-bch.h>
#include <linux/bch.h>

Expand All @@ -29,14 +30,15 @@ struct nand_bch_control {
};

/**
* nand_bch_calcuate_ecc - Calculate the ECC corresponding to a data block
* @chip: NAND chip object
* nand_ecc_sw_bch_calculate - Calculate the ECC corresponding to a data block
* @nand: NAND device
* @buf: Input buffer with raw data
* @code: Output buffer with ECC
*/
int nand_bch_calculate_ecc(struct nand_chip *chip, const unsigned char *buf,
unsigned char *code)
int nand_ecc_sw_bch_calculate(struct nand_device *nand,
const unsigned char *buf, unsigned char *code)
{
struct nand_chip *chip = mtd_to_nand(nanddev_to_mtd(nand));
struct nand_bch_control *nbc = chip->ecc.priv;
unsigned int i;

Expand All @@ -49,20 +51,21 @@ int nand_bch_calculate_ecc(struct nand_chip *chip, const unsigned char *buf,

return 0;
}
EXPORT_SYMBOL(nand_bch_calculate_ecc);
EXPORT_SYMBOL(nand_ecc_sw_bch_calculate);

/**
* nand_bch_correct_data - Detect, correct and report bit error(s)
* @chip: NAND chip object
* nand_ecc_sw_bch_correct - Detect, correct and report bit error(s)
* @nand: NAND device
* @buf: Raw data read from the chip
* @read_ecc: ECC bytes from the chip
* @calc_ecc: ECC calculated from the raw data
*
* Detect and correct bit errors for a data block.
*/
int nand_bch_correct_data(struct nand_chip *chip, unsigned char *buf,
unsigned char *read_ecc, unsigned char *calc_ecc)
int nand_ecc_sw_bch_correct(struct nand_device *nand, unsigned char *buf,
unsigned char *read_ecc, unsigned char *calc_ecc)
{
struct nand_chip *chip = mtd_to_nand(nanddev_to_mtd(nand));
struct nand_bch_control *nbc = chip->ecc.priv;
unsigned int *errloc = nbc->errloc;
int i, count;
Expand All @@ -86,11 +89,11 @@ int nand_bch_correct_data(struct nand_chip *chip, unsigned char *buf,

return count;
}
EXPORT_SYMBOL(nand_bch_correct_data);
EXPORT_SYMBOL(nand_ecc_sw_bch_correct);

/**
* nand_bch_init - Initialize software BCH ECC engine
* @chip: NAND chip object
* nand_ecc_sw_bch_init - Initialize software BCH ECC engine
* @nand: NAND device
*
* Returns: a pointer to a new NAND BCH control structure, or NULL upon failure
*
Expand All @@ -105,9 +108,10 @@ EXPORT_SYMBOL(nand_bch_correct_data);
* @eccsize = 512 (thus, m = 13 is the smallest integer such that 2^m - 1 > 512 * 8)
* @eccbytes = 7 (7 bytes are required to store m * t = 13 * 4 = 52 bits)
*/
int nand_bch_init(struct nand_chip *chip)
int nand_ecc_sw_bch_init(struct nand_device *nand)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct mtd_info *mtd = nanddev_to_mtd(nand);
struct nand_chip *chip = mtd_to_nand(mtd);
unsigned int m, t, eccsteps, i;
struct nand_bch_control *nbc = NULL;
unsigned char *erased_page;
Expand Down Expand Up @@ -198,18 +202,21 @@ int nand_bch_init(struct nand_chip *chip)
chip->ecc.strength = (eccbytes * 8) / fls(8 * eccsize);

return 0;

fail:
nand_bch_free(chip);
nand_ecc_sw_bch_cleanup(nand);

return -EINVAL;
}
EXPORT_SYMBOL(nand_bch_init);
EXPORT_SYMBOL(nand_ecc_sw_bch_init);

/**
* nand_bch_free - Release NAND BCH ECC resources
* @nbc: NAND BCH control structure
* nand_ecc_sw_bch_cleanup - Cleanup software BCH ECC resources
* @nand: NAND device
*/
void nand_bch_free(struct nand_chip *chip)
void nand_ecc_sw_bch_cleanup(struct nand_device *nand)
{
struct nand_chip *chip = mtd_to_nand(nanddev_to_mtd(nand));
struct nand_bch_control *nbc = chip->ecc.priv;

if (nbc) {
Expand All @@ -219,7 +226,7 @@ void nand_bch_free(struct nand_chip *chip)
kfree(nbc);
}
}
EXPORT_SYMBOL(nand_bch_free);
EXPORT_SYMBOL(nand_ecc_sw_bch_cleanup);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ivan Djelic <ivan.djelic@parrot.com>");
Expand Down
44 changes: 40 additions & 4 deletions drivers/mtd/nand/raw/nand_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -5139,6 +5139,42 @@ static void nand_scan_ident_cleanup(struct nand_chip *chip)
kfree(chip->parameters.onfi);
}

int rawnand_sw_bch_init(struct nand_chip *chip)
{
struct nand_device *base = &chip->base;

return nand_ecc_sw_bch_init(base);
}
EXPORT_SYMBOL(rawnand_sw_bch_init);

static int rawnand_sw_bch_calculate(struct nand_chip *chip,
const unsigned char *buf,
unsigned char *code)
{
struct nand_device *base = &chip->base;

return nand_ecc_sw_bch_calculate(base, buf, code);
}

int rawnand_sw_bch_correct(struct nand_chip *chip, unsigned char *buf,
unsigned char *read_ecc, unsigned char *calc_ecc)
{
struct nand_device *base = &chip->base;

return nand_ecc_sw_bch_correct(base, buf, read_ecc, calc_ecc);
}
EXPORT_SYMBOL(rawnand_sw_bch_correct);

void rawnand_sw_bch_cleanup(struct nand_chip *chip)
{
struct nand_device *base = &chip->base;

nand_ecc_sw_bch_cleanup(base);

chip->ecc.priv = NULL;
}
EXPORT_SYMBOL(rawnand_sw_bch_cleanup);

static int nand_set_ecc_on_host_ops(struct nand_chip *chip)
{
struct nand_ecc_ctrl *ecc = &chip->ecc;
Expand Down Expand Up @@ -5235,8 +5271,8 @@ static int nand_set_ecc_soft_ops(struct nand_chip *chip)
WARN(1, "CONFIG_MTD_NAND_ECC_SW_BCH not enabled\n");
return -EINVAL;
}
ecc->calculate = nand_bch_calculate_ecc;
ecc->correct = nand_bch_correct_data;
ecc->calculate = rawnand_sw_bch_calculate;
ecc->correct = rawnand_sw_bch_correct;
ecc->read_page = nand_read_page_swecc;
ecc->read_subpage = nand_read_subpage;
ecc->write_page = nand_write_page_swecc;
Expand Down Expand Up @@ -5292,7 +5328,7 @@ static int nand_set_ecc_soft_ops(struct nand_chip *chip)

/* See the software BCH ECC initialization for details */
ecc->bytes = 0;
ret = nand_bch_init(chip);
ret = rawnand_sw_bch_init(chip);
if (ret) {
WARN(1, "BCH ECC initialization failed!\n");
return ret;
Expand Down Expand Up @@ -5957,7 +5993,7 @@ void nand_cleanup(struct nand_chip *chip)
{
if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT &&
chip->ecc.algo == NAND_ECC_ALGO_BCH)
nand_bch_free(chip);
rawnand_sw_bch_cleanup(chip);

nanddev_cleanup(&chip->base);

Expand Down
23 changes: 9 additions & 14 deletions drivers/mtd/nand/raw/omap2.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include <linux/of.h>
#include <linux/of_device.h>

#include <linux/mtd/nand-ecc-sw-bch.h>
#include <linux/platform_data/elm.h>

#include <linux/omap-gpmc.h>
Expand Down Expand Up @@ -2041,13 +2040,13 @@ static int omap_nand_attach_chip(struct nand_chip *chip)
chip->ecc.bytes = 7;
chip->ecc.strength = 4;
chip->ecc.hwctl = omap_enable_hwecc_bch;
chip->ecc.correct = nand_bch_correct_data;
chip->ecc.correct = rawnand_sw_bch_correct;
chip->ecc.calculate = omap_calculate_ecc_bch_sw;
mtd_set_ooblayout(mtd, &omap_sw_ooblayout_ops);
/* Reserve one byte for the OMAP marker */
oobbytes_per_step = chip->ecc.bytes + 1;
/* Software BCH library is used for locating errors */
err = nand_bch_init(chip);
err = rawnand_sw_bch_init(chip);
if (err) {
dev_err(dev, "Unable to use BCH library\n");
return err;
Expand Down Expand Up @@ -2083,13 +2082,13 @@ static int omap_nand_attach_chip(struct nand_chip *chip)
chip->ecc.bytes = 13;
chip->ecc.strength = 8;
chip->ecc.hwctl = omap_enable_hwecc_bch;
chip->ecc.correct = nand_bch_correct_data;
chip->ecc.correct = rawnand_sw_bch_correct;
chip->ecc.calculate = omap_calculate_ecc_bch_sw;
mtd_set_ooblayout(mtd, &omap_sw_ooblayout_ops);
/* Reserve one byte for the OMAP marker */
oobbytes_per_step = chip->ecc.bytes + 1;
/* Software BCH library is used for locating errors */
err = nand_bch_init(chip);
err = rawnand_sw_bch_init(chip);
if (err) {
dev_err(dev, "unable to use BCH library\n");
return err;
Expand Down Expand Up @@ -2195,7 +2194,6 @@ static int omap_nand_probe(struct platform_device *pdev)
nand_chip = &info->nand;
mtd = nand_to_mtd(nand_chip);
mtd->dev.parent = &pdev->dev;
nand_chip->ecc.priv = NULL;
nand_set_flash_node(nand_chip, dev->of_node);

if (!mtd->name) {
Expand Down Expand Up @@ -2271,10 +2269,9 @@ static int omap_nand_probe(struct platform_device *pdev)
return_error:
if (!IS_ERR_OR_NULL(info->dma))
dma_release_channel(info->dma);
if (nand_chip->ecc.priv) {
nand_bch_free(nand_chip);
nand_chip->ecc.priv = NULL;
}

rawnand_sw_bch_cleanup(nand_chip);

return err;
}

Expand All @@ -2285,10 +2282,8 @@ static int omap_nand_remove(struct platform_device *pdev)
struct omap_nand_info *info = mtd_to_omap(mtd);
int ret;

if (nand_chip->ecc.priv) {
nand_bch_free(nand_chip);
nand_chip->ecc.priv = NULL;
}
rawnand_sw_bch_cleanup(nand_chip);

if (info->dma)
dma_release_channel(info->dma);
ret = mtd_device_unregister(mtd);
Expand Down
45 changes: 16 additions & 29 deletions include/linux/mtd/nand-ecc-sw-bch.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,53 +8,40 @@
#ifndef __MTD_NAND_ECC_SW_BCH_H__
#define __MTD_NAND_ECC_SW_BCH_H__

struct mtd_info;
struct nand_chip;
#include <linux/mtd/nand.h>

#if IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_BCH)

/*
* Calculate BCH ecc code
*/
int nand_bch_calculate_ecc(struct nand_chip *chip, const u_char *dat,
u_char *ecc_code);

/*
* Detect and correct bit errors
*/
int nand_bch_correct_data(struct nand_chip *chip, u_char *dat,
u_char *read_ecc, u_char *calc_ecc);
/*
* Initialize BCH encoder/decoder
*/
int nand_bch_init(struct nand_chip *chip);
/*
* Release BCH encoder/decoder resources
*/
void nand_bch_free(struct nand_chip *chip);
int nand_ecc_sw_bch_calculate(struct nand_device *nand,
const unsigned char *buf, unsigned char *code);
int nand_ecc_sw_bch_correct(struct nand_device *nand, unsigned char *buf,
unsigned char *read_ecc, unsigned char *calc_ecc);
int nand_ecc_sw_bch_init(struct nand_device *nand);
void nand_ecc_sw_bch_cleanup(struct nand_device *nand);

#else /* !CONFIG_MTD_NAND_ECC_SW_BCH */

static inline int
nand_bch_calculate_ecc(struct nand_chip *chip, const u_char *dat,
u_char *ecc_code)
static inline int nand_ecc_sw_bch_calculate(struct nand_device *nand,
const unsigned char *buf,
unsigned char *code)
{
return -ENOTSUPP;
}

static inline int
nand_bch_correct_data(struct nand_chip *chip, unsigned char *buf,
unsigned char *read_ecc, unsigned char *calc_ecc)
static inline int nand_ecc_sw_bch_correct(struct nand_device *nand,
unsigned char *buf,
unsigned char *read_ecc,
unsigned char *calc_ecc)
{
return -ENOTSUPP;
}

static inline int nand_bch_init(struct nand_chip *chip)
static inline int nand_ecc_sw_bch_init(struct nand_device *nand)
{
return -ENOTSUPP;
}

static inline void nand_bch_free(struct nand_chip *chip) {}
static inline void nand_ecc_sw_bch_cleanup(struct nand_device *nand) {}

#endif /* CONFIG_MTD_NAND_ECC_SW_BCH */

Expand Down
5 changes: 5 additions & 0 deletions include/linux/mtd/rawnand.h
Original file line number Diff line number Diff line change
Expand Up @@ -1303,6 +1303,11 @@ static inline int nand_opcode_8bits(unsigned int command)
return 0;
}

int rawnand_sw_bch_init(struct nand_chip *chip);
int rawnand_sw_bch_correct(struct nand_chip *chip, unsigned char *buf,
unsigned char *read_ecc, unsigned char *calc_ecc);
void rawnand_sw_bch_cleanup(struct nand_chip *chip);

int nand_check_erased_ecc_chunk(void *data, int datalen,
void *ecc, int ecclen,
void *extraoob, int extraooblen,
Expand Down

0 comments on commit ea146d7

Please sign in to comment.