imx-bbu-nand-fcb: erase on demand
Instead of erasing the whole partition on update entry, erase the areas separately when we actually want to write them. This is done as a step towards robust update. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
14fd7e9478
commit
678617ecaf
|
@ -272,34 +272,6 @@ static int fcb_create(struct imx_nand_fcb_bbu_handler *imx_handler,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int imx_bbu_erase(struct mtd_info *mtd)
|
|
||||||
{
|
|
||||||
uint64_t offset = 0;
|
|
||||||
struct erase_info erase;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
while (offset < mtd->size) {
|
|
||||||
pr_debug("erasing at 0x%08llx\n", offset);
|
|
||||||
if (mtd_block_isbad(mtd, offset)) {
|
|
||||||
pr_debug("erase skip block @ 0x%08llx\n", offset);
|
|
||||||
offset += mtd->erasesize;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&erase, 0, sizeof(erase));
|
|
||||||
erase.addr = offset;
|
|
||||||
erase.len = mtd->erasesize;
|
|
||||||
|
|
||||||
ret = mtd_erase(mtd, &erase);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
offset += mtd->erasesize;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mtd_peb_write_block(struct mtd_info *mtd, void *buf, int block, int len)
|
static int mtd_peb_write_block(struct mtd_info *mtd, void *buf, int block, int len)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -352,13 +324,22 @@ static int imx_bbu_firmware_start_block(struct mtd_info *mtd, int num)
|
||||||
static int imx_bbu_write_firmware(struct mtd_info *mtd, unsigned num, void *buf,
|
static int imx_bbu_write_firmware(struct mtd_info *mtd, unsigned num, void *buf,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret, i;
|
||||||
int num_blocks = imx_bbu_firmware_max_blocks(mtd);
|
int num_blocks = imx_bbu_firmware_max_blocks(mtd);
|
||||||
int block = imx_bbu_firmware_start_block(mtd, num);
|
int block = imx_bbu_firmware_start_block(mtd, num);
|
||||||
|
|
||||||
pr_info("writing firmware %d to block %d (ofs 0x%08x)\n",
|
pr_info("writing firmware %d to block %d (ofs 0x%08x)\n",
|
||||||
num, block, block * mtd->erasesize);
|
num, block, block * mtd->erasesize);
|
||||||
|
|
||||||
|
for (i = 0; i < num_blocks; i++) {
|
||||||
|
if (mtd_peb_is_bad(mtd, block + i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = mtd_peb_erase(mtd, block + i);
|
||||||
|
if (ret && ret != -EIO)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
int now = min(len, mtd->erasesize);
|
int now = min(len, mtd->erasesize);
|
||||||
|
|
||||||
|
@ -470,6 +451,10 @@ again:
|
||||||
if (cpu_is_mx28())
|
if (cpu_is_mx28())
|
||||||
imx28_dbbt_create(dbbt, *n_bad_blocksp);
|
imx28_dbbt_create(dbbt, *n_bad_blocksp);
|
||||||
|
|
||||||
|
ret = mtd_peb_erase(mtd, block);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ret = raw_write_page(mtd, fcb_raw_page, block * mtd->erasesize);
|
ret = raw_write_page(mtd, fcb_raw_page, block * mtd->erasesize);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("Writing FCB on block %d failed with %s\n",
|
pr_err("Writing FCB on block %d failed with %s\n",
|
||||||
|
@ -629,10 +614,6 @@ static int imx_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *dat
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = imx_bbu_erase(mtd);
|
|
||||||
if (ret)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = imx_bbu_write_firmware(mtd, 0, fw, fw_size);
|
ret = imx_bbu_write_firmware(mtd, 0, fw, fw_size);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
Loading…
Reference in New Issue