diff options
Diffstat (limited to 'drivers/mtd/nand/rtc_from4.c')
-rw-r--r-- | drivers/mtd/nand/rtc_from4.c | 62 |
1 files changed, 37 insertions, 25 deletions
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c index 6c97bfaea19a..b7083104a05b 100644 --- a/drivers/mtd/nand/rtc_from4.c +++ b/drivers/mtd/nand/rtc_from4.c | |||
@@ -444,7 +444,8 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha | |||
444 | * note: see pages 34..37 of data sheet for details. | 444 | * note: see pages 34..37 of data sheet for details. |
445 | * | 445 | * |
446 | */ | 446 | */ |
447 | static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page) | 447 | static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, |
448 | int state, int status, int page) | ||
448 | { | 449 | { |
449 | int er_stat = 0; | 450 | int er_stat = 0; |
450 | int rtn, retlen; | 451 | int rtn, retlen; |
@@ -455,39 +456,50 @@ static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int s | |||
455 | this->cmdfunc(mtd, NAND_CMD_STATUS_CLEAR, -1, -1); | 456 | this->cmdfunc(mtd, NAND_CMD_STATUS_CLEAR, -1, -1); |
456 | 457 | ||
457 | if (state == FL_ERASING) { | 458 | if (state == FL_ERASING) { |
459 | |||
458 | for (i = 0; i < 4; i++) { | 460 | for (i = 0; i < 4; i++) { |
459 | if (status & 1 << (i + 1)) { | 461 | if (!(status & 1 << (i + 1))) |
460 | this->cmdfunc(mtd, (NAND_CMD_STATUS_ERROR + i + 1), -1, -1); | 462 | continue; |
461 | rtn = this->read_byte(mtd); | 463 | this->cmdfunc(mtd, (NAND_CMD_STATUS_ERROR + i + 1), |
462 | this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1); | 464 | -1, -1); |
463 | if (!(rtn & ERR_STAT_ECC_AVAILABLE)) { | 465 | rtn = this->read_byte(mtd); |
464 | er_stat |= 1 << (i + 1); /* err_ecc_not_avail */ | 466 | this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1); |
465 | } | 467 | |
466 | } | 468 | /* err_ecc_not_avail */ |
469 | if (!(rtn & ERR_STAT_ECC_AVAILABLE)) | ||
470 | er_stat |= 1 << (i + 1); | ||
467 | } | 471 | } |
472 | |||
468 | } else if (state == FL_WRITING) { | 473 | } else if (state == FL_WRITING) { |
474 | |||
475 | unsigned long corrected = mtd->ecc_stats.corrected; | ||
476 | |||
469 | /* single bank write logic */ | 477 | /* single bank write logic */ |
470 | this->cmdfunc(mtd, NAND_CMD_STATUS_ERROR, -1, -1); | 478 | this->cmdfunc(mtd, NAND_CMD_STATUS_ERROR, -1, -1); |
471 | rtn = this->read_byte(mtd); | 479 | rtn = this->read_byte(mtd); |
472 | this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1); | 480 | this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1); |
481 | |||
473 | if (!(rtn & ERR_STAT_ECC_AVAILABLE)) { | 482 | if (!(rtn & ERR_STAT_ECC_AVAILABLE)) { |
474 | er_stat |= 1 << 1; /* err_ecc_not_avail */ | 483 | /* err_ecc_not_avail */ |
475 | } else { | 484 | er_stat |= 1 << 1; |
476 | len = mtd->writesize; | 485 | goto out; |
477 | buf = kmalloc(len, GFP_KERNEL); | ||
478 | if (!buf) { | ||
479 | printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n"); | ||
480 | er_stat = 1; /* if we can't check, assume failed */ | ||
481 | } else { | ||
482 | /* recovery read */ | ||
483 | /* page read */ | ||
484 | rtn = nand_do_read_ecc(mtd, page, len, &retlen, buf, NULL, this->autooob, 1); | ||
485 | if (rtn) { /* if read failed or > 1-bit error corrected */ | ||
486 | er_stat |= 1 << 1; /* ECC read failed */ | ||
487 | } | ||
488 | kfree(buf); | ||
489 | } | ||
490 | } | 486 | } |
487 | |||
488 | len = mtd->writesize; | ||
489 | buf = kmalloc(len, GFP_KERNEL); | ||
490 | if (!buf) { | ||
491 | printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n"); | ||
492 | er_stat = 1; | ||
493 | goto out; | ||
494 | } | ||
495 | |||
496 | /* recovery read */ | ||
497 | rtn = nand_do_read(mtd, page, len, &retlen, buf); | ||
498 | |||
499 | /* if read failed or > 1-bit error corrected */ | ||
500 | if (rtn || (mtd->ecc_stats.corrected - corrected) > 1) { | ||
501 | er_stat |= 1 << 1; | ||
502 | kfree(buf); | ||
491 | } | 503 | } |
492 | 504 | ||
493 | rtn = status; | 505 | rtn = status; |