diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2016-03-11 10:49:50 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2016-03-11 10:49:50 +0100 |
commit | 251ae23e9fa0a5ab88823e63bb18b89706b7ea87 (patch) | |
tree | 2c14c5b8fca7ab31335980ad359c56fc5fdb4cb2 | |
parent | 034d4ddcb6dfc7f72cb5076807e93a7bb7e4636b (diff) | |
parent | a1d621cbe3cc9ad7e8bdf35f51cbe61e5182ca1d (diff) | |
download | barebox-251ae23e9fa0a5ab88823e63bb18b89706b7ea87.tar.gz barebox-251ae23e9fa0a5ab88823e63bb18b89706b7ea87.tar.xz |
Merge branch 'for-next/mtd'
-rw-r--r-- | commands/nand.c | 9 | ||||
-rw-r--r-- | common/imx-bbu-nand-fcb.c | 8 | ||||
-rw-r--r-- | drivers/mtd/core.c | 42 | ||||
-rw-r--r-- | drivers/mtd/devices/m25p80.c | 2 | ||||
-rw-r--r-- | drivers/mtd/mtdoob.c | 2 | ||||
-rw-r--r-- | drivers/mtd/mtdraw.c | 53 | ||||
-rw-r--r-- | drivers/mtd/nand/nand-bb.c | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 2 | ||||
-rw-r--r-- | drivers/mtd/spi-nor/spi-nor.c | 1 | ||||
-rw-r--r-- | fs/devfs-core.c | 2 | ||||
-rw-r--r-- | fs/devfs.c | 2 | ||||
-rw-r--r-- | fs/fs.c | 2 | ||||
-rw-r--r-- | include/driver.h | 4 | ||||
-rw-r--r-- | include/fs.h | 4 | ||||
-rw-r--r-- | include/linux/mtd/mtd-abi.h | 8 | ||||
-rw-r--r-- | include/linux/mtd/mtd.h | 10 |
16 files changed, 99 insertions, 56 deletions
diff --git a/commands/nand.c b/commands/nand.c index ad1c8c9b3d..c330ad1dc4 100644 --- a/commands/nand.c +++ b/commands/nand.c @@ -90,8 +90,13 @@ static int do_nand(int argc, char *argv[]) } ret = ioctl(fd, MEMSETBADBLOCK, &badblock); - if (ret) - perror("ioctl"); + if (ret) { + if (ret == -EINVAL) + printf("Maybe offset %lld is out of range.\n", + badblock); + else + perror("ioctl"); + } close(fd); return ret; diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c index 22031f5b7f..3eb9e9b169 100644 --- a/common/imx-bbu-nand-fcb.c +++ b/common/imx-bbu-nand-fcb.c @@ -337,14 +337,14 @@ static int imx_bbu_write_firmware(struct mtd_info *mtd, unsigned block, return block; } -static int dbbt_data_create(struct mtd_info *mtd, void *buf, int block_last) +static int dbbt_data_create(struct mtd_info *mtd, void *buf, int num_blocks) { int n; int n_bad_blocks = 0; uint32_t *bb = buf + 0x8; uint32_t *n_bad_blocksp = buf + 0x4; - for (n = 0; n <= block_last; n++) { + for (n = 0; n < num_blocks; n++) { loff_t offset = n * mtd->erasesize; if (mtd_block_isbad(mtd, offset)) { n_bad_blocks++; @@ -461,10 +461,6 @@ static int imx_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *dat */ memset(fcb_raw_page + mtd->writesize, 0xFF, 2); - ret = raw_write_page(mtd, fcb_raw_page, mtd->erasesize); - if (ret) - goto out; - dbbt->Checksum = 0; dbbt->FingerPrint = 0x54424244; dbbt->Version = 0x01000000; diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c index 62307db709..161c6ad874 100644 --- a/drivers/mtd/core.c +++ b/drivers/mtd/core.c @@ -67,14 +67,13 @@ int mtd_all_ff(const void *buf, unsigned int len) } static ssize_t mtd_op_read(struct cdev *cdev, void* buf, size_t count, - loff_t _offset, ulong flags) + loff_t offset, ulong flags) { struct mtd_info *mtd = cdev->priv; size_t retlen; int ret; - unsigned long offset = _offset; - dev_dbg(cdev->dev, "read ofs: 0x%08lx count: 0x%08zx\n", + dev_dbg(cdev->dev, "read ofs: 0x%08llx count: 0x%08zx\n", offset, count); ret = mtd_read(mtd, offset, count, &retlen, buf); @@ -115,13 +114,13 @@ static struct mtd_erase_region_info *mtd_find_erase_region(struct mtd_info *mtd, return NULL; } -static int mtd_erase_align(struct mtd_info *mtd, size_t *count, loff_t *offset) +static int mtd_erase_align(struct mtd_info *mtd, loff_t *count, loff_t *offset) { struct mtd_erase_region_info *e; loff_t ofs; if (mtd->numeraseregions == 0) { - ofs = *offset & ~(mtd->erasesize - 1); + ofs = *offset & ~(loff_t)(mtd->erasesize - 1); *count += (*offset - ofs); *count = ALIGN(*count, mtd->erasesize); *offset = ofs; @@ -145,11 +144,11 @@ static int mtd_erase_align(struct mtd_info *mtd, size_t *count, loff_t *offset) return 0; } -static int mtd_op_erase(struct cdev *cdev, size_t count, loff_t offset) +static int mtd_op_erase(struct cdev *cdev, loff_t count, loff_t offset) { struct mtd_info *mtd = cdev->priv; struct erase_info erase; - uint32_t addr; + loff_t addr; int ret; ret = mtd_erase_align(mtd, &count, &offset); @@ -169,7 +168,7 @@ static int mtd_op_erase(struct cdev *cdev, size_t count, loff_t offset) erase.len = mtd->erasesize; while (count > 0) { - dev_dbg(cdev->dev, "erase %d %d\n", addr, erase.len); + dev_dbg(cdev->dev, "erase 0x%08llx len: 0x%08llx\n", addr, erase.len); if (mtd->allow_erasebad || (mtd->master && mtd->master->allow_erasebad)) ret = 0; @@ -179,7 +178,7 @@ static int mtd_op_erase(struct cdev *cdev, size_t count, loff_t offset) erase.addr = addr; if (ret > 0) { - printf("Skipping bad block at 0x%08x\n", addr); + printf("Skipping bad block at 0x%08llx\n", addr); } else { ret = mtd_erase(mtd, &erase); if (ret) @@ -310,6 +309,9 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs) { int ret; + if (ofs < 0 || ofs >= mtd->size) + return -EINVAL; + if (mtd->block_markbad) ret = mtd->block_markbad(mtd, ofs); else @@ -324,6 +326,11 @@ int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, int ret_code; *retlen = 0; + if (from < 0 || from >= mtd->size || len > mtd->size - from) + return -EINVAL; + if (!len) + return 0; + /* * In the absence of an error, drivers return a non-negative integer * representing the maximum number of bitflips that were corrected on @@ -342,11 +349,28 @@ int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, { *retlen = 0; + if (to < 0 || to >= mtd->size || len > mtd->size - to) + return -EINVAL; + if (!mtd->write || !(mtd->flags & MTD_WRITEABLE)) + return -EROFS; + if (!len) + return 0; + return mtd->write(mtd, to, len, retlen, buf); } int mtd_erase(struct mtd_info *mtd, struct erase_info *instr) { + if (instr->addr >= mtd->size || instr->len > mtd->size - instr->addr) + return -EINVAL; + if (!(mtd->flags & MTD_WRITEABLE)) + return -EROFS; + instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN; + if (!instr->len) { + instr->state = MTD_ERASE_DONE; + mtd_erase_callback(instr); + return 0; + } return mtd->erase(mtd, instr); } diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index d627690080..656a7f5ef0 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -298,6 +298,8 @@ static __maybe_unused struct of_device_id m25p80_dt_ids[] = { { .compatible = "m25p80", }, { + .compatible = "jedec,spi-nor", + }, { /* sentinel */ } }; diff --git a/drivers/mtd/mtdoob.c b/drivers/mtd/mtdoob.c index 6160ddba08..4dcf2f5915 100644 --- a/drivers/mtd/mtdoob.c +++ b/drivers/mtd/mtdoob.c @@ -79,7 +79,7 @@ static int add_mtdoob_device(struct mtd_info *mtd, const char *devname, void **p mtdoob = xzalloc(sizeof(*mtdoob)); mtdoob->cdev.ops = &mtd_ops_oob; mtdoob->cdev.size = mtd_div_by_wb(mtd->size, mtd) * mtd->oobsize; - mtdoob->cdev.name = asprintf("%s_oob%d", devname, mtd->class_dev.id); + mtdoob->cdev.name = asprintf("%s.oob", mtd->cdev.name); mtdoob->cdev.priv = mtdoob; mtdoob->cdev.dev = &mtd->class_dev; mtdoob->mtd = mtd; diff --git a/drivers/mtd/mtdraw.c b/drivers/mtd/mtdraw.c index ae4bec2a4c..4d6ac72bd9 100644 --- a/drivers/mtd/mtdraw.c +++ b/drivers/mtd/mtdraw.c @@ -83,6 +83,20 @@ static struct mtd_info *to_mtd(struct cdev *cdev) return mtdraw->mtd; } +static unsigned int mtdraw_offset_to_block(struct mtd_info *mtd, loff_t offset) +{ + u64 ofs64 = offset; + + do_div(ofs64, mtd->writesize + mtd->oobsize); + + return ofs64; +} + +static loff_t mtdraw_raw_to_mtd_offset(struct mtd_info *mtd, loff_t offset) +{ + return (loff_t)mtdraw_offset_to_block(mtd, offset) * mtd->writesize; +} + static ssize_t mtdraw_read_unaligned(struct mtd_info *mtd, void *dst, size_t count, int skip, ulong offset) { @@ -117,22 +131,21 @@ err: } static ssize_t mtdraw_read(struct cdev *cdev, void *buf, size_t count, - loff_t _offset, ulong flags) + loff_t offset, ulong flags) { struct mtd_info *mtd = to_mtd(cdev); ssize_t retlen = 0, ret = 1, toread; - ulong numpage; + ulong numblock; int skip; - unsigned long offset = _offset; - numpage = offset / (mtd->writesize + mtd->oobsize); - skip = offset % (mtd->writesize + mtd->oobsize); + numblock = mtdraw_offset_to_block(mtd, offset); + skip = offset - numblock * (mtd->writesize + mtd->oobsize); while (ret > 0 && count > 0) { toread = min_t(int, count, mtd->writesize + mtd->oobsize - skip); ret = mtdraw_read_unaligned(mtd, buf, toread, - skip, numpage++ * mtd->writesize); + skip, numblock++ * mtd->writesize); buf += ret; skip = 0; count -= ret; @@ -171,20 +184,21 @@ static void mtdraw_fillbuf(struct mtdraw *mtdraw, const void *src, int nbbytes) } static ssize_t mtdraw_write(struct cdev *cdev, const void *buf, size_t count, - loff_t _offset, ulong flags) + loff_t offset, ulong flags) { struct mtdraw *mtdraw = to_mtdraw(cdev); struct mtd_info *mtd = to_mtd(cdev); int bsz = mtd->writesize + mtd->oobsize; - ulong numpage; + ulong numblock; size_t retlen = 0, tofill; - unsigned long offset = _offset; int ret = 0; + numblock = mtdraw_offset_to_block(mtd, offset); + if (mtdraw->write_fill && mtdraw->write_ofs + mtdraw->write_fill != offset) return -EINVAL; - if (mtdraw->write_fill == 0 && offset % bsz) + if (mtdraw->write_fill == 0 && offset - numblock * mtd->writesize != 0) return -EINVAL; if (mtdraw->write_fill) { @@ -196,16 +210,16 @@ static ssize_t mtdraw_write(struct cdev *cdev, const void *buf, size_t count, } if (mtdraw->write_fill == bsz) { - numpage = mtdraw->write_ofs / (mtd->writesize + mtd->oobsize); + numblock = mtdraw_offset_to_block(mtd, mtdraw->write_ofs); ret = mtdraw_blkwrite(mtd, mtdraw->writebuf, - mtd->writesize * numpage); + mtd->writesize * numblock); mtdraw->write_fill = 0; } - numpage = offset / (mtd->writesize + mtd->oobsize); + numblock = mtdraw_offset_to_block(mtd, offset); while (ret >= 0 && count >= bsz) { ret = mtdraw_blkwrite(mtd, buf + retlen, - mtd->writesize * numpage++); + mtd->writesize * numblock++); count -= ret; retlen += ret; offset += ret; @@ -225,15 +239,14 @@ static ssize_t mtdraw_write(struct cdev *cdev, const void *buf, size_t count, } } -static int mtdraw_erase(struct cdev *cdev, size_t count, loff_t _offset) +static int mtdraw_erase(struct cdev *cdev, loff_t count, loff_t offset) { struct mtd_info *mtd = to_mtd(cdev); struct erase_info erase; - unsigned long offset = _offset; int ret; - offset = offset / (mtd->writesize + mtd->oobsize) * mtd->writesize; - count = count / (mtd->writesize + mtd->oobsize) * mtd->writesize; + offset = mtdraw_raw_to_mtd_offset(mtd, offset); + count = mtdraw_raw_to_mtd_offset(mtd, count); memset(&erase, 0, sizeof(erase)); erase.mtd = mtd; @@ -241,7 +254,7 @@ static int mtdraw_erase(struct cdev *cdev, size_t count, loff_t _offset) erase.len = mtd->erasesize; while (count > 0) { - debug("erase %d %d\n", erase.addr, erase.len); + debug("erase 0x%08llx len: 0x%08llx\n", erase.addr, erase.len); if (!mtd->allow_erasebad) ret = mtd_block_isbad(mtd, erase.addr); @@ -249,7 +262,7 @@ static int mtdraw_erase(struct cdev *cdev, size_t count, loff_t _offset) ret = 0; if (ret > 0) { - printf("Skipping bad block at 0x%08x\n", erase.addr); + printf("Skipping bad block at 0x%08llx\n", erase.addr); } else { ret = mtd_erase(mtd, &erase); if (ret) diff --git a/drivers/mtd/nand/nand-bb.c b/drivers/mtd/nand/nand-bb.c index 8e4600ab03..e6d42772b3 100644 --- a/drivers/mtd/nand/nand-bb.c +++ b/drivers/mtd/nand/nand-bb.c @@ -88,7 +88,7 @@ static ssize_t nand_bb_read(struct cdev *cdev, void *buf, size_t count, } /* Must be a multiple of the largest NAND page size */ -#define BB_WRITEBUF_SIZE 4096 +#define BB_WRITEBUF_SIZE 8192 #ifdef CONFIG_MTD_WRITE static int nand_bb_write_buf(struct nand_bb *bb, size_t count) @@ -157,7 +157,7 @@ static ssize_t nand_bb_write(struct cdev *cdev, const void *buf, size_t count, return bytes; } -static int nand_bb_erase(struct cdev *cdev, size_t count, loff_t offset) +static int nand_bb_erase(struct cdev *cdev, loff_t count, loff_t offset) { struct nand_bb *bb = cdev->priv; struct erase_info erase = {}; diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 554d3d2f96..ec5a8b757c 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3718,7 +3718,7 @@ int nand_scan_tail(struct mtd_info *mtd) * properly set. */ if (!mtd->bitflip_threshold) - mtd->bitflip_threshold = mtd->ecc_strength; + mtd->bitflip_threshold = DIV_ROUND_UP(mtd->ecc_strength * 3, 4); /* Check, if we should skip the bad block table scan */ if (chip->options & NAND_SKIP_BBTSCAN) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 908aacb6a2..4b55b0c3d8 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -571,6 +571,7 @@ static const struct spi_device_id spi_nor_ids[] = { { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) }, { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, + { "s25fl116k", INFO(0x014015, 0, 64 * 1024, 32, SECT_4K) }, { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, 0) }, { "s25fl204k", INFO(0x014013, 0, 64 * 1024, 8, SECT_4K) }, diff --git a/fs/devfs-core.c b/fs/devfs-core.c index 88a7e3a1d6..deacaaad3f 100644 --- a/fs/devfs-core.c +++ b/fs/devfs-core.c @@ -259,7 +259,7 @@ int cdev_ioctl(struct cdev *cdev, int request, void *buf) return cdev->ops->ioctl(cdev, request, buf); } -int cdev_erase(struct cdev *cdev, size_t count, loff_t offset) +int cdev_erase(struct cdev *cdev, loff_t count, loff_t offset) { if (!cdev->ops->erase) return -ENOSYS; diff --git a/fs/devfs.c b/fs/devfs.c index 0b8d4fd246..6fabcf8ffa 100644 --- a/fs/devfs.c +++ b/fs/devfs.c @@ -66,7 +66,7 @@ static loff_t devfs_lseek(struct device_d *_dev, FILE *f, loff_t pos) return ret - cdev->offset; } -static int devfs_erase(struct device_d *_dev, FILE *f, size_t count, loff_t offset) +static int devfs_erase(struct device_d *_dev, FILE *f, loff_t count, loff_t offset) { struct cdev *cdev = f->priv; @@ -924,7 +924,7 @@ out: } EXPORT_SYMBOL(lseek); -int erase(int fd, size_t count, loff_t offset) +int erase(int fd, loff_t count, loff_t offset) { struct fs_driver_d *fsdrv; FILE *f; diff --git a/include/driver.h b/include/driver.h index 5e2b88f315..80aa8d821c 100644 --- a/include/driver.h +++ b/include/driver.h @@ -431,7 +431,7 @@ struct file_operations { int (*open)(struct cdev*, unsigned long flags); int (*close)(struct cdev*); int (*flush)(struct cdev*); - int (*erase)(struct cdev*, size_t count, loff_t offset); + int (*erase)(struct cdev*, loff_t count, loff_t offset); int (*protect)(struct cdev*, size_t count, loff_t offset, int prot); int (*memmap)(struct cdev*, void **map, int flags); }; @@ -476,7 +476,7 @@ int cdev_flush(struct cdev *cdev); ssize_t cdev_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags); ssize_t cdev_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags); int cdev_ioctl(struct cdev *cdev, int cmd, void *buf); -int cdev_erase(struct cdev *cdev, size_t count, loff_t offset); +int cdev_erase(struct cdev *cdev, loff_t count, loff_t offset); #define DEVFS_PARTITION_FIXED (1U << 0) #define DEVFS_PARTITION_READONLY (1U << 1) diff --git a/include/fs.h b/include/fs.h index 23156eadae..9f4164ed77 100644 --- a/include/fs.h +++ b/include/fs.h @@ -70,7 +70,7 @@ struct fs_driver_d { int (*stat)(struct device_d *dev, const char *file, struct stat *stat); int (*ioctl)(struct device_d *dev, FILE *f, int request, void *buf); - int (*erase)(struct device_d *dev, FILE *f, size_t count, + int (*erase)(struct device_d *dev, FILE *f, loff_t count, loff_t offset); int (*protect)(struct device_d *dev, FILE *f, size_t count, loff_t offset, int prot); @@ -145,7 +145,7 @@ int mount (const char *device, const char *fsname, const char *path, int umount(const char *pathname); /* not-so-standard functions */ -int erase(int fd, size_t count, loff_t offset); +int erase(int fd, loff_t count, loff_t offset); int protect(int fd, size_t count, loff_t offset, int prot); int protect_file(const char *file, int prot); void *memmap(int fd, int flags); diff --git a/include/linux/mtd/mtd-abi.h b/include/linux/mtd/mtd-abi.h index c46605d5e3..8e778df173 100644 --- a/include/linux/mtd/mtd-abi.h +++ b/include/linux/mtd/mtd-abi.h @@ -10,13 +10,13 @@ #include <asm-generic/div64.h> struct erase_info_user { - uint32_t start; - uint32_t length; + uint64_t start; + uint64_t length; }; struct mtd_oob_buf { - uint32_t start; - uint32_t length; + uint64_t start; + uint64_t length; unsigned char *ptr; }; diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 7e828bc98f..421a941aad 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -26,14 +26,16 @@ #define MTD_ERASE_DONE 0x08 #define MTD_ERASE_FAILED 0x10 +#define MTD_FAIL_ADDR_UNKNOWN -1LL + /* If the erase fails, fail_addr might indicate exactly which block failed. If fail_addr = 0xffffffff, the failure was not at the device level or was not specific to any particular block. */ struct erase_info { struct mtd_info *mtd; - u_int32_t addr; - u_int32_t len; - u_int32_t fail_addr; + u_int64_t addr; + u_int64_t len; + u_int64_t fail_addr; u_long time; u_long retries; u_int dev; @@ -45,7 +47,7 @@ struct erase_info { }; struct mtd_erase_region_info { - u_int32_t offset; /* At which this region starts, from the beginning of the MTD */ + u_int64_t offset; /* At which this region starts, from the beginning of the MTD */ u_int32_t erasesize; /* For this region */ u_int32_t numblocks; /* Number of blocks of erasesize in this region */ unsigned long *lockmap; /* If keeping bitmap of locks */ |