diff options
Diffstat (limited to 'drivers/mtd/ubi')
-rw-r--r-- | drivers/mtd/ubi/io.c | 37 | ||||
-rw-r--r-- | drivers/mtd/ubi/scan.c | 20 |
2 files changed, 38 insertions, 19 deletions
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index c2960ac9f39c..811775aa8ee8 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c | |||
@@ -482,10 +482,17 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum) | |||
482 | uint32_t data = 0; | 482 | uint32_t data = 0; |
483 | struct ubi_vid_hdr vid_hdr; | 483 | struct ubi_vid_hdr vid_hdr; |
484 | 484 | ||
485 | addr = (loff_t)pnum * ubi->peb_size + ubi->vid_hdr_aloffset; | 485 | /* |
486 | * It is important to first invalidate the EC header, and then the VID | ||
487 | * header. Otherwise a power cut may lead to valid EC header and | ||
488 | * invalid VID header, in which case UBI will treat this PEB as | ||
489 | * corrupted and will try to preserve it, and print scary warnings (see | ||
490 | * the header comment in scan.c for more information). | ||
491 | */ | ||
492 | addr = (loff_t)pnum * ubi->peb_size; | ||
486 | err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data); | 493 | err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data); |
487 | if (!err) { | 494 | if (!err) { |
488 | addr -= ubi->vid_hdr_aloffset; | 495 | addr += ubi->vid_hdr_aloffset; |
489 | err = ubi->mtd->write(ubi->mtd, addr, 4, &written, | 496 | err = ubi->mtd->write(ubi->mtd, addr, 4, &written, |
490 | (void *)&data); | 497 | (void *)&data); |
491 | if (!err) | 498 | if (!err) |
@@ -494,18 +501,24 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum) | |||
494 | 501 | ||
495 | /* | 502 | /* |
496 | * We failed to write to the media. This was observed with Spansion | 503 | * We failed to write to the media. This was observed with Spansion |
497 | * S29GL512N NOR flash. Most probably the eraseblock erasure was | 504 | * S29GL512N NOR flash. Most probably the previously eraseblock erasure |
498 | * interrupted at a very inappropriate moment, so it became unwritable. | 505 | * was interrupted at a very inappropriate moment, so it became |
499 | * In this case we probably anyway have garbage in this PEB. | 506 | * unwritable. In this case we probably anyway have garbage in this |
507 | * PEB. | ||
500 | */ | 508 | */ |
501 | err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0); | 509 | err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0); |
502 | if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR) | 510 | if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR) { |
503 | /* | 511 | struct ubi_ec_hdr ec_hdr; |
504 | * The VID header is corrupted, so we can safely erase this | 512 | |
505 | * PEB and not afraid that it will be treated as a valid PEB in | 513 | err1 = ubi_io_read_ec_hdr(ubi, pnum, &ec_hdr, 0); |
506 | * case of an unclean reboot. | 514 | if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR) |
507 | */ | 515 | /* |
508 | return 0; | 516 | * Both VID and EC headers are corrupted, so we can |
517 | * safely erase this PEB and not afraid that it will be | ||
518 | * treated as a valid PEB in case of an unclean reboot. | ||
519 | */ | ||
520 | return 0; | ||
521 | } | ||
509 | 522 | ||
510 | /* | 523 | /* |
511 | * The PEB contains a valid VID header, but we cannot invalidate it. | 524 | * The PEB contains a valid VID header, but we cannot invalidate it. |
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 3c631863bf40..79ca304fc4db 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c | |||
@@ -787,16 +787,15 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr, | |||
787 | * erased, so it became unstable and corrupted, and should be | 787 | * erased, so it became unstable and corrupted, and should be |
788 | * erased. | 788 | * erased. |
789 | */ | 789 | */ |
790 | return 0; | 790 | err = 0; |
791 | goto out_unlock; | ||
791 | } | 792 | } |
792 | 793 | ||
793 | if (err) | 794 | if (err) |
794 | return err; | 795 | goto out_unlock; |
795 | 796 | ||
796 | if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size)) { | 797 | if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size)) |
797 | mutex_unlock(&ubi->buf_mutex); | 798 | goto out_unlock; |
798 | return 0; | ||
799 | } | ||
800 | 799 | ||
801 | ubi_err("PEB %d contains corrupted VID header, and the data does not " | 800 | ubi_err("PEB %d contains corrupted VID header, and the data does not " |
802 | "contain all 0xFF, this may be a non-UBI PEB or a severe VID " | 801 | "contain all 0xFF, this may be a non-UBI PEB or a severe VID " |
@@ -806,8 +805,11 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr, | |||
806 | pnum, ubi->leb_start, ubi->leb_size); | 805 | pnum, ubi->leb_start, ubi->leb_size); |
807 | ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, | 806 | ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, |
808 | ubi->peb_buf1, ubi->leb_size, 1); | 807 | ubi->peb_buf1, ubi->leb_size, 1); |
808 | err = 1; | ||
809 | |||
810 | out_unlock: | ||
809 | mutex_unlock(&ubi->buf_mutex); | 811 | mutex_unlock(&ubi->buf_mutex); |
810 | return 1; | 812 | return err; |
811 | } | 813 | } |
812 | 814 | ||
813 | /** | 815 | /** |
@@ -951,6 +953,10 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, | |||
951 | * impossible to distinguish it from a PEB which just | 953 | * impossible to distinguish it from a PEB which just |
952 | * contains garbage because of a power cut during erase | 954 | * contains garbage because of a power cut during erase |
953 | * operation. So we just schedule this PEB for erasure. | 955 | * operation. So we just schedule this PEB for erasure. |
956 | * | ||
957 | * Besides, in case of NOR flash, we deliberatly | ||
958 | * corrupt both headers because NOR flash erasure is | ||
959 | * slow and can start from the end. | ||
954 | */ | 960 | */ |
955 | err = 0; | 961 | err = 0; |
956 | else | 962 | else |