diff options
| -rw-r--r-- | drivers/mtd/ubi/io.c | 37 | ||||
| -rw-r--r-- | drivers/mtd/ubi/scan.c | 4 |
2 files changed, 29 insertions, 12 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 204345be8e62..79ca304fc4db 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c | |||
| @@ -953,6 +953,10 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, | |||
| 953 | * impossible to distinguish it from a PEB which just | 953 | * impossible to distinguish it from a PEB which just |
| 954 | * contains garbage because of a power cut during erase | 954 | * contains garbage because of a power cut during erase |
| 955 | * 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. | ||
| 956 | */ | 960 | */ |
| 957 | err = 0; | 961 | err = 0; |
| 958 | else | 962 | else |
