Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 155311
b: refs/heads/master
c: ebf53f4
h: refs/heads/master
i:
  155309: 847ea70
  155307: 0c94df2
  155303: e3eb302
  155295: 384d4f6
v: v3
  • Loading branch information
Artem Bityutskiy authored and Artem Bityutskiy committed Jul 7, 2009
1 parent e8df1ec commit a75926f
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: fe96efc1a3c049f0a1bcd9b65e0faeb751ce5ec6
refs/heads/master: ebf53f421308c2f59c9bcbad4c5c297a0d00199a
5 changes: 5 additions & 0 deletions trunk/drivers/mtd/ubi/build.c
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,11 @@ static int io_init(struct ubi_device *ubi)
if (ubi->mtd->block_isbad && ubi->mtd->block_markbad)
ubi->bad_allowed = 1;

if (ubi->mtd->type == MTD_NORFLASH) {
ubi_assert(ubi->mtd->writesize == 1);
ubi->nor_flash = 1;
}

ubi->min_io_size = ubi->mtd->writesize;
ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;

Expand Down
58 changes: 56 additions & 2 deletions trunk/drivers/mtd/ubi/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,8 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
addr = (loff_t)pnum * ubi->peb_size + offset;
err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf);
if (err) {
ubi_err("error %d while writing %d bytes to PEB %d:%d, written"
" %zd bytes", err, len, pnum, offset, written);
ubi_err("error %d while writing %d bytes to PEB %d:%d, written "
"%zd bytes", err, len, pnum, offset, written);
ubi_dbg_dump_stack();
} else
ubi_assert(written == len);
Expand Down Expand Up @@ -453,6 +453,54 @@ static int torture_peb(struct ubi_device *ubi, int pnum)
return err;
}

/**
* nor_erase_prepare - prepare a NOR flash PEB for erasure.
* @ubi: UBI device description object
* @pnum: physical eraseblock number to prepare
*
* NOR flash, or at least some of them, have peculiar embedded PEB erasure
* algorithm: the PEB is first filled with zeroes, then it is erased. And
* filling with zeroes starts from the end of the PEB. This was observed with
* Spansion S29GL512N NOR flash.
*
* This means that in case of a power cut we may end up with intact data at the
* beginning of the PEB, and all zeroes at the end of PEB. In other words, the
* EC and VID headers are OK, but a large chunk of data at the end of PEB is
* zeroed. This makes UBI mistakenly treat this PEB as used and associate it
* with an LEB, which leads to subsequent failures (e.g., UBIFS fails).
*
* This function is called before erasing NOR PEBs and it zeroes out EC and VID
* magic numbers in order to invalidate them and prevent the failures. Returns
* zero in case of success and a negative error code in case of failure.
*/
static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
{
int err;
size_t written;
loff_t addr;
uint32_t data = 0;

addr = (loff_t)pnum * ubi->peb_size;
err = ubi->mtd->write(ubi->mtd, addr, 4, &written, &data);
if (err) {
ubi_err("error %d while writing 4 bytes to PEB %d:0, written "
"%zd bytes", err, pnum, 0, written);
ubi_dbg_dump_stack();
return err;
}

addr += ubi->vid_hdr_aloffset;
err = ubi->mtd->write(ubi->mtd, addr, 4, &written, &data);
if (err) {
ubi_err("error %d while writing 4 bytes to PEB %d:%d, written "
"%zd bytes", err, pnum, ubi->vid_hdr_aloffset, written);
ubi_dbg_dump_stack();
return err;
}

return 0;
}

/**
* ubi_io_sync_erase - synchronously erase a physical eraseblock.
* @ubi: UBI device description object
Expand Down Expand Up @@ -484,6 +532,12 @@ int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture)
return -EROFS;
}

if (ubi->nor_flash) {
err = nor_erase_prepare(ubi, pnum);
if (err)
return err;
}

if (torture) {
ret = torture_peb(ubi, pnum);
if (ret < 0)
Expand Down
4 changes: 3 additions & 1 deletion trunk/drivers/mtd/ubi/ubi.h
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ struct ubi_wl_entry;
* @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset
* @bad_allowed: whether the MTD device admits of bad physical eraseblocks or
* not
* @nor_flash: non-zero if working on top of NOR flash
* @mtd: MTD device descriptor
*
* @peb_buf1: a buffer of PEB size used for different purposes
Expand Down Expand Up @@ -454,7 +455,8 @@ struct ubi_device {
int vid_hdr_offset;
int vid_hdr_aloffset;
int vid_hdr_shift;
int bad_allowed;
unsigned int bad_allowed:1;
unsigned int nor_flash:1;
struct mtd_info *mtd;

void *peb_buf1;
Expand Down

0 comments on commit a75926f

Please sign in to comment.