9
0
Fork 0

Merge branch 'for-next/mtd'

This commit is contained in:
Sascha Hauer 2016-03-11 10:49:50 +01:00
commit 251ae23e9f
16 changed files with 99 additions and 56 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -297,6 +297,8 @@ static int m25p_probe(struct device_d *dev)
static __maybe_unused struct of_device_id m25p80_dt_ids[] = {
{
.compatible = "m25p80",
}, {
.compatible = "jedec,spi-nor",
}, {
/* sentinel */
}

View File

@ -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;

View File

@ -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)

View File

@ -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 = {};

View File

@ -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)

View File

@ -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) },

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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;
};

View File

@ -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 */