[PATCH 04/20] mtd: nand: ecc-bch: Stop exporting the private structure

Adam Ford aford173 at gmail.com
Sat Jan 9 09:46:44 EST 2021


On Tue, Sep 29, 2020 at 6:09 PM Miquel Raynal <miquel.raynal at bootlin.com> wrote:
>
> The NAND BCH control structure has nothing to do outside of this
> driver, all users of the nand_bch_init/free() functions just save it
> to chip->ecc.priv so do it in this driver directly and return a
> regular error code instead.
>
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---

Starting with this commit:  3c0fe36abebe, the kernel either doesn't
build or returns errors on some omap2plus devices with the following
error:

    nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xbc
    nand: Micron MT29F4G16ABBDA3W
    nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
    nand: using OMAP_ECC_BCH8_CODE_HW_DETECTION_SW
    Invalid ECC layout
    omap2-nand 30000000.nand: unable to use BCH library
    omap2-nand: probe of 30000000.nand failed with error -22
    8<--- cut here ---

There are few commits using git bisect that have build errors, so it
wasn't possible for me to determine the exact commit that broke the
ECC.  If the build failed, I marked it as 'bad' to git bisect.

Newer commits have remedied the build issue, but the Invalid ECC
layout error still exists as of 5.11-RC2.

Do you have any suggestions on what I can do to remedy this?  I am
willing to try and test.



