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