diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-30 23:04:09 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-30 23:04:09 -0500 |
commit | 060e8e3b6f8fc0ba97de2276249fbd80fa25b0a2 (patch) | |
tree | f36d3ccd0fa20f98c694c09ab9b07ec3db0a00f6 | |
parent | 271bf66d4c0c8db29764d241e4e46883d9c0a198 (diff) | |
parent | 2c7ca5cc3624e05a5235f70039adce30725972d6 (diff) |
Merge tag 'upstream-3.14-rc1' of git://git.infradead.org/linux-ubifs
Pull ubifs updates from Artem Bityutskiy:
- Improve the NOR erasure quirk - now it tries to do as little writes
as possible, because the eraseblock may be in an "unstable" state and
write operation sometimes causes NOR chip lock-ups.
- Both UBI and UBIFS changes are now maintainer in one single tree,
because the amount of changes dropped significantly.
* tag 'upstream-3.14-rc1' of git://git.infradead.org/linux-ubifs:
UBI: avoid program operation on NOR flash after erasure interrupted
MAINTAINERS: keep UBI and UBIFS stuff in the same tree
UBI: fix error return code
-rw-r--r-- | MAINTAINERS | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/attach.c | 4 | ||||
-rw-r--r-- | drivers/mtd/ubi/build.c | 4 | ||||
-rw-r--r-- | drivers/mtd/ubi/io.c | 54 |
4 files changed, 29 insertions, 35 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index b5795f031b3e..5f840aeab64d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -8960,7 +8960,7 @@ UNSORTED BLOCK IMAGES (UBI) | |||
8960 | M: Artem Bityutskiy <dedekind1@gmail.com> | 8960 | M: Artem Bityutskiy <dedekind1@gmail.com> |
8961 | W: http://www.linux-mtd.infradead.org/ | 8961 | W: http://www.linux-mtd.infradead.org/ |
8962 | L: linux-mtd@lists.infradead.org | 8962 | L: linux-mtd@lists.infradead.org |
8963 | T: git git://git.infradead.org/ubi-2.6.git | 8963 | T: git git://git.infradead.org/ubifs-2.6.git |
8964 | S: Maintained | 8964 | S: Maintained |
8965 | F: drivers/mtd/ubi/ | 8965 | F: drivers/mtd/ubi/ |
8966 | F: include/linux/mtd/ubi.h | 8966 | F: include/linux/mtd/ubi.h |
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index 33bb1f2b63e4..6f27d9a1be3b 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c | |||
@@ -1453,8 +1453,10 @@ int ubi_attach(struct ubi_device *ubi, int force_scan) | |||
1453 | struct ubi_attach_info *scan_ai; | 1453 | struct ubi_attach_info *scan_ai; |
1454 | 1454 | ||
1455 | scan_ai = alloc_ai("ubi_ckh_aeb_slab_cache"); | 1455 | scan_ai = alloc_ai("ubi_ckh_aeb_slab_cache"); |
1456 | if (!scan_ai) | 1456 | if (!scan_ai) { |
1457 | err = -ENOMEM; | ||
1457 | goto out_wl; | 1458 | goto out_wl; |
1459 | } | ||
1458 | 1460 | ||
1459 | err = scan_all(ubi, scan_ai, 0); | 1461 | err = scan_all(ubi, scan_ai, 0); |
1460 | if (err) { | 1462 | if (err) { |
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index e05dc6298c1d..57deae961429 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
@@ -1245,8 +1245,10 @@ static int __init ubi_init(void) | |||
1245 | ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab", | 1245 | ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab", |
1246 | sizeof(struct ubi_wl_entry), | 1246 | sizeof(struct ubi_wl_entry), |
1247 | 0, 0, NULL); | 1247 | 0, 0, NULL); |
1248 | if (!ubi_wl_entry_slab) | 1248 | if (!ubi_wl_entry_slab) { |
1249 | err = -ENOMEM; | ||
1249 | goto out_dev_unreg; | 1250 | goto out_dev_unreg; |
1251 | } | ||
1250 | 1252 | ||
1251 | err = ubi_debugfs_init(); | 1253 | err = ubi_debugfs_init(); |
1252 | if (err) | 1254 | if (err) |
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index bf79def40126..d36134925d31 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c | |||
@@ -495,10 +495,12 @@ out: | |||
495 | */ | 495 | */ |
496 | static int nor_erase_prepare(struct ubi_device *ubi, int pnum) | 496 | static int nor_erase_prepare(struct ubi_device *ubi, int pnum) |
497 | { | 497 | { |
498 | int err, err1; | 498 | int err; |
499 | size_t written; | 499 | size_t written; |
500 | loff_t addr; | 500 | loff_t addr; |
501 | uint32_t data = 0; | 501 | uint32_t data = 0; |
502 | struct ubi_ec_hdr ec_hdr; | ||
503 | |||
502 | /* | 504 | /* |
503 | * Note, we cannot generally define VID header buffers on stack, | 505 | * Note, we cannot generally define VID header buffers on stack, |
504 | * because of the way we deal with these buffers (see the header | 506 | * 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) | |||
509 | struct ubi_vid_hdr vid_hdr; | 511 | struct ubi_vid_hdr vid_hdr; |
510 | 512 | ||
511 | /* | 513 | /* |
514 | * If VID or EC is valid, we have to corrupt them before erasing. | ||
512 | * It is important to first invalidate the EC header, and then the VID | 515 | * It is important to first invalidate the EC header, and then the VID |
513 | * header. Otherwise a power cut may lead to valid EC header and | 516 | * header. Otherwise a power cut may lead to valid EC header and |
514 | * invalid VID header, in which case UBI will treat this PEB as | 517 | * invalid VID header, in which case UBI will treat this PEB as |
515 | * corrupted and will try to preserve it, and print scary warnings. | 518 | * corrupted and will try to preserve it, and print scary warnings. |
516 | */ | 519 | */ |
517 | addr = (loff_t)pnum * ubi->peb_size; | 520 | addr = (loff_t)pnum * ubi->peb_size; |
518 | err = mtd_write(ubi->mtd, addr, 4, &written, (void *)&data); | 521 | err = ubi_io_read_ec_hdr(ubi, pnum, &ec_hdr, 0); |
519 | if (!err) { | 522 | if (err != UBI_IO_BAD_HDR_EBADMSG && err != UBI_IO_BAD_HDR && |
520 | addr += ubi->vid_hdr_aloffset; | 523 | err != UBI_IO_FF){ |
521 | err = mtd_write(ubi->mtd, addr, 4, &written, (void *)&data); | 524 | err = mtd_write(ubi->mtd, addr, 4, &written, (void *)&data); |
522 | if (!err) | 525 | if(err) |
523 | return 0; | 526 | goto error; |
524 | } | 527 | } |
525 | 528 | ||
526 | /* | 529 | err = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0); |
527 | * We failed to write to the media. This was observed with Spansion | 530 | if (err != UBI_IO_BAD_HDR_EBADMSG && err != UBI_IO_BAD_HDR && |
528 | * S29GL512N NOR flash. Most probably the previously eraseblock erasure | 531 | err != UBI_IO_FF){ |
529 | * was interrupted at a very inappropriate moment, so it became | 532 | addr += ubi->vid_hdr_aloffset; |
530 | * unwritable. In this case we probably anyway have garbage in this | 533 | err = mtd_write(ubi->mtd, addr, 4, &written, (void *)&data); |
531 | * PEB. | 534 | if (err) |
532 | */ | 535 | goto error; |
533 | err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0); | ||
534 | if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR || | ||
535 | err1 == UBI_IO_FF) { | ||
536 | struct ubi_ec_hdr ec_hdr; | ||
537 | |||
538 | err1 = ubi_io_read_ec_hdr(ubi, pnum, &ec_hdr, 0); | ||
539 | if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR || | ||
540 | err1 == UBI_IO_FF) | ||
541 | /* | ||
542 | * Both VID and EC headers are corrupted, so we can | ||
543 | * safely erase this PEB and not afraid that it will be | ||
544 | * treated as a valid PEB in case of an unclean reboot. | ||
545 | */ | ||
546 | return 0; | ||
547 | } | 536 | } |
537 | return 0; | ||
548 | 538 | ||
539 | error: | ||
549 | /* | 540 | /* |
550 | * The PEB contains a valid VID header, but we cannot invalidate it. | 541 | * The PEB contains a valid VID or EC header, but we cannot invalidate |
551 | * Supposedly the flash media or the driver is screwed up, so return an | 542 | * it. Supposedly the flash media or the driver is screwed up, so |
552 | * error. | 543 | * return an error. |
553 | */ | 544 | */ |
554 | ubi_err("cannot invalidate PEB %d, write returned %d read returned %d", | 545 | ubi_err("cannot invalidate PEB %d, write returned %d", pnum, err); |
555 | pnum, err, err1); | ||
556 | ubi_dump_flash(ubi, pnum, 0, ubi->peb_size); | 546 | ubi_dump_flash(ubi, pnum, 0, ubi->peb_size); |
557 | return -EIO; | 547 | return -EIO; |
558 | } | 548 | } |