summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/io.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-12-13 09:29:52 +0100
committerTakashi Iwai <tiwai@suse.de>2010-12-13 09:29:52 +0100
commit354d14b3f53cc749c5d26d4ba7280d1e931d6bc4 (patch)
tree59b597e44902d8db8bde7deac1e7e707327c6fe6 /drivers/mtd/ubi/io.c
parent5144c534d16529bc469396211131e8935589f833 (diff)
parent5b84ba26a9672e615897234fa5efd3eea2d6b295 (diff)
downloadlinux-stable-354d14b3f53cc749c5d26d4ba7280d1e931d6bc4.tar.gz
linux-stable-354d14b3f53cc749c5d26d4ba7280d1e931d6bc4.tar.bz2
linux-stable-354d14b3f53cc749c5d26d4ba7280d1e931d6bc4.zip
Merge branch 'topic/workq-update' into topic/misc
Diffstat (limited to 'drivers/mtd/ubi/io.c')
-rw-r--r--drivers/mtd/ubi/io.c37
1 files changed, 25 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)
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.