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