xref: /openbmc/linux/drivers/mtd/tests/mtd_test.c (revision abc173ad)
1084db4b0SAkinobu Mita #define pr_fmt(fmt) "mtd_test: " fmt
2084db4b0SAkinobu Mita 
3084db4b0SAkinobu Mita #include <linux/init.h>
4084db4b0SAkinobu Mita #include <linux/module.h>
5084db4b0SAkinobu Mita #include <linux/sched.h>
6084db4b0SAkinobu Mita #include <linux/printk.h>
7084db4b0SAkinobu Mita 
8084db4b0SAkinobu Mita #include "mtd_test.h"
9084db4b0SAkinobu Mita 
10084db4b0SAkinobu Mita int mtdtest_erase_eraseblock(struct mtd_info *mtd, unsigned int ebnum)
11084db4b0SAkinobu Mita {
12084db4b0SAkinobu Mita 	int err;
13084db4b0SAkinobu Mita 	struct erase_info ei;
14084db4b0SAkinobu Mita 	loff_t addr = ebnum * mtd->erasesize;
15084db4b0SAkinobu Mita 
16084db4b0SAkinobu Mita 	memset(&ei, 0, sizeof(struct erase_info));
17084db4b0SAkinobu Mita 	ei.mtd  = mtd;
18084db4b0SAkinobu Mita 	ei.addr = addr;
19084db4b0SAkinobu Mita 	ei.len  = mtd->erasesize;
20084db4b0SAkinobu Mita 
21084db4b0SAkinobu Mita 	err = mtd_erase(mtd, &ei);
22084db4b0SAkinobu Mita 	if (err) {
23084db4b0SAkinobu Mita 		pr_info("error %d while erasing EB %d\n", err, ebnum);
24084db4b0SAkinobu Mita 		return err;
25084db4b0SAkinobu Mita 	}
26084db4b0SAkinobu Mita 
27084db4b0SAkinobu Mita 	if (ei.state == MTD_ERASE_FAILED) {
28084db4b0SAkinobu Mita 		pr_info("some erase error occurred at EB %d\n", ebnum);
29084db4b0SAkinobu Mita 		return -EIO;
30084db4b0SAkinobu Mita 	}
31084db4b0SAkinobu Mita 	return 0;
32084db4b0SAkinobu Mita }
33084db4b0SAkinobu Mita 
34084db4b0SAkinobu Mita static int is_block_bad(struct mtd_info *mtd, unsigned int ebnum)
35084db4b0SAkinobu Mita {
36084db4b0SAkinobu Mita 	int ret;
37084db4b0SAkinobu Mita 	loff_t addr = ebnum * mtd->erasesize;
38084db4b0SAkinobu Mita 
39084db4b0SAkinobu Mita 	ret = mtd_block_isbad(mtd, addr);
40084db4b0SAkinobu Mita 	if (ret)
41084db4b0SAkinobu Mita 		pr_info("block %d is bad\n", ebnum);
42084db4b0SAkinobu Mita 
43084db4b0SAkinobu Mita 	return ret;
44084db4b0SAkinobu Mita }
45084db4b0SAkinobu Mita 
46084db4b0SAkinobu Mita int mtdtest_scan_for_bad_eraseblocks(struct mtd_info *mtd, unsigned char *bbt,
47084db4b0SAkinobu Mita 					unsigned int eb, int ebcnt)
48084db4b0SAkinobu Mita {
49084db4b0SAkinobu Mita 	int i, bad = 0;
50084db4b0SAkinobu Mita 
51084db4b0SAkinobu Mita 	if (!mtd_can_have_bb(mtd))
52084db4b0SAkinobu Mita 		return 0;
53084db4b0SAkinobu Mita 
54084db4b0SAkinobu Mita 	pr_info("scanning for bad eraseblocks\n");
55084db4b0SAkinobu Mita 	for (i = 0; i < ebcnt; ++i) {
56084db4b0SAkinobu Mita 		bbt[i] = is_block_bad(mtd, eb + i) ? 1 : 0;
57084db4b0SAkinobu Mita 		if (bbt[i])
58084db4b0SAkinobu Mita 			bad += 1;
59084db4b0SAkinobu Mita 		cond_resched();
60084db4b0SAkinobu Mita 	}
61084db4b0SAkinobu Mita 	pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
62084db4b0SAkinobu Mita 
63084db4b0SAkinobu Mita 	return 0;
64084db4b0SAkinobu Mita }
65084db4b0SAkinobu Mita 
66084db4b0SAkinobu Mita int mtdtest_erase_good_eraseblocks(struct mtd_info *mtd, unsigned char *bbt,
67084db4b0SAkinobu Mita 				unsigned int eb, int ebcnt)
68084db4b0SAkinobu Mita {
69084db4b0SAkinobu Mita 	int err;
70084db4b0SAkinobu Mita 	unsigned int i;
71084db4b0SAkinobu Mita 
72084db4b0SAkinobu Mita 	for (i = 0; i < ebcnt; ++i) {
73084db4b0SAkinobu Mita 		if (bbt[i])
74084db4b0SAkinobu Mita 			continue;
75084db4b0SAkinobu Mita 		err = mtdtest_erase_eraseblock(mtd, eb + i);
76084db4b0SAkinobu Mita 		if (err)
77084db4b0SAkinobu Mita 			return err;
78084db4b0SAkinobu Mita 		cond_resched();
79084db4b0SAkinobu Mita 	}
80084db4b0SAkinobu Mita 
81084db4b0SAkinobu Mita 	return 0;
82084db4b0SAkinobu Mita }
83084db4b0SAkinobu Mita 
84084db4b0SAkinobu Mita int mtdtest_read(struct mtd_info *mtd, loff_t addr, size_t size, void *buf)
85084db4b0SAkinobu Mita {
86084db4b0SAkinobu Mita 	size_t read;
87084db4b0SAkinobu Mita 	int err;
88084db4b0SAkinobu Mita 
89084db4b0SAkinobu Mita 	err = mtd_read(mtd, addr, size, &read, buf);
90084db4b0SAkinobu Mita 	/* Ignore corrected ECC errors */
91084db4b0SAkinobu Mita 	if (mtd_is_bitflip(err))
92084db4b0SAkinobu Mita 		err = 0;
93084db4b0SAkinobu Mita 	if (!err && read != size)
94084db4b0SAkinobu Mita 		err = -EIO;
95abc173adSAkinobu Mita 	if (err)
96abc173adSAkinobu Mita 		pr_err("error: read failed at %#llx\n", addr);
97084db4b0SAkinobu Mita 
98084db4b0SAkinobu Mita 	return err;
99084db4b0SAkinobu Mita }
100084db4b0SAkinobu Mita 
101084db4b0SAkinobu Mita int mtdtest_write(struct mtd_info *mtd, loff_t addr, size_t size,
102084db4b0SAkinobu Mita 		const void *buf)
103084db4b0SAkinobu Mita {
104084db4b0SAkinobu Mita 	size_t written;
105084db4b0SAkinobu Mita 	int err;
106084db4b0SAkinobu Mita 
107084db4b0SAkinobu Mita 	err = mtd_write(mtd, addr, size, &written, buf);
108084db4b0SAkinobu Mita 	if (!err && written != size)
109084db4b0SAkinobu Mita 		err = -EIO;
110084db4b0SAkinobu Mita 
111084db4b0SAkinobu Mita 	return err;
112084db4b0SAkinobu Mita }
113