diff options
Diffstat (limited to 'drivers/mtd/nftlcore.c')
| -rw-r--r-- | drivers/mtd/nftlcore.c | 84 |
1 files changed, 29 insertions, 55 deletions
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index c5f4ebf4b384..868aa3d35d09 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Linux driver for NAND Flash Translation Layer * * Copyright © 1999 Machine Vision Holdings, Inc. * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define PRERELEASE @@ -25,7 +12,7 @@ #include <linux/module.h> #include <asm/errno.h> #include <asm/io.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/delay.h> #include <linux/slab.h> #include <linux/init.h> @@ -34,7 +21,7 @@ #include <linux/kmod.h> #include <linux/mtd/mtd.h> -#include <linux/mtd/nand.h> +#include <linux/mtd/rawnand.h> #include <linux/mtd/nftl.h> #include <linux/mtd/blktrans.h> @@ -50,7 +37,7 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) struct NFTLrecord *nftl; unsigned long temp; - if (mtd->type != MTD_NANDFLASH || mtd->size > UINT_MAX) + if (!mtd_type_is_nand(mtd) || mtd->size > UINT_MAX) return; /* OK, this is moderately ugly. But probably safe. Alternatives? */ if (memcmp(mtd->name, "DiskOnChip", 10)) @@ -137,7 +124,7 @@ int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, size_t *retlen, uint8_t *buf) { loff_t mask = mtd->writesize - 1; - struct mtd_oob_ops ops; + struct mtd_oob_ops ops = { }; int res; ops.mode = MTD_OPS_PLACE_OOB; @@ -158,7 +145,7 @@ int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, size_t *retlen, uint8_t *buf) { loff_t mask = mtd->writesize - 1; - struct mtd_oob_ops ops; + struct mtd_oob_ops ops = { }; int res; ops.mode = MTD_OPS_PLACE_OOB; @@ -181,7 +168,7 @@ static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len, size_t *retlen, uint8_t *buf, uint8_t *oob) { loff_t mask = mtd->writesize - 1; - struct mtd_oob_ops ops; + struct mtd_oob_ops ops = { }; int res; ops.mode = MTD_OPS_PLACE_OOB; @@ -241,6 +228,25 @@ static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate ) return BLOCK_NIL; } +static noinline_for_stack void NFTL_move_block(struct mtd_info *mtd, loff_t src, loff_t dst) +{ + unsigned char movebuf[512]; + struct nftl_oob oob; + size_t retlen; + int ret; + + ret = mtd_read(mtd, src, 512, &retlen, movebuf); + if (ret < 0 && !mtd_is_bitflip(ret)) { + ret = mtd_read(mtd, src, 512, &retlen, movebuf); + if (ret != -EIO) + printk("Error went away on retry.\n"); + } + memset(&oob, 0xff, sizeof(struct nftl_oob)); + oob.b.Status = oob.b.Status1 = SECTOR_USED; + + nftl_write(mtd, dst, 512, &retlen, movebuf, (char *)&oob); +} + static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock ) { struct mtd_info *mtd = nftl->mbd.mtd; @@ -402,9 +408,6 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p */ pr_debug("Folding chain %d into unit %d\n", thisVUC, targetEUN); for (block = 0; block < nftl->EraseSize / 512 ; block++) { - unsigned char movebuf[512]; - int ret; - /* If it's in the target EUN already, or if it's pending write, do nothing */ if (BlockMap[block] == targetEUN || (pendingblock == (thisVUC * (nftl->EraseSize / 512) + block))) { @@ -416,25 +419,8 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p if (BlockMap[block] == BLOCK_NIL) continue; - ret = mtd_read(mtd, - (nftl->EraseSize * BlockMap[block]) + (block * 512), - 512, - &retlen, - movebuf); - if (ret < 0 && !mtd_is_bitflip(ret)) { - ret = mtd_read(mtd, - (nftl->EraseSize * BlockMap[block]) + (block * 512), - 512, - &retlen, - movebuf); - if (ret != -EIO) - printk("Error went away on retry.\n"); - } - memset(&oob, 0xff, sizeof(struct nftl_oob)); - oob.b.Status = oob.b.Status1 = SECTOR_USED; - - nftl_write(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + - (block * 512), 512, &retlen, movebuf, (char *)&oob); + NFTL_move_block(mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512), + (nftl->EraseSize * targetEUN) + (block * 512)); } /* add the header so that it is now a valid chain */ @@ -632,7 +618,6 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) return BLOCK_NIL; } //printk("Restarting scan\n"); - lastEUN = BLOCK_NIL; continue; } @@ -810,18 +795,7 @@ static struct mtd_blktrans_ops nftl_tr = { .owner = THIS_MODULE, }; -static int __init init_nftl(void) -{ - return register_mtd_blktrans(&nftl_tr); -} - -static void __exit cleanup_nftl(void) -{ - deregister_mtd_blktrans(&nftl_tr); -} - -module_init(init_nftl); -module_exit(cleanup_nftl); +module_mtd_blktrans(nftl_tr); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>, Fabrice Bellard <fabrice.bellard@netgem.com> et al."); |
