diff options
Diffstat (limited to 'drivers/mtd/ubi/io.c')
-rw-r--r-- | drivers/mtd/ubi/io.c | 49 |
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 | */ |
476 | static int nor_erase_prepare(struct ubi_device *ubi, int pnum) | 477 | static 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 | /** |