diff options
Diffstat (limited to 'drivers/mtd/ubi/io.c')
| -rw-r--r-- | drivers/mtd/ubi/io.c | 54 | 
1 files changed, 22 insertions, 32 deletions
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index bf79def4012..d36134925d3 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -495,10 +495,12 @@ out:   */  static int nor_erase_prepare(struct ubi_device *ubi, int pnum)  { -	int err, err1; +	int err;  	size_t written;  	loff_t addr;  	uint32_t data = 0; +	struct ubi_ec_hdr ec_hdr; +  	/*  	 * Note, we cannot generally define VID header buffers on stack,  	 * because of the way we deal with these buffers (see the header @@ -509,50 +511,38 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)  	struct ubi_vid_hdr vid_hdr;  	/* +	 * If VID or EC is valid, we have to corrupt them before erasing.  	 * 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.  	 */  	addr = (loff_t)pnum * ubi->peb_size; -	err = mtd_write(ubi->mtd, addr, 4, &written, (void *)&data); -	if (!err) { -		addr += ubi->vid_hdr_aloffset; +	err = ubi_io_read_ec_hdr(ubi, pnum, &ec_hdr, 0); +	if (err != UBI_IO_BAD_HDR_EBADMSG && err != UBI_IO_BAD_HDR && +	    err != UBI_IO_FF){  		err = mtd_write(ubi->mtd, addr, 4, &written, (void *)&data); -		if (!err) -			return 0; +		if(err) +			goto error;  	} -	/* -	 * We failed to write to the media. This was observed with Spansion -	 * 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 || -	    err1 == UBI_IO_FF) { -		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 || -		    err1 == UBI_IO_FF) -			/* -			 * 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; +	err = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0); +	if (err != UBI_IO_BAD_HDR_EBADMSG && err != UBI_IO_BAD_HDR && +	    err != UBI_IO_FF){ +		addr += ubi->vid_hdr_aloffset; +		err = mtd_write(ubi->mtd, addr, 4, &written, (void *)&data); +		if (err) +			goto error;  	} +	return 0; +error:  	/* -	 * The PEB contains a valid VID header, but we cannot invalidate it. -	 * Supposedly the flash media or the driver is screwed up, so return an -	 * error. +	 * The PEB contains a valid VID or EC header, but we cannot invalidate +	 * it. Supposedly the flash media or the driver is screwed up, so +	 * return an error.  	 */ -	ubi_err("cannot invalidate PEB %d, write returned %d read returned %d", -		pnum, err, err1); +	ubi_err("cannot invalidate PEB %d, write returned %d", pnum, err);  	ubi_dump_flash(ubi, pnum, 0, ubi->peb_size);  	return -EIO;  }  | 
