aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/ubi/io.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index b693138fc51..8aa51e7a6a7 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -476,30 +476,46 @@ out:
*/
static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
{
- int err;
+ int err, err1;
size_t written;
loff_t addr;
uint32_t data = 0;
+ struct ubi_vid_hdr vid_hdr;
addr = (loff_t)pnum * ubi->peb_size + ubi->vid_hdr_aloffset;
err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);
- if (err) {
- ubi_err("error %d while writing 4 bytes to PEB %d:%d, written "
- "%zd bytes", err, pnum, ubi->vid_hdr_aloffset, written);
- ubi_dbg_dump_stack();
- return err;
+ if (!err) {
+ addr -= ubi->vid_hdr_aloffset;
+ err = ubi->mtd->write(ubi->mtd, addr, 4, &written,
+ (void *)&data);
+ if (!err)
+ return 0;
}
- addr -= ubi->vid_hdr_aloffset;
- err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);
- if (err) {
- ubi_err("error %d while writing 4 bytes to PEB %d:%d, written "
- "%zd bytes", err, pnum, 0, written);
- ubi_dbg_dump_stack();
- return err;
- }
+ /*
+ * We failed to write to the media. This was observed with Spansion
+ * S29GL512N NOR flash. Most probably the eraseblock erasure was
+ * interrupted at a very inappropriate moment, so it became unwritable.
+ * In this case we probably anyway have garbage in this PEB.
+ */
+ err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
+ if (err1 == UBI_IO_BAD_VID_HDR)
+ /*
+ * The VID header is corrupted, so we can safely erase this
+ * PEB and not afraid that it will be treated as a valid PEB in
+ * case of an unclean reboot.
+ */
+ return 0;
- return 0;
+ /*
+ * The PEB contains a valid VID header, but we cannot invalidate it.
+ * Supposedly the flash media or the driver is screwed up, so return an
+ * error.
+ */
+ ubi_err("cannot invalidate PEB %d, write returned %d read returned %d",
+ pnum, err, err1);
+ ubi_dbg_dump_flash(ubi, pnum, 0, ubi->peb_size);
+ return -EIO;
}
/**