>  drivers/mtd/nand/ecc-sw-bch.c       | 36 ++++++++++++++++-------------
>  drivers/mtd/nand/raw/fsmc_nand.c    |  2 +-
>  drivers/mtd/nand/raw/nand_base.c    | 12 ++++++----
>  drivers/mtd/nand/raw/omap2.c        | 16 ++++++-------
>  include/linux/mtd/nand-ecc-sw-bch.h | 11 ++++-----
>  5 files changed, 41 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/mtd/nand/ecc-sw-bch.c b/drivers/mtd/nand/ecc-sw-bch.c
> index fe080a0837d8..97221ec3876e 100644
> --- a/drivers/mtd/nand/ecc-sw-bch.c
> +++ b/drivers/mtd/nand/ecc-sw-bch.c
> @@ -90,7 +90,7 @@ EXPORT_SYMBOL(nand_bch_correct_data);
>
>  /**
>   * nand_bch_init - Initialize software BCH ECC engine
> - * @mtd: MTD device
> + * @chip: NAND chip object
>   *
>   * Returns: a pointer to a new NAND BCH control structure, or NULL upon failure
>   *
> @@ -105,24 +105,24 @@ 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)
>   */
> -struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
> +int nand_bch_init(struct nand_chip *chip)
>  {
> -       struct nand_chip *nand = mtd_to_nand(mtd);
> +       struct mtd_info *mtd = nand_to_mtd(chip);
>         unsigned int m, t, eccsteps, i;
>         struct nand_bch_control *nbc = NULL;
>         unsigned char *erased_page;
> -       unsigned int eccsize = nand->ecc.size;
> -       unsigned int eccbytes = nand->ecc.bytes;
> -       unsigned int eccstrength = nand->ecc.strength;
> +       unsigned int eccsize = chip->ecc.size;
> +       unsigned int eccbytes = chip->ecc.bytes;
> +       unsigned int eccstrength = chip->ecc.strength;
>
>         if (!eccbytes && eccstrength) {
>                 eccbytes = DIV_ROUND_UP(eccstrength * fls(8 * eccsize), 8);
> -               nand->ecc.bytes = eccbytes;
> +               chip->ecc.bytes = eccbytes;
>         }
>
>         if (!eccsize || !eccbytes) {
>                 pr_warn("ecc parameters not supplied\n");
> -               goto fail;
> +               return -EINVAL;
>         }
>
>         m = fls(1+8*eccsize);
> @@ -130,7 +130,9 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
>
>         nbc = kzalloc(sizeof(*nbc), GFP_KERNEL);
>         if (!nbc)
> -               goto fail;
> +               return -ENOMEM;
> +
> +       chip->ecc.priv = nbc;
>
>         nbc->bch = bch_init(m, t, 0, false);
>         if (!nbc->bch)
> @@ -165,8 +167,8 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
>          * FIXME: we should probably rework the sequencing in nand_scan_tail()
>          * to avoid setting those fields twice.
>          */
> -       nand->ecc.steps = eccsteps;
> -       nand->ecc.total = eccsteps * eccbytes;
> +       chip->ecc.steps = eccsteps;
> +       chip->ecc.total = eccsteps * eccbytes;
>         if (mtd_ooblayout_count_eccbytes(mtd) != (eccsteps*eccbytes)) {
>                 pr_warn("invalid ecc layout\n");
>                 goto fail;
> @@ -192,12 +194,12 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
>                 nbc->eccmask[i] ^= 0xff;
>
>         if (!eccstrength)
> -               nand->ecc.strength = (eccbytes * 8) / fls(8 * eccsize);
> +               chip->ecc.strength = (eccbytes * 8) / fls(8 * eccsize);
>
> -       return nbc;
> +       return 0;
>  fail:
> -       nand_bch_free(nbc);
> -       return NULL;
> +       nand_bch_free(chip);
> +       return -EINVAL;
>  }
>  EXPORT_SYMBOL(nand_bch_init);
>
> @@ -205,8 +207,10 @@ EXPORT_SYMBOL(nand_bch_init);
>   * nand_bch_free - Release NAND BCH ECC resources
>   * @nbc: NAND BCH control structure
>   */
> -void nand_bch_free(struct nand_bch_control *nbc)
> +void nand_bch_free(struct nand_chip *chip)
>  {
> +       struct nand_bch_control *nbc = chip->ecc.priv;
> +
>         if (nbc) {
>                 bch_free(nbc->bch);
>                 kfree(nbc->errloc);
> diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c
> index 4191831df182..1bc2462efeab 100644
> --- a/drivers/mtd/nand/raw/fsmc_nand.c
> +++ b/drivers/mtd/nand/raw/fsmc_nand.c
> @@ -927,7 +927,7 @@ static int fsmc_nand_attach_chip(struct nand_chip *nand)
>
>         /*
>          * Don't set layout for BCH4 SW ECC. This will be
> -        * generated later in nand_bch_init() later.
> +        * generated later during BCH initialization.
>          */
>         if (nand->ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST) {
>                 switch (mtd->oobsize) {
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 189d3a301a38..c47441ddc5cf 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -5208,6 +5208,7 @@ static int nand_set_ecc_soft_ops(struct nand_chip *chip)
>         struct mtd_info *mtd = nand_to_mtd(chip);
>         struct nand_device *nanddev = mtd_to_nanddev(mtd);
>         struct nand_ecc_ctrl *ecc = &chip->ecc;
> +       int ret;
>
>         if (WARN_ON(ecc->engine_type != NAND_ECC_ENGINE_TYPE_SOFT))
>                 return -EINVAL;
> @@ -5294,13 +5295,14 @@ static int nand_set_ecc_soft_ops(struct nand_chip *chip)
>                         ecc->strength = bytes * 8 / fls(8 * ecc->size);
>                 }
>
> -               /* See nand_bch_init() for details. */
> +               /* See the software BCH ECC initialization for details */
>                 ecc->bytes = 0;
> -               ecc->priv = nand_bch_init(mtd);
> -               if (!ecc->priv) {
> +               ret = nand_bch_init(chip);
> +               if (ret) {
>                         WARN(1, "BCH ECC initialization failed!\n");
> -                       return -EINVAL;
> +                       return ret;
>                 }
> +
>                 return 0;
>         default:
>                 WARN(1, "Unsupported ECC algorithm!\n");
> @@ -5960,7 +5962,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((struct nand_bch_control *)chip->ecc.priv);
> +               nand_bch_free(chip);
>
>         nanddev_cleanup(&chip->base);
>
> diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c
> index 0ef209e1cd87..6aab57336690 100644
> --- a/drivers/mtd/nand/raw/omap2.c
> +++ b/drivers/mtd/nand/raw/omap2.c
> @@ -2047,10 +2047,10 @@ static int omap_nand_attach_chip(struct nand_chip *chip)
>                 /* Reserve one byte for the OMAP marker */
>                 oobbytes_per_step       = chip->ecc.bytes + 1;
>                 /* Software BCH library is used for locating errors */
> -               chip->ecc.priv          = nand_bch_init(mtd);
> -               if (!chip->ecc.priv) {
> +               err = nand_bch_init(chip);
> +               if (err) {
>                         dev_err(dev, "Unable to use BCH library\n");
> -                       return -EINVAL;
> +                       return err;
>                 }
>                 break;
>
> @@ -2089,10 +2089,10 @@ static int omap_nand_attach_chip(struct nand_chip *chip)
>                 /* Reserve one byte for the OMAP marker */
>                 oobbytes_per_step       = chip->ecc.bytes + 1;
>                 /* Software BCH library is used for locating errors */
> -               chip->ecc.priv          = nand_bch_init(mtd);
> -               if (!chip->ecc.priv) {
> +               err = nand_bch_init(chip);
> +               if (err) {
>                         dev_err(dev, "unable to use BCH library\n");
> -                       return -EINVAL;
> +                       return err;
>                 }
>                 break;
>
> @@ -2272,7 +2272,7 @@ static int omap_nand_probe(struct platform_device *pdev)
>         if (!IS_ERR_OR_NULL(info->dma))
>                 dma_release_channel(info->dma);
>         if (nand_chip->ecc.priv) {
> -               nand_bch_free(nand_chip->ecc.priv);
> +               nand_bch_free(nand_chip);
>                 nand_chip->ecc.priv = NULL;
>         }
>         return err;
> @@ -2286,7 +2286,7 @@ static int omap_nand_remove(struct platform_device *pdev)
>         int ret;
>
>         if (nand_chip->ecc.priv) {
> -               nand_bch_free(nand_chip->ecc.priv);
> +               nand_bch_free(nand_chip);
>                 nand_chip->ecc.priv = NULL;
>         }
>         if (info->dma)
> diff --git a/include/linux/mtd/nand-ecc-sw-bch.h b/include/linux/mtd/nand-ecc-sw-bch.h
> index 1e1ee3af82b1..b62b8bd4669f 100644
> --- a/include/linux/mtd/nand-ecc-sw-bch.h
> +++ b/include/linux/mtd/nand-ecc-sw-bch.h
> @@ -10,7 +10,6 @@
>
>  struct mtd_info;
>  struct nand_chip;
> -struct nand_bch_control;
>
>  #if IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_BCH)
>
> @@ -30,11 +29,11 @@ int nand_bch_correct_data(struct nand_chip *chip, u_char *dat,
>  /*
>   * Initialize BCH encoder/decoder
>   */
> -struct nand_bch_control *nand_bch_init(struct mtd_info *mtd);
> +int nand_bch_init(struct nand_chip *chip);
>  /*
>   * Release BCH encoder/decoder resources
>   */
> -void nand_bch_free(struct nand_bch_control *nbc);
> +void nand_bch_free(struct nand_chip *chip);
>
>  #else /* !CONFIG_MTD_NAND_ECC_SW_BCH */
>
> @@ -54,12 +53,12 @@ nand_bch_correct_data(struct nand_chip *chip, unsigned char *buf,
>         return -ENOTSUPP;
>  }
>
> -static inline struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
> +static inline int nand_bch_init(struct nand_chip *chip)
>  {
> -       return NULL;
> +       return -ENOTSUPP;
>  }
>
> -static inline void nand_bch_free(struct nand_bch_control *nbc) {}
> +static inline void nand_bch_free(struct nand_chip *chip) {}
>
>  #endif /* CONFIG_MTD_NAND_ECC_SW_BCH */
>
> --
> 2.20.1
>
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/



More information about the linux-mtd mailing list