Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | // SPDX-License-Identifier: GPL-2.0 #define pr_fmt(fmt) "mtd_test: " fmt #include <linux/module.h> #include <linux/sched.h> #include <linux/printk.h> #include "mtd_test.h" int mtdtest_erase_eraseblock(struct mtd_info *mtd, unsigned int ebnum) { int err; struct erase_info ei; loff_t addr = (loff_t)ebnum * mtd->erasesize; memset(&ei, 0, sizeof(struct erase_info)); ei.addr = addr; ei.len = mtd->erasesize; err = mtd_erase(mtd, &ei); if (err) { pr_info("error %d while erasing EB %d\n", err, ebnum); return err; } return 0; } static int is_block_bad(struct mtd_info *mtd, unsigned int ebnum) { int ret; loff_t addr = (loff_t)ebnum * mtd->erasesize; ret = mtd_block_isbad(mtd, addr); if (ret) pr_info("block %d is bad\n", ebnum); return ret; } int mtdtest_scan_for_bad_eraseblocks(struct mtd_info *mtd, unsigned char *bbt, unsigned int eb, int ebcnt) { int i, bad = 0; if (!mtd_can_have_bb(mtd)) return 0; pr_info("scanning for bad eraseblocks\n"); for (i = 0; i < ebcnt; ++i) { bbt[i] = is_block_bad(mtd, eb + i) ? 1 : 0; if (bbt[i]) bad += 1; cond_resched(); } pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); return 0; } int mtdtest_erase_good_eraseblocks(struct mtd_info *mtd, unsigned char *bbt, unsigned int eb, int ebcnt) { int err; unsigned int i; for (i = 0; i < ebcnt; ++i) { if (bbt[i]) continue; err = mtdtest_erase_eraseblock(mtd, eb + i); if (err) return err; cond_resched(); } return 0; } int mtdtest_read(struct mtd_info *mtd, loff_t addr, size_t size, void *buf) { size_t read; int err; err = mtd_read(mtd, addr, size, &read, buf); /* Ignore corrected ECC errors */ if (mtd_is_bitflip(err)) err = 0; if (!err && read != size) err = -EIO; if (err) pr_err("error: read failed at %#llx\n", addr); return err; } int mtdtest_write(struct mtd_info *mtd, loff_t addr, size_t size, const void *buf) { size_t written; int err; err = mtd_write(mtd, addr, size, &written, buf); if (!err && written != size) err = -EIO; if (err) pr_err("error: write failed at %#llx\n", addr); return err; } |