kernel: handle bad blocks in ubi auto attach code
The first block(s) of the ubi mtd device might be bad. We need to take care on our own to skip the bad block(s) and read the next one(s). Don't treat recoverable read errors as fatal and check for the UBI magic if the data of a block could be recovered using ECC or similar. Signed-off-by: Mathias Kresin <dev@kresin.me>
This commit is contained in:
parent
fdf6760cda
commit
0ac91d82ed
2 changed files with 36 additions and 8 deletions
|
@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
|
|
||||||
--- a/drivers/mtd/ubi/build.c
|
--- a/drivers/mtd/ubi/build.c
|
||||||
+++ b/drivers/mtd/ubi/build.c
|
+++ b/drivers/mtd/ubi/build.c
|
||||||
@@ -1171,6 +1171,54 @@ static struct mtd_info * __init open_mtd
|
@@ -1171,6 +1171,68 @@ static struct mtd_info * __init open_mtd
|
||||||
return mtd;
|
return mtd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
+{
|
+{
|
||||||
+ int err;
|
+ int err;
|
||||||
+ struct mtd_info *mtd;
|
+ struct mtd_info *mtd;
|
||||||
|
+ loff_t offset = 0;
|
||||||
+ size_t len;
|
+ size_t len;
|
||||||
+ char magic[4];
|
+ char magic[4];
|
||||||
+
|
+
|
||||||
|
@ -31,9 +32,22 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
+ if (IS_ERR(mtd))
|
+ if (IS_ERR(mtd))
|
||||||
+ return;
|
+ return;
|
||||||
+
|
+
|
||||||
|
+ /* get the first not bad block */
|
||||||
|
+ if (mtd_can_have_bb(mtd))
|
||||||
|
+ while (mtd_block_isbad(mtd, offset)) {
|
||||||
|
+ offset += mtd->erasesize;
|
||||||
|
+
|
||||||
|
+ if (offset > mtd->size) {
|
||||||
|
+ pr_err("UBI error: Failed to find a non-bad "
|
||||||
|
+ "block on mtd%d\n", mtd->index);
|
||||||
|
+ goto cleanup;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+ /* check for a valid ubi magic if read from flash was successful */
|
+ /* check for a valid ubi magic if read from flash was successful */
|
||||||
+ err = mtd_read(mtd, 0, 4, &len, (void *) magic);
|
+ err = mtd_read(mtd, offset, 4, &len, (void *) magic);
|
||||||
+ if (!err && len == 4 && strncmp(magic, "UBI#", 4)) {
|
+ if ((!err || mtd_is_bitflip(err)) &&
|
||||||
|
+ len == 4 && strncmp(magic, "UBI#", 4)) {
|
||||||
+ pr_err("UBI error: no valid UBI magic found inside mtd%d\n", mtd->index);
|
+ pr_err("UBI error: no valid UBI magic found inside mtd%d\n", mtd->index);
|
||||||
+ goto cleanup;
|
+ goto cleanup;
|
||||||
+ }
|
+ }
|
||||||
|
@ -63,7 +77,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
static int __init ubi_init(void)
|
static int __init ubi_init(void)
|
||||||
{
|
{
|
||||||
int err, i, k;
|
int err, i, k;
|
||||||
@@ -1254,6 +1302,12 @@ static int __init ubi_init(void)
|
@@ -1254,6 +1316,12 @@ static int __init ubi_init(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
|
|
||||||
--- a/drivers/mtd/ubi/build.c
|
--- a/drivers/mtd/ubi/build.c
|
||||||
+++ b/drivers/mtd/ubi/build.c
|
+++ b/drivers/mtd/ubi/build.c
|
||||||
@@ -1226,6 +1226,54 @@ static struct mtd_info * __init open_mtd
|
@@ -1226,6 +1226,68 @@ static struct mtd_info * __init open_mtd
|
||||||
return mtd;
|
return mtd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
+{
|
+{
|
||||||
+ int err;
|
+ int err;
|
||||||
+ struct mtd_info *mtd;
|
+ struct mtd_info *mtd;
|
||||||
|
+ loff_t offset = 0;
|
||||||
+ size_t len;
|
+ size_t len;
|
||||||
+ char magic[4];
|
+ char magic[4];
|
||||||
+
|
+
|
||||||
|
@ -31,9 +32,22 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
+ if (IS_ERR(mtd))
|
+ if (IS_ERR(mtd))
|
||||||
+ return;
|
+ return;
|
||||||
+
|
+
|
||||||
|
+ /* get the first not bad block */
|
||||||
|
+ if (mtd_can_have_bb(mtd))
|
||||||
|
+ while (mtd_block_isbad(mtd, offset)) {
|
||||||
|
+ offset += mtd->erasesize;
|
||||||
|
+
|
||||||
|
+ if (offset > mtd->size) {
|
||||||
|
+ pr_err("UBI error: Failed to find a non-bad "
|
||||||
|
+ "block on mtd%d\n", mtd->index);
|
||||||
|
+ goto cleanup;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+ /* check for a valid ubi magic if read from flash was successful */
|
+ /* check for a valid ubi magic if read from flash was successful */
|
||||||
+ err = mtd_read(mtd, 0, 4, &len, (void *) magic);
|
+ err = mtd_read(mtd, offset, 4, &len, (void *) magic);
|
||||||
+ if (!err && len == 4 && strncmp(magic, "UBI#", 4)) {
|
+ if ((!err || mtd_is_bitflip(err)) &&
|
||||||
|
+ len == 4 && strncmp(magic, "UBI#", 4)) {
|
||||||
+ pr_err("UBI error: no valid UBI magic found inside mtd%d\n", mtd->index);
|
+ pr_err("UBI error: no valid UBI magic found inside mtd%d\n", mtd->index);
|
||||||
+ goto cleanup;
|
+ goto cleanup;
|
||||||
+ }
|
+ }
|
||||||
|
@ -63,7 +77,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
static int __init ubi_init(void)
|
static int __init ubi_init(void)
|
||||||
{
|
{
|
||||||
int err, i, k;
|
int err, i, k;
|
||||||
@@ -1309,6 +1357,12 @@ static int __init ubi_init(void)
|
@@ -1309,6 +1371,12 @@ static int __init ubi_init(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue