aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/ubi/io.c')
-rw-r--r--drivers/mtd/ubi/io.c49
1 files changed, 33 insertions, 16 deletions
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 4cb69925d8d9..8aa51e7a6a7d 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -269,6 +269,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
269 ubi_err("error %d while writing %d bytes to PEB %d:%d, written " 269 ubi_err("error %d while writing %d bytes to PEB %d:%d, written "
270 "%zd bytes", err, len, pnum, offset, written); 270 "%zd bytes", err, len, pnum, offset, written);
271 ubi_dbg_dump_stack(); 271 ubi_dbg_dump_stack();
272 ubi_dbg_dump_flash(ubi, pnum, offset, len);
272 } else 273 } else
273 ubi_assert(written == len); 274 ubi_assert(written == len);
274 275
@@ -475,30 +476,46 @@ out:
475 */ 476 */
476static int nor_erase_prepare(struct ubi_device *ubi, int pnum) 477static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
477{ 478{
478 int err; 479 int err, err1;
479 size_t written; 480 size_t written;
480 loff_t addr; 481 loff_t addr;
481 uint32_t data = 0; 482 uint32_t data = 0;
483 struct ubi_vid_hdr vid_hdr;
482 484
483 addr = (loff_t)pnum * ubi->peb_size; 485 addr = (loff_t)pnum * ubi->peb_size + ubi->vid_hdr_aloffset;
484 err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data); 486 err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);
485 if (err) { 487 if (!err) {
486 ubi_err("error %d while writing 4 bytes to PEB %d:%d, written " 488 addr -= ubi->vid_hdr_aloffset;
487 "%zd bytes", err, pnum, 0, written); 489 err = ubi->mtd->write(ubi->mtd, addr, 4, &written,
488 ubi_dbg_dump_stack(); 490 (void *)&data);
489 return err; 491 if (!err)
492 return 0;
490 } 493 }
491 494
492 addr += ubi->vid_hdr_aloffset; 495 /*
493 err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data); 496 * We failed to write to the media. This was observed with Spansion
494 if (err) { 497 * S29GL512N NOR flash. Most probably the eraseblock erasure was
495 ubi_err("error %d while writing 4 bytes to PEB %d:%d, written " 498 * interrupted at a very inappropriate moment, so it became unwritable.
496 "%zd bytes", err, pnum, ubi->vid_hdr_aloffset, written); 499 * In this case we probably anyway have garbage in this PEB.
497 ubi_dbg_dump_stack(); 500 */
498 return err; 501 err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
499 } 502 if (err1 == UBI_IO_BAD_VID_HDR)
503 /*
504 * The VID header is corrupted, so we can safely erase this
505 * PEB and not afraid that it will be treated as a valid PEB in
506 * case of an unclean reboot.
507 */
508 return 0;
500 509
501 return 0; 510 /*
511 * The PEB contains a valid VID header, but we cannot invalidate it.
512 * Supposedly the flash media or the driver is screwed up, so return an
513 * error.
514 */
515 ubi_err("cannot invalidate PEB %d, write returned %d read returned %d",
516 pnum, err, err1);
517 ubi_dbg_dump_flash(ubi, pnum, 0, ubi->peb_size);
518 return -EIO;
502} 519}
503 520
504/** 521/**