summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2019-08-15 10:58:11 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2019-08-15 10:58:11 +0200
commita0b3119905e16d7610f950d0fd04a8689979be2e (patch)
tree90dd07db7ee5ac0dbe66c3f94919d26e1c548409
parent4c122cff4aa80dbfe9ebccca3ef196f70f75ef22 (diff)
parent3adce7def29d79b4f01216becf9a7fd0f8765e88 (diff)
downloadbarebox-a0b3119905e16d7610f950d0fd04a8689979be2e.tar.gz
barebox-a0b3119905e16d7610f950d0fd04a8689979be2e.tar.xz
Merge branch 'for-next/mtd'
-rw-r--r--commands/ubiformat.c1
-rw-r--r--common/imx-bbu-nand-fcb.c5
-rw-r--r--common/state/backend_bucket_circular.c2
-rw-r--r--common/ubiformat.c62
-rw-r--r--drivers/mtd/nand/nand_base.c4
-rw-r--r--drivers/mtd/peb.c9
-rw-r--r--drivers/mtd/spi-nor/spi-nor.c1
-rw-r--r--drivers/mtd/ubi/eba.c2
-rw-r--r--drivers/mtd/ubi/io.c29
-rw-r--r--drivers/mtd/ubi/ubi.h1
-rw-r--r--drivers/mtd/ubi/wl.c5
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) {
/*