summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2016-03-11 10:49:50 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2016-03-11 10:49:50 +0100
commit251ae23e9fa0a5ab88823e63bb18b89706b7ea87 (patch)
tree2c14c5b8fca7ab31335980ad359c56fc5fdb4cb2
parent034d4ddcb6dfc7f72cb5076807e93a7bb7e4636b (diff)
parenta1d621cbe3cc9ad7e8bdf35f51cbe61e5182ca1d (diff)
downloadbarebox-251ae23e9fa0a5ab88823e63bb18b89706b7ea87.tar.gz
barebox-251ae23e9fa0a5ab88823e63bb18b89706b7ea87.tar.xz
Merge branch 'for-next/mtd'
-rw-r--r--commands/nand.c9
-rw-r--r--common/imx-bbu-nand-fcb.c8
-rw-r--r--drivers/mtd/core.c42
-rw-r--r--drivers/mtd/devices/m25p80.c2
-rw-r--r--drivers/mtd/mtdoob.c2
-rw-r--r--drivers/mtd/mtdraw.c53
-rw-r--r--drivers/mtd/nand/nand-bb.c4
-rw-r--r--drivers/mtd/nand/nand_base.c2
-rw-r--r--drivers/mtd/spi-nor/spi-nor.c1
-rw-r--r--fs/devfs-core.c2
-rw-r--r--fs/devfs.c2
-rw-r--r--fs/fs.c2
-rw-r--r--include/driver.h4
-rw-r--r--include/fs.h4
-rw-r--r--include/linux/mtd/mtd-abi.h8
-rw-r--r--include/linux/mtd/mtd.h10
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;
diff --git a/fs/fs.c b/fs/fs.c
index ace72f7d54..c4b3583433 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -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 */