Commit e834402fa09de8537ab850b971f6e468e3430593
Committed by
Scott Wood
1 parent
98d9d92359
Exists in
master
and in
53 other branches
nand: adjust erase/read/write partition/chip size for bad blocks
Adjust the sizes calculated for whole partition/chip operations by removing the size of bad blocks so we don't try to erase/read/write past a partition/chip boundary. Signed-off-by: Harvey Chapman <hchapman@3gfp.com>
Showing 1 changed file with 35 additions and 0 deletions Side-by-side Diff
common/cmd_nand.c
... | ... | @@ -425,6 +425,31 @@ |
425 | 425 | return ret; |
426 | 426 | } |
427 | 427 | |
428 | +/* Adjust a chip/partition size down for bad blocks so we don't | |
429 | + * read/write/erase past the end of a chip/partition by accident. | |
430 | + */ | |
431 | +static void adjust_size_for_badblocks(loff_t *size, loff_t offset, int dev) | |
432 | +{ | |
433 | + /* We grab the nand info object here fresh because this is usually | |
434 | + * called after arg_off_size() which can change the value of dev. | |
435 | + */ | |
436 | + nand_info_t *nand = &nand_info[dev]; | |
437 | + loff_t maxoffset = offset + *size; | |
438 | + int badblocks = 0; | |
439 | + | |
440 | + /* count badblocks in NAND from offset to offset + size */ | |
441 | + for (; offset < maxoffset; offset += nand->erasesize) { | |
442 | + if (nand_block_isbad(nand, offset)) | |
443 | + badblocks++; | |
444 | + } | |
445 | + /* adjust size if any bad blocks found */ | |
446 | + if (badblocks) { | |
447 | + *size -= badblocks * nand->erasesize; | |
448 | + printf("size adjusted to 0x%llx (%d bad blocks)\n", | |
449 | + (unsigned long long)*size, badblocks); | |
450 | + } | |
451 | +} | |
452 | + | |
428 | 453 | static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
429 | 454 | { |
430 | 455 | int i, ret = 0; |
... | ... | @@ -521,6 +546,7 @@ |
521 | 546 | int scrub = !strncmp(cmd, "scrub", 5); |
522 | 547 | int spread = 0; |
523 | 548 | int args = 2; |
549 | + int adjust_size = 0; | |
524 | 550 | const char *scrub_warn = |
525 | 551 | "Warning: " |
526 | 552 | "scrub option will erase all factory set bad blocks!\n" |
527 | 553 | |
... | ... | @@ -537,8 +563,10 @@ |
537 | 563 | spread = 1; |
538 | 564 | } else if (!strcmp(&cmd[5], ".part")) { |
539 | 565 | args = 1; |
566 | + adjust_size = 1; | |
540 | 567 | } else if (!strcmp(&cmd[5], ".chip")) { |
541 | 568 | args = 0; |
569 | + adjust_size = 1; | |
542 | 570 | } else { |
543 | 571 | goto usage; |
544 | 572 | } |
... | ... | @@ -558,6 +586,10 @@ |
558 | 586 | &maxsize) != 0) |
559 | 587 | return 1; |
560 | 588 | |
589 | + /* size is unspecified */ | |
590 | + if (adjust_size && !scrub) | |
591 | + adjust_size_for_badblocks(&size, off, dev); | |
592 | + | |
561 | 593 | nand = &nand_info[dev]; |
562 | 594 | |
563 | 595 | memset(&opts, 0, sizeof(opts)); |
... | ... | @@ -642,6 +674,9 @@ |
642 | 674 | &off, &size, &maxsize) != 0) |
643 | 675 | return 1; |
644 | 676 | |
677 | + /* size is unspecified */ | |
678 | + if (argc < 5) | |
679 | + adjust_size_for_badblocks(&size, off, dev); | |
645 | 680 | rwsize = size; |
646 | 681 | } |
647 | 682 |