xref: /openbmc/linux/drivers/mtd/tests/pagetest.c (revision 4cd10358)
14cd10358SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2a995c792SAkinobu Mita /*
3a995c792SAkinobu Mita  * Copyright (C) 2006-2008 Nokia Corporation
4a995c792SAkinobu Mita  *
5a995c792SAkinobu Mita  * Test page read and write on MTD device.
6a995c792SAkinobu Mita  *
7a995c792SAkinobu Mita  * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
8a995c792SAkinobu Mita  */
9a995c792SAkinobu Mita 
10a995c792SAkinobu Mita #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11a995c792SAkinobu Mita 
12a995c792SAkinobu Mita #include <asm/div64.h>
13a995c792SAkinobu Mita #include <linux/init.h>
14a995c792SAkinobu Mita #include <linux/module.h>
15a995c792SAkinobu Mita #include <linux/moduleparam.h>
16a995c792SAkinobu Mita #include <linux/err.h>
17a995c792SAkinobu Mita #include <linux/mtd/mtd.h>
18a995c792SAkinobu Mita #include <linux/slab.h>
19a995c792SAkinobu Mita #include <linux/sched.h>
20a995c792SAkinobu Mita #include <linux/random.h>
21a995c792SAkinobu Mita 
2266b28183SAkinobu Mita #include "mtd_test.h"
2366b28183SAkinobu Mita 
24a995c792SAkinobu Mita static int dev = -EINVAL;
25a995c792SAkinobu Mita module_param(dev, int, S_IRUGO);
26a995c792SAkinobu Mita MODULE_PARM_DESC(dev, "MTD device number to use");
27a995c792SAkinobu Mita 
28a995c792SAkinobu Mita static struct mtd_info *mtd;
29a995c792SAkinobu Mita static unsigned char *twopages;
30a995c792SAkinobu Mita static unsigned char *writebuf;
31a995c792SAkinobu Mita static unsigned char *boundary;
32a995c792SAkinobu Mita static unsigned char *bbt;
33a995c792SAkinobu Mita 
34a995c792SAkinobu Mita static int pgsize;
35a995c792SAkinobu Mita static int bufsize;
36a995c792SAkinobu Mita static int ebcnt;
37a995c792SAkinobu Mita static int pgcnt;
38a995c792SAkinobu Mita static int errcnt;
39a995c792SAkinobu Mita static struct rnd_state rnd_state;
40a995c792SAkinobu Mita 
write_eraseblock(int ebnum)41a995c792SAkinobu Mita static int write_eraseblock(int ebnum)
42a995c792SAkinobu Mita {
431001ff7aSBrian Norris 	loff_t addr = (loff_t)ebnum * mtd->erasesize;
44a995c792SAkinobu Mita 
45a995c792SAkinobu Mita 	prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
46a995c792SAkinobu Mita 	cond_resched();
478a9f4aa3SAkinobu Mita 	return mtdtest_write(mtd, addr, mtd->erasesize, writebuf);
48a995c792SAkinobu Mita }
49a995c792SAkinobu Mita 
verify_eraseblock(int ebnum)50a995c792SAkinobu Mita static int verify_eraseblock(int ebnum)
51a995c792SAkinobu Mita {
52a995c792SAkinobu Mita 	uint32_t j;
53a995c792SAkinobu Mita 	int err = 0, i;
54a995c792SAkinobu Mita 	loff_t addr0, addrn;
551001ff7aSBrian Norris 	loff_t addr = (loff_t)ebnum * mtd->erasesize;
56a995c792SAkinobu Mita 
57a995c792SAkinobu Mita 	addr0 = 0;
58a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[i]; ++i)
59a995c792SAkinobu Mita 		addr0 += mtd->erasesize;
60a995c792SAkinobu Mita 
61a995c792SAkinobu Mita 	addrn = mtd->size;
62a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
63a995c792SAkinobu Mita 		addrn -= mtd->erasesize;
64a995c792SAkinobu Mita 
65a995c792SAkinobu Mita 	prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
66a995c792SAkinobu Mita 	for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) {
67a995c792SAkinobu Mita 		/* Do a read to set the internal dataRAMs to different data */
6866b28183SAkinobu Mita 		err = mtdtest_read(mtd, addr0, bufsize, twopages);
69abc173adSAkinobu Mita 		if (err)
70a995c792SAkinobu Mita 			return err;
7166b28183SAkinobu Mita 		err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages);
72abc173adSAkinobu Mita 		if (err)
73a995c792SAkinobu Mita 			return err;
74a995c792SAkinobu Mita 		memset(twopages, 0, bufsize);
7566b28183SAkinobu Mita 		err = mtdtest_read(mtd, addr, bufsize, twopages);
76abc173adSAkinobu Mita 		if (err)
77a995c792SAkinobu Mita 			break;
78a995c792SAkinobu Mita 		if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) {
79a995c792SAkinobu Mita 			pr_err("error: verify failed at %#llx\n",
80a995c792SAkinobu Mita 			       (long long)addr);
81a995c792SAkinobu Mita 			errcnt += 1;
82a995c792SAkinobu Mita 		}
83a995c792SAkinobu Mita 	}
84a995c792SAkinobu Mita 	/* Check boundary between eraseblocks */
85a995c792SAkinobu Mita 	if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) {
86a995c792SAkinobu Mita 		struct rnd_state old_state = rnd_state;
87a995c792SAkinobu Mita 
88a995c792SAkinobu Mita 		/* Do a read to set the internal dataRAMs to different data */
8966b28183SAkinobu Mita 		err = mtdtest_read(mtd, addr0, bufsize, twopages);
90abc173adSAkinobu Mita 		if (err)
91a995c792SAkinobu Mita 			return err;
9266b28183SAkinobu Mita 		err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages);
93abc173adSAkinobu Mita 		if (err)
94a995c792SAkinobu Mita 			return err;
95a995c792SAkinobu Mita 		memset(twopages, 0, bufsize);
9666b28183SAkinobu Mita 		err = mtdtest_read(mtd, addr, bufsize, twopages);
97abc173adSAkinobu Mita 		if (err)
98a995c792SAkinobu Mita 			return err;
99a995c792SAkinobu Mita 		memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize);
100a995c792SAkinobu Mita 		prandom_bytes_state(&rnd_state, boundary + pgsize, pgsize);
101a995c792SAkinobu Mita 		if (memcmp(twopages, boundary, bufsize)) {
102a995c792SAkinobu Mita 			pr_err("error: verify failed at %#llx\n",
103a995c792SAkinobu Mita 			       (long long)addr);
104a995c792SAkinobu Mita 			errcnt += 1;
105a995c792SAkinobu Mita 		}
106a995c792SAkinobu Mita 		rnd_state = old_state;
107a995c792SAkinobu Mita 	}
108a995c792SAkinobu Mita 	return err;
109a995c792SAkinobu Mita }
110a995c792SAkinobu Mita 
crosstest(void)111a995c792SAkinobu Mita static int crosstest(void)
112a995c792SAkinobu Mita {
113a995c792SAkinobu Mita 	int err = 0, i;
114a995c792SAkinobu Mita 	loff_t addr, addr0, addrn;
115a995c792SAkinobu Mita 	unsigned char *pp1, *pp2, *pp3, *pp4;
116a995c792SAkinobu Mita 
117a995c792SAkinobu Mita 	pr_info("crosstest\n");
1186396bb22SKees Cook 	pp1 = kcalloc(pgsize, 4, GFP_KERNEL);
119a995c792SAkinobu Mita 	if (!pp1)
120a995c792SAkinobu Mita 		return -ENOMEM;
121a995c792SAkinobu Mita 	pp2 = pp1 + pgsize;
122a995c792SAkinobu Mita 	pp3 = pp2 + pgsize;
123a995c792SAkinobu Mita 	pp4 = pp3 + pgsize;
124a995c792SAkinobu Mita 
125a995c792SAkinobu Mita 	addr0 = 0;
126a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[i]; ++i)
127a995c792SAkinobu Mita 		addr0 += mtd->erasesize;
128a995c792SAkinobu Mita 
129a995c792SAkinobu Mita 	addrn = mtd->size;
130a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
131a995c792SAkinobu Mita 		addrn -= mtd->erasesize;
132a995c792SAkinobu Mita 
133a995c792SAkinobu Mita 	/* Read 2nd-to-last page to pp1 */
134a995c792SAkinobu Mita 	addr = addrn - pgsize - pgsize;
13566b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr, pgsize, pp1);
13666b28183SAkinobu Mita 	if (err) {
137a995c792SAkinobu Mita 		kfree(pp1);
138a995c792SAkinobu Mita 		return err;
139a995c792SAkinobu Mita 	}
140a995c792SAkinobu Mita 
141a995c792SAkinobu Mita 	/* Read 3rd-to-last page to pp1 */
142a995c792SAkinobu Mita 	addr = addrn - pgsize - pgsize - pgsize;
14366b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr, pgsize, pp1);
14466b28183SAkinobu Mita 	if (err) {
145a995c792SAkinobu Mita 		kfree(pp1);
146a995c792SAkinobu Mita 		return err;
147a995c792SAkinobu Mita 	}
148a995c792SAkinobu Mita 
149a995c792SAkinobu Mita 	/* Read first page to pp2 */
150a995c792SAkinobu Mita 	addr = addr0;
151a995c792SAkinobu Mita 	pr_info("reading page at %#llx\n", (long long)addr);
15266b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr, pgsize, pp2);
15366b28183SAkinobu Mita 	if (err) {
154a995c792SAkinobu Mita 		kfree(pp1);
155a995c792SAkinobu Mita 		return err;
156a995c792SAkinobu Mita 	}
157a995c792SAkinobu Mita 
158a995c792SAkinobu Mita 	/* Read last page to pp3 */
159a995c792SAkinobu Mita 	addr = addrn - pgsize;
160a995c792SAkinobu Mita 	pr_info("reading page at %#llx\n", (long long)addr);
16166b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr, pgsize, pp3);
16266b28183SAkinobu Mita 	if (err) {
163a995c792SAkinobu Mita 		kfree(pp1);
164a995c792SAkinobu Mita 		return err;
165a995c792SAkinobu Mita 	}
166a995c792SAkinobu Mita 
167a995c792SAkinobu Mita 	/* Read first page again to pp4 */
168a995c792SAkinobu Mita 	addr = addr0;
169a995c792SAkinobu Mita 	pr_info("reading page at %#llx\n", (long long)addr);
17066b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr, pgsize, pp4);
17166b28183SAkinobu Mita 	if (err) {
172a995c792SAkinobu Mita 		kfree(pp1);
173a995c792SAkinobu Mita 		return err;
174a995c792SAkinobu Mita 	}
175a995c792SAkinobu Mita 
176a995c792SAkinobu Mita 	/* pp2 and pp4 should be the same */
177a995c792SAkinobu Mita 	pr_info("verifying pages read at %#llx match\n",
178a995c792SAkinobu Mita 	       (long long)addr0);
179a995c792SAkinobu Mita 	if (memcmp(pp2, pp4, pgsize)) {
180a995c792SAkinobu Mita 		pr_err("verify failed!\n");
181a995c792SAkinobu Mita 		errcnt += 1;
182a995c792SAkinobu Mita 	} else if (!err)
183a995c792SAkinobu Mita 		pr_info("crosstest ok\n");
184a995c792SAkinobu Mita 	kfree(pp1);
185a995c792SAkinobu Mita 	return err;
186a995c792SAkinobu Mita }
187a995c792SAkinobu Mita 
erasecrosstest(void)188a995c792SAkinobu Mita static int erasecrosstest(void)
189a995c792SAkinobu Mita {
190a995c792SAkinobu Mita 	int err = 0, i, ebnum, ebnum2;
191a995c792SAkinobu Mita 	loff_t addr0;
192a995c792SAkinobu Mita 	char *readbuf = twopages;
193a995c792SAkinobu Mita 
194a995c792SAkinobu Mita 	pr_info("erasecrosstest\n");
195a995c792SAkinobu Mita 
196a995c792SAkinobu Mita 	ebnum = 0;
197a995c792SAkinobu Mita 	addr0 = 0;
198a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[i]; ++i) {
199a995c792SAkinobu Mita 		addr0 += mtd->erasesize;
200a995c792SAkinobu Mita 		ebnum += 1;
201a995c792SAkinobu Mita 	}
202a995c792SAkinobu Mita 
203a995c792SAkinobu Mita 	ebnum2 = ebcnt - 1;
204a995c792SAkinobu Mita 	while (ebnum2 && bbt[ebnum2])
205a995c792SAkinobu Mita 		ebnum2 -= 1;
206a995c792SAkinobu Mita 
207a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum);
20866b28183SAkinobu Mita 	err = mtdtest_erase_eraseblock(mtd, ebnum);
209a995c792SAkinobu Mita 	if (err)
210a995c792SAkinobu Mita 		return err;
211a995c792SAkinobu Mita 
212a995c792SAkinobu Mita 	pr_info("writing 1st page of block %d\n", ebnum);
213a995c792SAkinobu Mita 	prandom_bytes_state(&rnd_state, writebuf, pgsize);
214a995c792SAkinobu Mita 	strcpy(writebuf, "There is no data like this!");
21566b28183SAkinobu Mita 	err = mtdtest_write(mtd, addr0, pgsize, writebuf);
2168a9f4aa3SAkinobu Mita 	if (err)
21766b28183SAkinobu Mita 		return err;
218a995c792SAkinobu Mita 
219a995c792SAkinobu Mita 	pr_info("reading 1st page of block %d\n", ebnum);
220a995c792SAkinobu Mita 	memset(readbuf, 0, pgsize);
22166b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr0, pgsize, readbuf);
222abc173adSAkinobu Mita 	if (err)
22366b28183SAkinobu Mita 		return err;
224a995c792SAkinobu Mita 
225a995c792SAkinobu Mita 	pr_info("verifying 1st page of block %d\n", ebnum);
226a995c792SAkinobu Mita 	if (memcmp(writebuf, readbuf, pgsize)) {
227a995c792SAkinobu Mita 		pr_err("verify failed!\n");
228a995c792SAkinobu Mita 		errcnt += 1;
229a995c792SAkinobu Mita 		return -1;
230a995c792SAkinobu Mita 	}
231a995c792SAkinobu Mita 
232a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum);
23366b28183SAkinobu Mita 	err = mtdtest_erase_eraseblock(mtd, ebnum);
234a995c792SAkinobu Mita 	if (err)
235a995c792SAkinobu Mita 		return err;
236a995c792SAkinobu Mita 
237a995c792SAkinobu Mita 	pr_info("writing 1st page of block %d\n", ebnum);
238a995c792SAkinobu Mita 	prandom_bytes_state(&rnd_state, writebuf, pgsize);
239a995c792SAkinobu Mita 	strcpy(writebuf, "There is no data like this!");
24066b28183SAkinobu Mita 	err = mtdtest_write(mtd, addr0, pgsize, writebuf);
2418a9f4aa3SAkinobu Mita 	if (err)
24266b28183SAkinobu Mita 		return err;
243a995c792SAkinobu Mita 
244a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum2);
24566b28183SAkinobu Mita 	err = mtdtest_erase_eraseblock(mtd, ebnum2);
246a995c792SAkinobu Mita 	if (err)
247a995c792SAkinobu Mita 		return err;
248a995c792SAkinobu Mita 
249a995c792SAkinobu Mita 	pr_info("reading 1st page of block %d\n", ebnum);
250a995c792SAkinobu Mita 	memset(readbuf, 0, pgsize);
25166b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr0, pgsize, readbuf);
252abc173adSAkinobu Mita 	if (err)
25366b28183SAkinobu Mita 		return err;
254a995c792SAkinobu Mita 
255a995c792SAkinobu Mita 	pr_info("verifying 1st page of block %d\n", ebnum);
256a995c792SAkinobu Mita 	if (memcmp(writebuf, readbuf, pgsize)) {
257a995c792SAkinobu Mita 		pr_err("verify failed!\n");
258a995c792SAkinobu Mita 		errcnt += 1;
259a995c792SAkinobu Mita 		return -1;
260a995c792SAkinobu Mita 	}
261a995c792SAkinobu Mita 
262a995c792SAkinobu Mita 	if (!err)
263a995c792SAkinobu Mita 		pr_info("erasecrosstest ok\n");
264a995c792SAkinobu Mita 	return err;
265a995c792SAkinobu Mita }
266a995c792SAkinobu Mita 
erasetest(void)267a995c792SAkinobu Mita static int erasetest(void)
268a995c792SAkinobu Mita {
269a995c792SAkinobu Mita 	int err = 0, i, ebnum, ok = 1;
270a995c792SAkinobu Mita 	loff_t addr0;
271a995c792SAkinobu Mita 
272a995c792SAkinobu Mita 	pr_info("erasetest\n");
273a995c792SAkinobu Mita 
274a995c792SAkinobu Mita 	ebnum = 0;
275a995c792SAkinobu Mita 	addr0 = 0;
276a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[i]; ++i) {
277a995c792SAkinobu Mita 		addr0 += mtd->erasesize;
278a995c792SAkinobu Mita 		ebnum += 1;
279a995c792SAkinobu Mita 	}
280a995c792SAkinobu Mita 
281a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum);
28266b28183SAkinobu Mita 	err = mtdtest_erase_eraseblock(mtd, ebnum);
283a995c792SAkinobu Mita 	if (err)
284a995c792SAkinobu Mita 		return err;
285a995c792SAkinobu Mita 
286a995c792SAkinobu Mita 	pr_info("writing 1st page of block %d\n", ebnum);
287a995c792SAkinobu Mita 	prandom_bytes_state(&rnd_state, writebuf, pgsize);
28866b28183SAkinobu Mita 	err = mtdtest_write(mtd, addr0, pgsize, writebuf);
2898a9f4aa3SAkinobu Mita 	if (err)
29066b28183SAkinobu Mita 		return err;
291a995c792SAkinobu Mita 
292a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum);
29366b28183SAkinobu Mita 	err = mtdtest_erase_eraseblock(mtd, ebnum);
294a995c792SAkinobu Mita 	if (err)
295a995c792SAkinobu Mita 		return err;
296a995c792SAkinobu Mita 
297a995c792SAkinobu Mita 	pr_info("reading 1st page of block %d\n", ebnum);
29866b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr0, pgsize, twopages);
299abc173adSAkinobu Mita 	if (err)
30066b28183SAkinobu Mita 		return err;
301a995c792SAkinobu Mita 
302a995c792SAkinobu Mita 	pr_info("verifying 1st page of block %d is all 0xff\n",
303a995c792SAkinobu Mita 	       ebnum);
304a995c792SAkinobu Mita 	for (i = 0; i < pgsize; ++i)
305a995c792SAkinobu Mita 		if (twopages[i] != 0xff) {
306a995c792SAkinobu Mita 			pr_err("verifying all 0xff failed at %d\n",
307a995c792SAkinobu Mita 			       i);
308a995c792SAkinobu Mita 			errcnt += 1;
309a995c792SAkinobu Mita 			ok = 0;
310a995c792SAkinobu Mita 			break;
311a995c792SAkinobu Mita 		}
312a995c792SAkinobu Mita 
313a995c792SAkinobu Mita 	if (ok && !err)
314a995c792SAkinobu Mita 		pr_info("erasetest ok\n");
315a995c792SAkinobu Mita 
316a995c792SAkinobu Mita 	return err;
317a995c792SAkinobu Mita }
318a995c792SAkinobu Mita 
mtd_pagetest_init(void)319a995c792SAkinobu Mita static int __init mtd_pagetest_init(void)
320a995c792SAkinobu Mita {
321a995c792SAkinobu Mita 	int err = 0;
322a995c792SAkinobu Mita 	uint64_t tmp;
323a995c792SAkinobu Mita 	uint32_t i;
324a995c792SAkinobu Mita 
325a995c792SAkinobu Mita 	printk(KERN_INFO "\n");
326a995c792SAkinobu Mita 	printk(KERN_INFO "=================================================\n");
327a995c792SAkinobu Mita 
328a995c792SAkinobu Mita 	if (dev < 0) {
329a995c792SAkinobu Mita 		pr_info("Please specify a valid mtd-device via module parameter\n");
330a995c792SAkinobu Mita 		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
331a995c792SAkinobu Mita 		return -EINVAL;
332a995c792SAkinobu Mita 	}
333a995c792SAkinobu Mita 
334a995c792SAkinobu Mita 	pr_info("MTD device: %d\n", dev);
335a995c792SAkinobu Mita 
336a995c792SAkinobu Mita 	mtd = get_mtd_device(NULL, dev);
337a995c792SAkinobu Mita 	if (IS_ERR(mtd)) {
338a995c792SAkinobu Mita 		err = PTR_ERR(mtd);
339a995c792SAkinobu Mita 		pr_err("error: cannot get MTD device\n");
340a995c792SAkinobu Mita 		return err;
341a995c792SAkinobu Mita 	}
342a995c792SAkinobu Mita 
343818b9739SHuang Shijie 	if (!mtd_type_is_nand(mtd)) {
344a995c792SAkinobu Mita 		pr_info("this test requires NAND flash\n");
345a995c792SAkinobu Mita 		goto out;
346a995c792SAkinobu Mita 	}
347a995c792SAkinobu Mita 
348a995c792SAkinobu Mita 	tmp = mtd->size;
349a995c792SAkinobu Mita 	do_div(tmp, mtd->erasesize);
350a995c792SAkinobu Mita 	ebcnt = tmp;
351a995c792SAkinobu Mita 	pgcnt = mtd->erasesize / mtd->writesize;
352a995c792SAkinobu Mita 	pgsize = mtd->writesize;
353a995c792SAkinobu Mita 
354a995c792SAkinobu Mita 	pr_info("MTD device size %llu, eraseblock size %u, "
355a995c792SAkinobu Mita 	       "page size %u, count of eraseblocks %u, pages per "
356a995c792SAkinobu Mita 	       "eraseblock %u, OOB size %u\n",
357a995c792SAkinobu Mita 	       (unsigned long long)mtd->size, mtd->erasesize,
358a995c792SAkinobu Mita 	       pgsize, ebcnt, pgcnt, mtd->oobsize);
359a995c792SAkinobu Mita 
360a995c792SAkinobu Mita 	err = -ENOMEM;
361a995c792SAkinobu Mita 	bufsize = pgsize * 2;
362a995c792SAkinobu Mita 	writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
363a995c792SAkinobu Mita 	if (!writebuf)
364a995c792SAkinobu Mita 		goto out;
365a995c792SAkinobu Mita 	twopages = kmalloc(bufsize, GFP_KERNEL);
366a995c792SAkinobu Mita 	if (!twopages)
367a995c792SAkinobu Mita 		goto out;
368a995c792SAkinobu Mita 	boundary = kmalloc(bufsize, GFP_KERNEL);
369a995c792SAkinobu Mita 	if (!boundary)
370a995c792SAkinobu Mita 		goto out;
371a995c792SAkinobu Mita 
37266b28183SAkinobu Mita 	bbt = kzalloc(ebcnt, GFP_KERNEL);
37366b28183SAkinobu Mita 	if (!bbt)
37466b28183SAkinobu Mita 		goto out;
37566b28183SAkinobu Mita 	err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
376a995c792SAkinobu Mita 	if (err)
377a995c792SAkinobu Mita 		goto out;
378a995c792SAkinobu Mita 
379a995c792SAkinobu Mita 	/* Erase all eraseblocks */
380a995c792SAkinobu Mita 	pr_info("erasing whole device\n");
38166b28183SAkinobu Mita 	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
382a995c792SAkinobu Mita 	if (err)
383a995c792SAkinobu Mita 		goto out;
38466b28183SAkinobu Mita 	pr_info("erased %u eraseblocks\n", ebcnt);
385a995c792SAkinobu Mita 
386a995c792SAkinobu Mita 	/* Write all eraseblocks */
387a995c792SAkinobu Mita 	prandom_seed_state(&rnd_state, 1);
388a995c792SAkinobu Mita 	pr_info("writing whole device\n");
389a995c792SAkinobu Mita 	for (i = 0; i < ebcnt; ++i) {
390a995c792SAkinobu Mita 		if (bbt[i])
391a995c792SAkinobu Mita 			continue;
392a995c792SAkinobu Mita 		err = write_eraseblock(i);
393a995c792SAkinobu Mita 		if (err)
394a995c792SAkinobu Mita 			goto out;
395a995c792SAkinobu Mita 		if (i % 256 == 0)
396a995c792SAkinobu Mita 			pr_info("written up to eraseblock %u\n", i);
3972a6a28e7SRichard Weinberger 
3982a6a28e7SRichard Weinberger 		err = mtdtest_relax();
3992a6a28e7SRichard Weinberger 		if (err)
4002a6a28e7SRichard Weinberger 			goto out;
401a995c792SAkinobu Mita 	}
402a995c792SAkinobu Mita 	pr_info("written %u eraseblocks\n", i);
403a995c792SAkinobu Mita 
404a995c792SAkinobu Mita 	/* Check all eraseblocks */
405a995c792SAkinobu Mita 	prandom_seed_state(&rnd_state, 1);
406a995c792SAkinobu Mita 	pr_info("verifying all eraseblocks\n");
407a995c792SAkinobu Mita 	for (i = 0; i < ebcnt; ++i) {
408a995c792SAkinobu Mita 		if (bbt[i])
409a995c792SAkinobu Mita 			continue;
410a995c792SAkinobu Mita 		err = verify_eraseblock(i);
411a995c792SAkinobu Mita 		if (err)
412a995c792SAkinobu Mita 			goto out;
413a995c792SAkinobu Mita 		if (i % 256 == 0)
414a995c792SAkinobu Mita 			pr_info("verified up to eraseblock %u\n", i);
4152a6a28e7SRichard Weinberger 
4162a6a28e7SRichard Weinberger 		err = mtdtest_relax();
4172a6a28e7SRichard Weinberger 		if (err)
4182a6a28e7SRichard Weinberger 			goto out;
419a995c792SAkinobu Mita 	}
420a995c792SAkinobu Mita 	pr_info("verified %u eraseblocks\n", i);
421a995c792SAkinobu Mita 
422a995c792SAkinobu Mita 	err = crosstest();
423a995c792SAkinobu Mita 	if (err)
424a995c792SAkinobu Mita 		goto out;
425a995c792SAkinobu Mita 
426148a1a5dSStefan Agner 	if (ebcnt > 1) {
427a995c792SAkinobu Mita 		err = erasecrosstest();
428a995c792SAkinobu Mita 		if (err)
429a995c792SAkinobu Mita 			goto out;
430148a1a5dSStefan Agner 	} else {
431148a1a5dSStefan Agner 		pr_info("skipping erasecrosstest, 2 erase blocks needed\n");
432148a1a5dSStefan Agner 	}
433a995c792SAkinobu Mita 
434a995c792SAkinobu Mita 	err = erasetest();
435a995c792SAkinobu Mita 	if (err)
436a995c792SAkinobu Mita 		goto out;
437a995c792SAkinobu Mita 
438a995c792SAkinobu Mita 	pr_info("finished with %d errors\n", errcnt);
439a995c792SAkinobu Mita out:
440a995c792SAkinobu Mita 
441a995c792SAkinobu Mita 	kfree(bbt);
442a995c792SAkinobu Mita 	kfree(boundary);
443a995c792SAkinobu Mita 	kfree(twopages);
444a995c792SAkinobu Mita 	kfree(writebuf);
445a995c792SAkinobu Mita 	put_mtd_device(mtd);
446a995c792SAkinobu Mita 	if (err)
447a995c792SAkinobu Mita 		pr_info("error %d occurred\n", err);
448a995c792SAkinobu Mita 	printk(KERN_INFO "=================================================\n");
449a995c792SAkinobu Mita 	return err;
450a995c792SAkinobu Mita }
451a995c792SAkinobu Mita module_init(mtd_pagetest_init);
452a995c792SAkinobu Mita 
mtd_pagetest_exit(void)453a995c792SAkinobu Mita static void __exit mtd_pagetest_exit(void)
454a995c792SAkinobu Mita {
455a995c792SAkinobu Mita 	return;
456a995c792SAkinobu Mita }
457a995c792SAkinobu Mita module_exit(mtd_pagetest_exit);
458a995c792SAkinobu Mita 
459a995c792SAkinobu Mita MODULE_DESCRIPTION("NAND page test");
460a995c792SAkinobu Mita MODULE_AUTHOR("Adrian Hunter");
461a995c792SAkinobu Mita MODULE_LICENSE("GPL");
462