From b6bcd96de5a75bdc5d06a06f2efffc2d89e346ec Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 30 Oct 2020 12:30:31 +0100 Subject: mtd: nand: Update to Linux-5.9 This updates the barebox NAND layer and parts of the mtd layer to Linux-5.9. This patch is huge, but the barebox NAND layer is so far away from the Linux NAND layer that a step by step update would have taken ages. Unlike Linux barebox has functions to mark a block as good. This feature has been preserved. Also barebox used to make NAND write support optional, this feature is lost during the update for the sake of better compatibility to the Linux NAND layer. This patch has been tested: - GPMI aka nand_mxs on i.MX6 - nand_imx on i.MX25 - nand_omap_gpmc on AM335x - atmel_nand on Atmel sama5d3 - nand_denali on SoCFPGA Currently untested: - nand_orion - nand_mrvl_nfc - nand_s3c24xx The nand_denali driver is tested with the update of that driver to Linux-5.9 following in the next patch. I could only test the drivers with the NAND chips found on my boards, so there's still enough room for regressions, especially given that the NAND drivers themselves are mostly not updated. With the NAND layer being up-to-date with Linux it should hopefully be easy to update drivers to their Linux counterpart as well if necessary. Signed-off-by: Sascha Hauer --- drivers/mtd/nand/nand_bch.c | 88 ++++++++++++++++----------------------------- 1 file changed, 31 insertions(+), 57 deletions(-) (limited to 'drivers/mtd/nand/nand_bch.c') diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c index 42ffa1b21a..0d636d9608 100644 --- a/drivers/mtd/nand/nand_bch.c +++ b/drivers/mtd/nand/nand_bch.c @@ -1,19 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * This file provides ECC correction for more than 1 bit per block of data, * using binary BCH codes. It relies on the generic BCH library lib/bch.c. * * Copyright © 2011 Ivan Djelic - * - * This file is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 or (at your option) any - * later version. - * - * This file is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * */ #include @@ -22,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -29,20 +20,18 @@ /** * struct nand_bch_control - private NAND BCH control structure * @bch: BCH control structure - * @ecclayout: private ecc layout for this BCH configuration * @errloc: error location array * @eccmask: XOR ecc mask, allows erased pages to be decoded as valid */ struct nand_bch_control { struct bch_control *bch; - struct nand_ecclayout ecclayout; unsigned int *errloc; unsigned char *eccmask; }; /** * nand_bch_calculate_ecc - [NAND Interface] Calculate ECC for data block - * @mtd: MTD block structure + * @chip: NAND chip object * @buf: input buffer with raw data * @code: output buffer with ECC */ @@ -65,7 +54,7 @@ EXPORT_SYMBOL(nand_bch_calculate_ecc); /** * nand_bch_correct_data - [NAND Interface] Detect and correct bit error(s) - * @mtd: MTD block structure + * @chip: NAND chip object * @buf: raw data read from the chip * @read_ecc: ECC from the chip * @calc_ecc: the ECC calculated from raw data @@ -92,8 +81,8 @@ int nand_bch_correct_data(struct nand_chip *chip, unsigned char *buf, errloc[i]); } } else if (count < 0) { - printk(KERN_ERR "ecc unrecoverable error\n"); - count = -1; + pr_err("ecc unrecoverable error\n"); + count = -EBADMSG; } return count; } @@ -115,11 +104,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) */ -struct nand_bch_control *nand_bch_init(struct nand_chip *nand) +struct nand_bch_control *nand_bch_init(struct mtd_info *mtd) { - struct mtd_info *mtd = nand_to_mtd(nand); + struct nand_chip *nand = mtd_to_nand(mtd); unsigned int m, t, eccsteps, i; - struct nand_ecclayout *layout = nand->ecc.layout; struct nand_bch_control *nbc = NULL; unsigned char *erased_page; unsigned int eccsize = nand->ecc.size; @@ -132,7 +120,7 @@ struct nand_bch_control *nand_bch_init(struct nand_chip *nand) } if (!eccsize || !eccbytes) { - printk(KERN_WARNING "ecc parameters not supplied\n"); + pr_warn("ecc parameters not supplied\n"); goto fail; } @@ -149,55 +137,42 @@ struct nand_bch_control *nand_bch_init(struct nand_chip *nand) /* verify that eccbytes has the expected value */ if (nbc->bch->ecc_bytes != eccbytes) { - printk(KERN_WARNING "invalid eccbytes %u, should be %u\n", - eccbytes, nbc->bch->ecc_bytes); + pr_warn("invalid eccbytes %u, should be %u\n", + eccbytes, nbc->bch->ecc_bytes); goto fail; } eccsteps = mtd->writesize/eccsize; - /* if no ecc placement scheme was provided, build one */ - if (!layout) { - - /* handle large page devices only */ - if (mtd->oobsize < 64) { - printk(KERN_WARNING "must provide an oob scheme for " - "oobsize %d\n", mtd->oobsize); - goto fail; - } - - layout = &nbc->ecclayout; - layout->eccbytes = eccsteps*eccbytes; - - /* reserve 2 bytes for bad block marker */ - if (layout->eccbytes+2 > mtd->oobsize) { - printk(KERN_WARNING "no suitable oob scheme available " - "for oobsize %d eccbytes %u\n", mtd->oobsize, - eccbytes); - goto fail; - } - /* put ecc bytes at oob tail */ - for (i = 0; i < layout->eccbytes; i++) - layout->eccpos[i] = mtd->oobsize-layout->eccbytes+i; - - layout->oobfree[0].offset = 2; - layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes; - - nand->ecc.layout = layout; + /* Check that we have an oob layout description. */ + if (!mtd->ooblayout) { + pr_warn("missing oob scheme"); + goto fail; } /* sanity checks */ if (8*(eccsize+eccbytes) >= (1 << m)) { - printk(KERN_WARNING "eccsize %u is too large\n", eccsize); + pr_warn("eccsize %u is too large\n", eccsize); goto fail; } - if (layout->eccbytes != (eccsteps*eccbytes)) { - printk(KERN_WARNING "invalid ecc layout\n"); + + /* + * ecc->steps and ecc->total might be used by mtd->ooblayout->ecc(), + * which is called by mtd_ooblayout_count_eccbytes(). + * Make sure they are properly initialized before calling + * mtd_ooblayout_count_eccbytes(). + * 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; + if (mtd_ooblayout_count_eccbytes(mtd) != (eccsteps*eccbytes)) { + pr_warn("invalid ecc layout\n"); goto fail; } - nbc->eccmask = kmalloc(eccbytes, GFP_KERNEL); - nbc->errloc = kmalloc(t*sizeof(*nbc->errloc), GFP_KERNEL); + nbc->eccmask = kzalloc(eccbytes, GFP_KERNEL); + nbc->errloc = kmalloc_array(t, sizeof(*nbc->errloc), GFP_KERNEL); if (!nbc->eccmask || !nbc->errloc) goto fail; /* @@ -208,7 +183,6 @@ struct nand_bch_control *nand_bch_init(struct nand_chip *nand) goto fail; memset(erased_page, 0xff, eccsize); - memset(nbc->eccmask, 0, eccbytes); encode_bch(nbc->bch, erased_page, eccsize, nbc->eccmask); kfree(erased_page); -- cgit v1.2.3