diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2014-10-02 08:54:43 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2014-10-02 08:54:43 +0200 |
commit | 0d03667db7cd6ba227eab02d53e21572ae55e3a8 (patch) | |
tree | 8bb40731002f01de59a657e18f030644233b13b8 /drivers | |
parent | fa93e4fb602389c5a5d6991a86cf93ae6e92d016 (diff) | |
parent | 20e2c9642bdffaf262a4e311d2fea34a4e64a00a (diff) | |
download | barebox-0d03667db7cd6ba227eab02d53e21572ae55e3a8.tar.gz barebox-0d03667db7cd6ba227eab02d53e21572ae55e3a8.tar.xz |
Merge branch 'for-next/ubi'
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mtd/ubi/attach.c | 4 | ||||
-rw-r--r-- | drivers/mtd/ubi/fastmap.c | 12 | ||||
-rw-r--r-- | drivers/mtd/ubi/io.c | 54 | ||||
-rw-r--r-- | drivers/mtd/ubi/vtbl.c | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/wl.c | 10 |
5 files changed, 40 insertions, 42 deletions
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index 54129748ef..d6fe43b83e 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c @@ -1429,8 +1429,10 @@ int ubi_attach(struct ubi_device *ubi, int force_scan) struct ubi_attach_info *scan_ai; scan_ai = alloc_ai("ubi_ckh_aeb_slab_cache"); - if (!scan_ai) + if (!scan_ai) { + err = -ENOMEM; goto out_wl; + } err = scan_all(ubi, scan_ai, 0); if (err) { diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index de68c326da..8f29430e5c 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -127,7 +127,7 @@ static struct ubi_ainf_volume *add_vol(struct ubi_attach_info *ai, int vol_id, if (vol_id > av->vol_id) p = &(*p)->rb_left; - else if (vol_id > av->vol_id) + else p = &(*p)->rb_right; } @@ -422,7 +422,7 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai, pnum, err); ret = err > 0 ? UBI_BAD_FASTMAP : err; goto out; - } else if (ret == UBI_IO_BITFLIPS) + } else if (err == UBI_IO_BITFLIPS) scrub = 1; /* @@ -462,8 +462,8 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai, } } if (found_orphan) { - kfree(tmp_aeb); list_del(&tmp_aeb->u.list); + kfree(tmp_aeb); } new_aeb = kzalloc(sizeof(*new_aeb), GFP_KERNEL); @@ -835,16 +835,16 @@ fail_bad: ret = UBI_BAD_FASTMAP; fail: list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &used, u.list) { - free(tmp_aeb); list_del(&tmp_aeb->u.list); + free(tmp_aeb); } list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &eba_orphans, u.list) { - free(tmp_aeb); list_del(&tmp_aeb->u.list); + free(tmp_aeb); } list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &lfree, u.list) { - free(tmp_aeb); list_del(&tmp_aeb->u.list); + free(tmp_aeb); } return ret; diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index f9f9738e5e..e55dfc5bc2 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -473,10 +473,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 @@ -487,50 +489,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; } diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 48b291529f..c15809a724 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -580,7 +580,7 @@ static int init_volumes(struct ubi_device *ubi, /* Static volumes only */ av = ubi_find_av(ai, i); - if (!av) { + if (!av || !av->leb_count) { /* * No eraseblocks belonging to this volume found. We * don't actually know whether this static volume is diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index c083cac58b..4c20e908ed 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -635,6 +635,8 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi) e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF); self_check_in_wl_tree(ubi, e, &ubi->free); + ubi->free_count--; + ubi_assert(ubi->free_count >= 0); rb_erase(&e->u.rb, &ubi->free); return e; @@ -646,6 +648,9 @@ int ubi_wl_get_peb(struct ubi_device *ubi) peb = __wl_get_peb(ubi); + if (peb < 0) + return peb; + err = ubi_self_check_all_ff(ubi, peb, ubi->vid_hdr_aloffset, ubi->peb_size - ubi->vid_hdr_aloffset); if (err) { @@ -1015,6 +1020,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, /* Give the unused PEB back */ wl_tree_add(e2, &ubi->free); + ubi->free_count++; goto out_cancel; } self_check_in_wl_tree(ubi, e1, &ubi->used); @@ -1611,10 +1617,10 @@ int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum) vol_id, lnum, ubi->works_count); while (found) { - struct ubi_work *wrk; + struct ubi_work *wrk, *tmp; found = 0; - list_for_each_entry(wrk, &ubi->works, list) { + list_for_each_entry_safe(wrk, tmp, &ubi->works, list) { if ((vol_id == UBI_ALL || wrk->vol_id == vol_id) && (lnum == UBI_ALL || wrk->lnum == lnum)) { list_del(&wrk->list); |