UBI: improve NOR flash erasure quirk
More testing of NOR flash against power cuts showed that sometimes eraseblocks may be unwritable, and we cannot really invalidate them before erasure. But in this case the eraseblock probably contains garbage anyway, and we do not have to invalidate the headers. This assumption might be not true, but this is at least what I have observed. So if we cannot invalidate the headers, we make sure that the PEB does not contain valid VID header. If this is true, everything is fine, otherwise we panic.
This commit is contained in:
Родитель
867996b15c
Коммит
de75c771b4
|
@ -476,30 +476,46 @@ out:
|
|||
*/
|
||||
static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
|
||||
{
|
||||
int err;
|
||||
int err, err1;
|
||||
size_t written;
|
||||
loff_t addr;
|
||||
uint32_t data = 0;
|
||||
struct ubi_vid_hdr vid_hdr;
|
||||
|
||||
addr = (loff_t)pnum * ubi->peb_size + ubi->vid_hdr_aloffset;
|
||||
err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&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;
|
||||
if (!err) {
|
||||
addr -= ubi->vid_hdr_aloffset;
|
||||
err = ubi->mtd->write(ubi->mtd, addr, 4, &written,
|
||||
(void *)&data);
|
||||
if (!err)
|
||||
return 0;
|
||||
}
|
||||
|
||||
addr -= ubi->vid_hdr_aloffset;
|
||||
err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);
|
||||
if (err) {
|
||||
ubi_err("error %d while writing 4 bytes to PEB %d:%d, written "
|
||||
"%zd bytes", err, pnum, 0, written);
|
||||
ubi_dbg_dump_stack();
|
||||
return err;
|
||||
}
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
|
||||
if (err1 == UBI_IO_BAD_VID_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;
|
||||
|
||||
return 0;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
ubi_err("cannot invalidate PEB %d, write returned %d read returned %d",
|
||||
pnum, err, err1);
|
||||
ubi_dbg_dump_flash(ubi, pnum, 0, ubi->peb_size);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче