diff options
Diffstat (limited to 'drivers/mtd/ubi/io.c')
| -rw-r--r-- | drivers/mtd/ubi/io.c | 37 | 
1 files changed, 25 insertions, 12 deletions
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index c2960ac9f39..811775aa8ee 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)  	uint32_t data = 0;  	struct ubi_vid_hdr vid_hdr; -	addr = (loff_t)pnum * ubi->peb_size + ubi->vid_hdr_aloffset; +	/* +	 * It is important to first invalidate the EC header, and then the VID +	 * header. Otherwise a power cut may lead to valid EC header and +	 * invalid VID header, in which case UBI will treat this PEB as +	 * corrupted and will try to preserve it, and print scary warnings (see +	 * the header comment in scan.c for more information). +	 */ +	addr = (loff_t)pnum * ubi->peb_size;  	err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);  	if (!err) { -		addr -= ubi->vid_hdr_aloffset; +		addr += ubi->vid_hdr_aloffset;  		err = ubi->mtd->write(ubi->mtd, addr, 4, &written,  				      (void *)&data);  		if (!err) @@ -494,18 +501,24 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)  	/*  	 * We failed to write to the media. This was observed with Spansion -	 * S29GL512N NOR flash. Most probably the eraseblock erasure was -	 * interrupted at a very inappropriate moment, so it became unwritable. -	 * In this case we probably anyway have garbage in this PEB. +	 * S29GL512N NOR flash. Most probably the previously eraseblock erasure +	 * was interrupted at a very inappropriate moment, so it became +	 * unwritable. In this case we probably anyway have garbage in this +	 * PEB.  	 */  	err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0); -	if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR) -		/* -		 * The VID header is corrupted, so we can safely erase this -		 * PEB and not afraid that it will be treated as a valid PEB in -		 * case of an unclean reboot. -		 */ -		return 0; +	if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR) { +		struct ubi_ec_hdr ec_hdr; + +		err1 = ubi_io_read_ec_hdr(ubi, pnum, &ec_hdr, 0); +		if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR) +			/* +			 * Both VID and EC headers are corrupted, so we can +			 * safely erase this PEB and not afraid that it will be +			 * treated as a valid PEB in case of an unclean reboot. +			 */ +			return 0; +	}  	/*  	 * The PEB contains a valid VID header, but we cannot invalidate it.  |