Commit 2c7ca5cc3624e05a5235f70039adce30725972d6

Authored by Qi Wang 王起 (qiwang)
Committed by Artem Bityutskiy
1 parent b6b44e0ad2

UBI: avoid program operation on NOR flash after erasure interrupted

nor_erase_prepare() will be called before erase a NOR flash, it will program '0'
into a block to mark this block. But program data into a erasure interrupted block
can cause program timtout(several minutes at most) error, could impact other
operation on NOR flash. So UBIFS can read this block first to avoid unneeded
program operation.

This patch try to put read operation at head of write operation in
nor_erase_prepare(), read out the data.
If the data is already corrupt, then no need to program any data into this block,
just go to erase this block.

This patch is validated on Micron NOR flash, part number is:JS28F512M29EWHA

Signed-off-by: Qi Wang <qiwang@micron.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>

Showing 1 changed file with 22 additions and 32 deletions Side-by-side Diff

drivers/mtd/ubi/io.c
... ... @@ -495,10 +495,12 @@
495 495 */
496 496 static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
497 497 {
498   - int err, err1;
  498 + int err;
499 499 size_t written;
500 500 loff_t addr;
501 501 uint32_t data = 0;
  502 + struct ubi_ec_hdr ec_hdr;
  503 +
502 504 /*
503 505 * Note, we cannot generally define VID header buffers on stack,
504 506 * because of the way we deal with these buffers (see the header
505 507  
506 508  
507 509  
508 510  
509 511  
510 512  
511 513  
... ... @@ -509,50 +511,38 @@
509 511 struct ubi_vid_hdr vid_hdr;
510 512  
511 513 /*
  514 + * If VID or EC is valid, we have to corrupt them before erasing.
512 515 * It is important to first invalidate the EC header, and then the VID
513 516 * header. Otherwise a power cut may lead to valid EC header and
514 517 * invalid VID header, in which case UBI will treat this PEB as
515 518 * corrupted and will try to preserve it, and print scary warnings.
516 519 */
517 520 addr = (loff_t)pnum * ubi->peb_size;
518   - err = mtd_write(ubi->mtd, addr, 4, &written, (void *)&data);
519   - if (!err) {
520   - addr += ubi->vid_hdr_aloffset;
  521 + err = ubi_io_read_ec_hdr(ubi, pnum, &ec_hdr, 0);
  522 + if (err != UBI_IO_BAD_HDR_EBADMSG && err != UBI_IO_BAD_HDR &&
  523 + err != UBI_IO_FF){
521 524 err = mtd_write(ubi->mtd, addr, 4, &written, (void *)&data);
522   - if (!err)
523   - return 0;
  525 + if(err)
  526 + goto error;
524 527 }
525 528  
526   - /*
527   - * We failed to write to the media. This was observed with Spansion
528   - * S29GL512N NOR flash. Most probably the previously eraseblock erasure
529   - * was interrupted at a very inappropriate moment, so it became
530   - * unwritable. In this case we probably anyway have garbage in this
531   - * PEB.
532   - */
533   - err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
534   - if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR ||
535   - err1 == UBI_IO_FF) {
536   - struct ubi_ec_hdr ec_hdr;
537   -
538   - err1 = ubi_io_read_ec_hdr(ubi, pnum, &ec_hdr, 0);
539   - if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR ||
540   - err1 == UBI_IO_FF)
541   - /*
542   - * Both VID and EC headers are corrupted, so we can
543   - * safely erase this PEB and not afraid that it will be
544   - * treated as a valid PEB in case of an unclean reboot.
545   - */
546   - return 0;
  529 + err = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
  530 + if (err != UBI_IO_BAD_HDR_EBADMSG && err != UBI_IO_BAD_HDR &&
  531 + err != UBI_IO_FF){
  532 + addr += ubi->vid_hdr_aloffset;
  533 + err = mtd_write(ubi->mtd, addr, 4, &written, (void *)&data);
  534 + if (err)
  535 + goto error;
547 536 }
  537 + return 0;
548 538  
  539 +error:
549 540 /*
550   - * The PEB contains a valid VID header, but we cannot invalidate it.
551   - * Supposedly the flash media or the driver is screwed up, so return an
552   - * error.
  541 + * The PEB contains a valid VID or EC header, but we cannot invalidate
  542 + * it. Supposedly the flash media or the driver is screwed up, so
  543 + * return an error.
553 544 */
554   - ubi_err("cannot invalidate PEB %d, write returned %d read returned %d",
555   - pnum, err, err1);
  545 + ubi_err("cannot invalidate PEB %d, write returned %d", pnum, err);
556 546 ubi_dump_flash(ubi, pnum, 0, ubi->peb_size);
557 547 return -EIO;
558 548 }