static int migrate_from_bad(int offset, u8 *write_dat, u8 *write_oob) { int page; int error_block = offset / BLOCK_SIZE_BMT; int error_page = (offset / PAGE_SIZE_BMT) % page_per_block; int to_index; to_index = find_available_block(false); if (!to_index) { MSG("Cannot find an available block for BMT\n"); return 0; } for (page = 0; page < error_page; page++) { nand_read_page_bmt(PAGE_ADDR(error_block) + page, dat_buf, oob_buf); if (error_block < system_block_count) { set_bad_index_to_oob(oob_buf, error_block); } if (nand_write_page_bmt(PAGE_ADDR(to_index) + page, dat_buf, oob_buf)) { MSG("Write page %d fail\n", PAGE_ADDR(to_index) + page); mark_block_bad_bmt(OFFSET(to_index), BMT_BADBLOCK_GENERATE_LATER); return migrate_from_bad(offset, write_dat, write_oob); } } { memset(oob_buf, 0xFF, sizeof(oob_buf)); #if defined(TCSUPPORT_CPU_MT7510)||defined(TCSUPPORT_CPU_MT7520) memcpy(oob_buf, write_oob, mtd_bmt->oobsize); #else memcpy(oob_buf, write_oob, 1 << nand_chip_bmt->flash->oob_shift); #endif if (error_block < system_block_count) set_bad_index_to_oob(oob_buf, error_block); // if error_block is already a mapped block, original mapping index is in OOB. if (nand_write_page_bmt(PAGE_ADDR(to_index) + error_page, write_dat, oob_buf)) { MSG("Write page %d fail\n", PAGE_ADDR(to_index) + error_page); mark_block_bad_bmt(OFFSET(to_index), BMT_BADBLOCK_GENERATE_LATER); return migrate_from_bad(offset, write_dat, write_oob); } } MSG("Migrate from %d to %d done!\n",error_block, to_index); return to_index; }
static int migrate_from_bad(int offset, u8 * write_dat, u8 * write_oob) { int page; int error_block = offset / BLOCK_SIZE_BMT; int error_page = (offset / PAGE_SIZE_BMT) % page_per_block; int to_index; memcpy(oob_buf, write_oob, MAX_OOB_SIZE); to_index = find_available_block(false); if (!to_index) { MSG(INIT, "Cannot find an available block for BMT\n"); return 0; } { // migrate error page first MSG(INIT, "Write error page: 0x%x\n", error_page); if (!write_dat) { nand_read_page_bmt(PAGE_ADDR(error_block) + error_page, dat_buf, NULL); write_dat = dat_buf; } // memcpy(oob_buf, write_oob, MAX_OOB_SIZE); if (error_block < system_block_count) set_bad_index_to_oob(oob_buf, error_block); // if error_block is already a mapped block, original mapping index is in OOB. if (!nand_write_page_bmt(PAGE_ADDR(to_index) + error_page, write_dat, oob_buf)) { MSG(INIT, "Write to page 0x%x fail\n", PAGE_ADDR(to_index) + error_page); mark_block_bad_bmt(OFFSET(to_index)); return migrate_from_bad(offset, write_dat, write_oob); } } for (page = 0; page < page_per_block; page++) { if (page != error_page) { nand_read_page_bmt(PAGE_ADDR(error_block) + page, dat_buf, oob_buf); if (is_page_used(dat_buf, oob_buf)) { if (error_block < system_block_count) { set_bad_index_to_oob(oob_buf, error_block); } MSG(INIT, "\tmigrate page 0x%x to page 0x%x\n", PAGE_ADDR(error_block) + page, PAGE_ADDR(to_index) + page); if (!nand_write_page_bmt(PAGE_ADDR(to_index) + page, dat_buf, oob_buf)) { MSG(INIT, "Write to page 0x%x fail\n", PAGE_ADDR(to_index) + page); mark_block_bad_bmt(OFFSET(to_index)); return migrate_from_bad(offset, write_dat, write_oob); } } } } MSG(INIT, "Migrate from 0x%x to 0x%x done!\n", error_block, to_index); return to_index; }