aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2009-07-24 09:18:04 -0400
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2009-08-14 13:02:20 -0400
commitde75c771b4cc4da963164a538a8448128301bc35 (patch)
treea8fea3a1a6c68324b0b425c482f3c2ef5c7d1b22 /drivers/mtd/ubi
parent867996b15c1f0a98d2c405bada907e97499ba8c2 (diff)
UBI: improve NOR flash erasure quirk
More testing of NOR flash against power cuts showed that sometimes eraseblocks may be unwritable, and we cannot really invalidate them before erasure. But in this case the eraseblock probably contains garbage anyway, and we do not have to invalidate the headers. This assumption might be not true, but this is at least what I have observed. So if we cannot invalidate the headers, we make sure that the PEB does not contain valid VID header. If this is true, everything is fine, otherwise we panic.
Diffstat (limited to 'drivers/mtd/ubi')
-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 b693138fc519..8aa51e7a6a7d 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -476,30 +476,46 @@ out:
476 */ 476 */
477static int nor_erase_prepare(struct ubi_device *ubi, int pnum) 477static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
478{ 478{
479 int err; 479 int err, err1;
480 size_t written; 480 size_t written;
481 loff_t addr; 481 loff_t addr;
482 uint32_t data = 0; 482 uint32_t data = 0;
483 struct ubi_vid_hdr vid_hdr;
483 484
484 addr = (loff_t)pnum * ubi->peb_size + ubi->vid_hdr_aloffset; 485 addr = (loff_t)pnum * ubi->peb_size + ubi->vid_hdr_aloffset;
485 err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data); 486 err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);
486 if (err) { 487 if (!err) {
487 ubi_err("error %d while writing 4 bytes to PEB %d:%d, written " 488 addr -= ubi->vid_hdr_aloffset;
488 "%zd bytes", err, pnum, ubi->vid_hdr_aloffset, written); 489 err = ubi->mtd->write(ubi->mtd, addr, 4, &written,
489 ubi_dbg_dump_stack(); 490 (void *)&data);
490 return err; 491 if (!err)
492 return 0;
491 } 493 }
492 494
493 addr -= ubi->vid_hdr_aloffset; 495 /*
494 err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data); 496 * We failed to write to the media. This was observed with Spansion
495 if (err) { 497 * S29GL512N NOR flash. Most probably the eraseblock erasure was
496 ubi_err("error %d while writing 4 bytes to PEB %d:%d, written " 498 * interrupted at a very inappropriate moment, so it became unwritable.
497 "%zd bytes", err, pnum, 0, written); 499 * In this case we probably anyway have garbage in this PEB.
498 ubi_dbg_dump_stack(); 500 */
499 return err; 501 err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
500 } 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;
501 509
502 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;
503} 519}
504 520
505/** 521/**