diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2019-08-15 10:58:11 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-08-15 10:58:11 +0200 |
commit | a0b3119905e16d7610f950d0fd04a8689979be2e (patch) | |
tree | 90dd07db7ee5ac0dbe66c3f94919d26e1c548409 | |
parent | 4c122cff4aa80dbfe9ebccca3ef196f70f75ef22 (diff) | |
parent | 3adce7def29d79b4f01216becf9a7fd0f8765e88 (diff) | |
download | barebox-a0b3119905e16d7610f950d0fd04a8689979be2e.tar.gz barebox-a0b3119905e16d7610f950d0fd04a8689979be2e.tar.xz |
Merge branch 'for-next/mtd'
-rw-r--r-- | commands/ubiformat.c | 1 | ||||
-rw-r--r-- | common/imx-bbu-nand-fcb.c | 5 | ||||
-rw-r--r-- | common/state/backend_bucket_circular.c | 2 | ||||
-rw-r--r-- | common/ubiformat.c | 62 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 4 | ||||
-rw-r--r-- | drivers/mtd/peb.c | 9 | ||||
-rw-r--r-- | drivers/mtd/spi-nor/spi-nor.c | 1 | ||||
-rw-r--r-- | drivers/mtd/ubi/eba.c | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/io.c | 29 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 1 | ||||
-rw-r--r-- | drivers/mtd/ubi/wl.c | 5 |
11 files changed, 91 insertions, 30 deletions
diff --git a/commands/ubiformat.c b/commands/ubiformat.c index a88672d6c2..7537e6b567 100644 --- a/commands/ubiformat.c +++ b/commands/ubiformat.c @@ -58,7 +58,6 @@ static int parse_opt(int argc, char *argv[], struct ubiformat_args *args, char **node) { - srand(get_time_ns()); memset(args, 0, sizeof(*args)); while (1) { diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c index 6d773b59df..a62e2a2975 100644 --- a/common/imx-bbu-nand-fcb.c +++ b/common/imx-bbu-nand-fcb.c @@ -531,6 +531,9 @@ again: if (ret == -EBADMSG) { ret = mtd_peb_torture(mtd, block); + if (ret == -EIO) + mtd_peb_mark_bad(mtd, block); + if (!ret && retries++ < 3) goto again; } @@ -771,6 +774,8 @@ out: if (ret == -EBADMSG) { ret = mtd_peb_torture(mtd, block); + if (ret == -EIO) + mtd_peb_mark_bad(mtd, block); if (!ret && retries++ < 3) goto again; diff --git a/common/state/backend_bucket_circular.c b/common/state/backend_bucket_circular.c index 4676730d05..47970b79f3 100644 --- a/common/state/backend_bucket_circular.c +++ b/common/state/backend_bucket_circular.c @@ -95,6 +95,7 @@ static int state_mtd_peb_read(struct state_backend_storage_bucket_circular *circ if (ret == -EBADMSG) { ret = mtd_peb_torture(circ->mtd, circ->eraseblock); if (ret == -EIO) { + mtd_peb_mark_bad(circ->mtd, circ->eraseblock); dev_err(circ->dev, "Tortured eraseblock failed and is marked bad now, PEB %u\n", circ->eraseblock); return -EIO; @@ -132,6 +133,7 @@ static int state_mtd_peb_write(struct state_backend_storage_bucket_circular *cir if (ret == -EBADMSG) { ret = mtd_peb_torture(circ->mtd, circ->eraseblock); if (ret == -EIO) { + mtd_peb_mark_bad(circ->mtd, circ->eraseblock); dev_err(circ->dev, "Tortured eraseblock failed and is marked bad now, PEB %u\n", circ->eraseblock); return -EIO; diff --git a/common/ubiformat.c b/common/ubiformat.c index 1968bd98f8..72b9b6f2eb 100644 --- a/common/ubiformat.c +++ b/common/ubiformat.c @@ -31,7 +31,6 @@ #include <common.h> #include <fs.h> #include <fcntl.h> -#include <errno.h> #include <crc.h> #include <stdlib.h> #include <clock.h> @@ -188,6 +187,7 @@ static int flash_image(struct ubiformat_args *args, struct mtd_info *mtd, const struct ubigen_info *ui, struct ubi_scan_info *si) { int fd = 0, img_ebs, eb, written_ebs = 0, ret = -1, eb_cnt; + int skip_data_read = 0; off_t st_size; char *buf = NULL; uint64_t lastprint = 0; @@ -257,7 +257,7 @@ static int flash_image(struct ubiformat_args *args, struct mtd_info *mtd, printf("\n"); sys_errmsg("failed to erase eraseblock %d", eb); - if (err != EIO) + if (err != -EIO) goto out_close; if (mark_bad(args, mtd, si, eb)) @@ -266,17 +266,20 @@ static int flash_image(struct ubiformat_args *args, struct mtd_info *mtd, continue; } - if (args->image) { - err = read_full(fd, buf, mtd->erasesize); - if (err < 0) { - sys_errmsg("failed to read eraseblock %d from image", - written_ebs); - goto out_close; + if (!skip_data_read) { + if (args->image) { + err = read_full(fd, buf, mtd->erasesize); + if (err < 0) { + sys_errmsg("failed to read eraseblock %d from image", + written_ebs); + goto out_close; + } + } else { + memcpy(buf, inbuf, mtd->erasesize); + inbuf += mtd->erasesize; } - } else { - memcpy(buf, inbuf, mtd->erasesize); - inbuf += mtd->erasesize; } + skip_data_read = 0; if (args->override_ec) ec = args->ec; @@ -306,14 +309,24 @@ static int flash_image(struct ubiformat_args *args, struct mtd_info *mtd, if (err) { sys_errmsg("cannot write eraseblock %d", eb); - if (err != EIO) + if (err != -EIO) goto out_close; err = mtd_peb_torture(mtd, eb); - if (err < 0 && err != -EIO) - goto out_close; - if (err == -EIO && consecutive_bad_check(args, eb)) + if (err == -EIO) { + err = mark_bad(args, mtd, si, eb); + if (err) + goto out_close; + } else if (err) { goto out_close; + } + + /* + * We have to make sure that we do not read next block + * of data from the input image or stdin - we have to + * write buf first instead. + */ + skip_data_read = 1; continue; } @@ -387,7 +400,7 @@ static int format(struct ubiformat_args *args, struct mtd_info *mtd, printf("\n"); sys_errmsg("failed to erase eraseblock %d", eb); - if (err != EIO) + if (err != -EIO) goto out_free; if (mark_bad(args, mtd, si, eb)) @@ -419,17 +432,20 @@ static int format(struct ubiformat_args *args, struct mtd_info *mtd, sys_errmsg("cannot write EC header (%d bytes buffer) to eraseblock %d", write_size, eb); - if (errno != EIO) { + if (err != -EIO) { if (args->subpage_size != mtd->writesize) normsg("may be sub-page size is incorrect?"); goto out_free; } err = mtd_peb_torture(mtd, eb); - if (err < 0 && err != -EIO) - goto out_free; - if (err == -EIO && consecutive_bad_check(args, eb)) + if (err == -EIO) { + err = mark_bad(args, mtd, si, eb); + if (err) + goto out_free; + } else if (err) { goto out_free; + } continue; @@ -481,8 +497,10 @@ int ubiformat(struct mtd_info *mtd, struct ubiformat_args *args) if (!args->ubi_ver) args->ubi_ver = 1; - if (!args->image_seq) - args->image_seq = rand(); + if (!args->image_seq) { + srand(get_time_ns()); + args->image_seq = random32(); + } if (!is_power_of_2(mtd->writesize)) { errmsg("min. I/O size is %d, but should be power of 2", diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index bf15e6ccee..5474d0db3c 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3967,5 +3967,9 @@ int add_mtd_nand_device(struct mtd_info *mtd, char *devname) ARRAY_SIZE(bbt_type_strings), mtd); + dev_add_param_uint32_ro(&mtd->class_dev, "ecc.bytes", &chip->ecc.bytes, "%u"); + dev_add_param_uint32_ro(&mtd->class_dev, "ecc.strength", &chip->ecc.strength, "%u"); + dev_add_param_uint32_ro(&mtd->class_dev, "ecc.size", &chip->ecc.size, "%u"); + return ret; } diff --git a/drivers/mtd/peb.c b/drivers/mtd/peb.c index 388db7f587..c82b3e8bba 100644 --- a/drivers/mtd/peb.c +++ b/drivers/mtd/peb.c @@ -493,9 +493,8 @@ static uint8_t patterns[] = {0xa5, 0x5a, 0x0}; * is passed then this function will with the block freshly erased and * the positive number returned indicaties how often the block has been * erased during this test. - * If the block does not pass the test the block is marked as bad and - * -EIO is returned. - * Other negative errors are returned in case of other errors. + * If the block does not pass the test -EIO is returned. + * Other negative errors are returned in case of other errors. */ int mtd_peb_torture(struct mtd_info *mtd, int pnum) { @@ -549,11 +548,9 @@ out: * has not passed because it happened on a freshly erased * physical eraseblock which means something is wrong with it. */ - dev_err(&mtd->class_dev, "read problems on freshly erased PEB %d, marking it bad\n", + dev_err(&mtd->class_dev, "read problems on freshly erased PEB %d, must be bad\n", pnum); - mtd_peb_mark_bad(mtd, pnum); - err = -EIO; } diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index b2052ce0af..9dbc8302ed 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -972,6 +972,7 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, for (i = 0; i < len; ) { ssize_t written; + retval = 0; page_offset = (to + i) & (nor->page_size - 1); page_remain = min_t(size_t, nor->page_size - page_offset, diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 3aae3029e5..cca6ec4ba9 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -865,7 +865,7 @@ static int try_write_vid_and_data(struct ubi_volume *vol, int lnum, int offset, int len) { struct ubi_device *ubi = vol->ubi; - int pnum, opnum, err, vol_id = vol->vol_id; + int pnum, opnum = -1, err, vol_id = vol->vol_id; pnum = ubi_wl_get_peb(ubi); if (pnum < 0) { diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index d0ea23b124..78458b58e1 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -357,6 +357,35 @@ int ubi_io_is_bad(const struct ubi_device *ubi, int pnum) } /** + * ubi_io_mark_bad - mark a physical eraseblock as bad. + * @ubi: UBI device description object + * @pnum: the physical eraseblock number to mark + * + * This function returns zero in case of success and a negative error code in + * case of failure. + */ +int ubi_io_mark_bad(const struct ubi_device *ubi, int pnum) +{ + int err; + struct mtd_info *mtd = ubi->mtd; + + ubi_assert(pnum >= 0 && pnum < ubi->peb_count); + + if (ubi->ro_mode) { + ubi_err(ubi, "read-only mode"); + return -EROFS; + } + + if (!ubi->bad_allowed) + return 0; + + err = mtd_block_markbad(mtd, (loff_t)pnum * ubi->peb_size); + if (err) + ubi_err(ubi, "cannot mark PEB %d bad, error %d", pnum, err); + return err; +} + +/** * validate_ec_hdr - validate an erase counter header. * @ubi: UBI device description object * @ec_hdr: the erase counter header to check diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index b85d602055..922c1a3c8b 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -865,6 +865,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, int len); int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture); int ubi_io_is_bad(const struct ubi_device *ubi, int pnum); +int ubi_io_mark_bad(const struct ubi_device *ubi, int pnum); int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, struct ubi_ec_hdr *ec_hdr, int verbose); int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum, diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index fa1b813702..cf90ecfb23 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1085,6 +1085,11 @@ static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk) available_consumed = 1; } + ubi_msg(ubi, "mark PEB %d as bad", pnum); + err = ubi_io_mark_bad(ubi, pnum); + if (err) + goto out_ro; + if (ubi->beb_rsvd_pebs > 0) { if (available_consumed) { /* |