xref: /openbmc/linux/drivers/mtd/tests/pagetest.c (revision abc173ad)
1a995c792SAkinobu Mita /*
2a995c792SAkinobu Mita  * Copyright (C) 2006-2008 Nokia Corporation
3a995c792SAkinobu Mita  *
4a995c792SAkinobu Mita  * This program is free software; you can redistribute it and/or modify it
5a995c792SAkinobu Mita  * under the terms of the GNU General Public License version 2 as published by
6a995c792SAkinobu Mita  * the Free Software Foundation.
7a995c792SAkinobu Mita  *
8a995c792SAkinobu Mita  * This program is distributed in the hope that it will be useful, but WITHOUT
9a995c792SAkinobu Mita  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10a995c792SAkinobu Mita  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11a995c792SAkinobu Mita  * more details.
12a995c792SAkinobu Mita  *
13a995c792SAkinobu Mita  * You should have received a copy of the GNU General Public License along with
14a995c792SAkinobu Mita  * this program; see the file COPYING. If not, write to the Free Software
15a995c792SAkinobu Mita  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16a995c792SAkinobu Mita  *
17a995c792SAkinobu Mita  * Test page read and write on MTD device.
18a995c792SAkinobu Mita  *
19a995c792SAkinobu Mita  * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
20a995c792SAkinobu Mita  */
21a995c792SAkinobu Mita 
22a995c792SAkinobu Mita #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23a995c792SAkinobu Mita 
24a995c792SAkinobu Mita #include <asm/div64.h>
25a995c792SAkinobu Mita #include <linux/init.h>
26a995c792SAkinobu Mita #include <linux/module.h>
27a995c792SAkinobu Mita #include <linux/moduleparam.h>
28a995c792SAkinobu Mita #include <linux/err.h>
29a995c792SAkinobu Mita #include <linux/mtd/mtd.h>
30a995c792SAkinobu Mita #include <linux/slab.h>
31a995c792SAkinobu Mita #include <linux/sched.h>
32a995c792SAkinobu Mita #include <linux/random.h>
33a995c792SAkinobu Mita 
3466b28183SAkinobu Mita #include "mtd_test.h"
3566b28183SAkinobu Mita 
36a995c792SAkinobu Mita static int dev = -EINVAL;
37a995c792SAkinobu Mita module_param(dev, int, S_IRUGO);
38a995c792SAkinobu Mita MODULE_PARM_DESC(dev, "MTD device number to use");
39a995c792SAkinobu Mita 
40a995c792SAkinobu Mita static struct mtd_info *mtd;
41a995c792SAkinobu Mita static unsigned char *twopages;
42a995c792SAkinobu Mita static unsigned char *writebuf;
43a995c792SAkinobu Mita static unsigned char *boundary;
44a995c792SAkinobu Mita static unsigned char *bbt;
45a995c792SAkinobu Mita 
46a995c792SAkinobu Mita static int pgsize;
47a995c792SAkinobu Mita static int bufsize;
48a995c792SAkinobu Mita static int ebcnt;
49a995c792SAkinobu Mita static int pgcnt;
50a995c792SAkinobu Mita static int errcnt;
51a995c792SAkinobu Mita static struct rnd_state rnd_state;
52a995c792SAkinobu Mita 
53a995c792SAkinobu Mita static int write_eraseblock(int ebnum)
54a995c792SAkinobu Mita {
5566b28183SAkinobu Mita 	int err;
56a995c792SAkinobu Mita 	loff_t addr = ebnum * mtd->erasesize;
57a995c792SAkinobu Mita 
58a995c792SAkinobu Mita 	prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
59a995c792SAkinobu Mita 	cond_resched();
6066b28183SAkinobu Mita 	err = mtdtest_write(mtd, addr, mtd->erasesize, writebuf);
6166b28183SAkinobu Mita 	if (err)
62a995c792SAkinobu Mita 		pr_err("error: write failed at %#llx\n",
63a995c792SAkinobu Mita 		       (long long)addr);
64a995c792SAkinobu Mita 
65a995c792SAkinobu Mita 	return err;
66a995c792SAkinobu Mita }
67a995c792SAkinobu Mita 
68a995c792SAkinobu Mita static int verify_eraseblock(int ebnum)
69a995c792SAkinobu Mita {
70a995c792SAkinobu Mita 	uint32_t j;
71a995c792SAkinobu Mita 	int err = 0, i;
72a995c792SAkinobu Mita 	loff_t addr0, addrn;
73a995c792SAkinobu Mita 	loff_t addr = ebnum * mtd->erasesize;
74a995c792SAkinobu Mita 
75a995c792SAkinobu Mita 	addr0 = 0;
76a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[i]; ++i)
77a995c792SAkinobu Mita 		addr0 += mtd->erasesize;
78a995c792SAkinobu Mita 
79a995c792SAkinobu Mita 	addrn = mtd->size;
80a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
81a995c792SAkinobu Mita 		addrn -= mtd->erasesize;
82a995c792SAkinobu Mita 
83a995c792SAkinobu Mita 	prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
84a995c792SAkinobu Mita 	for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) {
85a995c792SAkinobu Mita 		/* Do a read to set the internal dataRAMs to different data */
8666b28183SAkinobu Mita 		err = mtdtest_read(mtd, addr0, bufsize, twopages);
87abc173adSAkinobu Mita 		if (err)
88a995c792SAkinobu Mita 			return err;
8966b28183SAkinobu Mita 		err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages);
90abc173adSAkinobu Mita 		if (err)
91a995c792SAkinobu Mita 			return err;
92a995c792SAkinobu Mita 		memset(twopages, 0, bufsize);
9366b28183SAkinobu Mita 		err = mtdtest_read(mtd, addr, bufsize, twopages);
94abc173adSAkinobu Mita 		if (err)
95a995c792SAkinobu Mita 			break;
96a995c792SAkinobu Mita 		if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) {
97a995c792SAkinobu Mita 			pr_err("error: verify failed at %#llx\n",
98a995c792SAkinobu Mita 			       (long long)addr);
99a995c792SAkinobu Mita 			errcnt += 1;
100a995c792SAkinobu Mita 		}
101a995c792SAkinobu Mita 	}
102a995c792SAkinobu Mita 	/* Check boundary between eraseblocks */
103a995c792SAkinobu Mita 	if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) {
104a995c792SAkinobu Mita 		struct rnd_state old_state = rnd_state;
105a995c792SAkinobu Mita 
106a995c792SAkinobu Mita 		/* Do a read to set the internal dataRAMs to different data */
10766b28183SAkinobu Mita 		err = mtdtest_read(mtd, addr0, bufsize, twopages);
108abc173adSAkinobu Mita 		if (err)
109a995c792SAkinobu Mita 			return err;
11066b28183SAkinobu Mita 		err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages);
111abc173adSAkinobu Mita 		if (err)
112a995c792SAkinobu Mita 			return err;
113a995c792SAkinobu Mita 		memset(twopages, 0, bufsize);
11466b28183SAkinobu Mita 		err = mtdtest_read(mtd, addr, bufsize, twopages);
115abc173adSAkinobu Mita 		if (err)
116a995c792SAkinobu Mita 			return err;
117a995c792SAkinobu Mita 		memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize);
118a995c792SAkinobu Mita 		prandom_bytes_state(&rnd_state, boundary + pgsize, pgsize);
119a995c792SAkinobu Mita 		if (memcmp(twopages, boundary, bufsize)) {
120a995c792SAkinobu Mita 			pr_err("error: verify failed at %#llx\n",
121a995c792SAkinobu Mita 			       (long long)addr);
122a995c792SAkinobu Mita 			errcnt += 1;
123a995c792SAkinobu Mita 		}
124a995c792SAkinobu Mita 		rnd_state = old_state;
125a995c792SAkinobu Mita 	}
126a995c792SAkinobu Mita 	return err;
127a995c792SAkinobu Mita }
128a995c792SAkinobu Mita 
129a995c792SAkinobu Mita static int crosstest(void)
130a995c792SAkinobu Mita {
131a995c792SAkinobu Mita 	int err = 0, i;
132a995c792SAkinobu Mita 	loff_t addr, addr0, addrn;
133a995c792SAkinobu Mita 	unsigned char *pp1, *pp2, *pp3, *pp4;
134a995c792SAkinobu Mita 
135a995c792SAkinobu Mita 	pr_info("crosstest\n");
136a995c792SAkinobu Mita 	pp1 = kmalloc(pgsize * 4, GFP_KERNEL);
137a995c792SAkinobu Mita 	if (!pp1)
138a995c792SAkinobu Mita 		return -ENOMEM;
139a995c792SAkinobu Mita 	pp2 = pp1 + pgsize;
140a995c792SAkinobu Mita 	pp3 = pp2 + pgsize;
141a995c792SAkinobu Mita 	pp4 = pp3 + pgsize;
142a995c792SAkinobu Mita 	memset(pp1, 0, pgsize * 4);
143a995c792SAkinobu Mita 
144a995c792SAkinobu Mita 	addr0 = 0;
145a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[i]; ++i)
146a995c792SAkinobu Mita 		addr0 += mtd->erasesize;
147a995c792SAkinobu Mita 
148a995c792SAkinobu Mita 	addrn = mtd->size;
149a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
150a995c792SAkinobu Mita 		addrn -= mtd->erasesize;
151a995c792SAkinobu Mita 
152a995c792SAkinobu Mita 	/* Read 2nd-to-last page to pp1 */
153a995c792SAkinobu Mita 	addr = addrn - pgsize - pgsize;
15466b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr, pgsize, pp1);
15566b28183SAkinobu Mita 	if (err) {
156a995c792SAkinobu Mita 		kfree(pp1);
157a995c792SAkinobu Mita 		return err;
158a995c792SAkinobu Mita 	}
159a995c792SAkinobu Mita 
160a995c792SAkinobu Mita 	/* Read 3rd-to-last page to pp1 */
161a995c792SAkinobu Mita 	addr = addrn - pgsize - pgsize - pgsize;
16266b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr, pgsize, pp1);
16366b28183SAkinobu Mita 	if (err) {
164a995c792SAkinobu Mita 		kfree(pp1);
165a995c792SAkinobu Mita 		return err;
166a995c792SAkinobu Mita 	}
167a995c792SAkinobu Mita 
168a995c792SAkinobu Mita 	/* Read first page to pp2 */
169a995c792SAkinobu Mita 	addr = addr0;
170a995c792SAkinobu Mita 	pr_info("reading page at %#llx\n", (long long)addr);
17166b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr, pgsize, pp2);
17266b28183SAkinobu Mita 	if (err) {
173a995c792SAkinobu Mita 		kfree(pp1);
174a995c792SAkinobu Mita 		return err;
175a995c792SAkinobu Mita 	}
176a995c792SAkinobu Mita 
177a995c792SAkinobu Mita 	/* Read last page to pp3 */
178a995c792SAkinobu Mita 	addr = addrn - pgsize;
179a995c792SAkinobu Mita 	pr_info("reading page at %#llx\n", (long long)addr);
18066b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr, pgsize, pp3);
18166b28183SAkinobu Mita 	if (err) {
182a995c792SAkinobu Mita 		kfree(pp1);
183a995c792SAkinobu Mita 		return err;
184a995c792SAkinobu Mita 	}
185a995c792SAkinobu Mita 
186a995c792SAkinobu Mita 	/* Read first page again to pp4 */
187a995c792SAkinobu Mita 	addr = addr0;
188a995c792SAkinobu Mita 	pr_info("reading page at %#llx\n", (long long)addr);
18966b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr, pgsize, pp4);
19066b28183SAkinobu Mita 	if (err) {
191a995c792SAkinobu Mita 		kfree(pp1);
192a995c792SAkinobu Mita 		return err;
193a995c792SAkinobu Mita 	}
194a995c792SAkinobu Mita 
195a995c792SAkinobu Mita 	/* pp2 and pp4 should be the same */
196a995c792SAkinobu Mita 	pr_info("verifying pages read at %#llx match\n",
197a995c792SAkinobu Mita 	       (long long)addr0);
198a995c792SAkinobu Mita 	if (memcmp(pp2, pp4, pgsize)) {
199a995c792SAkinobu Mita 		pr_err("verify failed!\n");
200a995c792SAkinobu Mita 		errcnt += 1;
201a995c792SAkinobu Mita 	} else if (!err)
202a995c792SAkinobu Mita 		pr_info("crosstest ok\n");
203a995c792SAkinobu Mita 	kfree(pp1);
204a995c792SAkinobu Mita 	return err;
205a995c792SAkinobu Mita }
206a995c792SAkinobu Mita 
207a995c792SAkinobu Mita static int erasecrosstest(void)
208a995c792SAkinobu Mita {
209a995c792SAkinobu Mita 	int err = 0, i, ebnum, ebnum2;
210a995c792SAkinobu Mita 	loff_t addr0;
211a995c792SAkinobu Mita 	char *readbuf = twopages;
212a995c792SAkinobu Mita 
213a995c792SAkinobu Mita 	pr_info("erasecrosstest\n");
214a995c792SAkinobu Mita 
215a995c792SAkinobu Mita 	ebnum = 0;
216a995c792SAkinobu Mita 	addr0 = 0;
217a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[i]; ++i) {
218a995c792SAkinobu Mita 		addr0 += mtd->erasesize;
219a995c792SAkinobu Mita 		ebnum += 1;
220a995c792SAkinobu Mita 	}
221a995c792SAkinobu Mita 
222a995c792SAkinobu Mita 	ebnum2 = ebcnt - 1;
223a995c792SAkinobu Mita 	while (ebnum2 && bbt[ebnum2])
224a995c792SAkinobu Mita 		ebnum2 -= 1;
225a995c792SAkinobu Mita 
226a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum);
22766b28183SAkinobu Mita 	err = mtdtest_erase_eraseblock(mtd, ebnum);
228a995c792SAkinobu Mita 	if (err)
229a995c792SAkinobu Mita 		return err;
230a995c792SAkinobu Mita 
231a995c792SAkinobu Mita 	pr_info("writing 1st page of block %d\n", ebnum);
232a995c792SAkinobu Mita 	prandom_bytes_state(&rnd_state, writebuf, pgsize);
233a995c792SAkinobu Mita 	strcpy(writebuf, "There is no data like this!");
23466b28183SAkinobu Mita 	err = mtdtest_write(mtd, addr0, pgsize, writebuf);
23566b28183SAkinobu Mita 	if (err) {
236a995c792SAkinobu Mita 		pr_info("error: write failed at %#llx\n",
237a995c792SAkinobu Mita 		       (long long)addr0);
23866b28183SAkinobu Mita 		return err;
239a995c792SAkinobu Mita 	}
240a995c792SAkinobu Mita 
241a995c792SAkinobu Mita 	pr_info("reading 1st page of block %d\n", ebnum);
242a995c792SAkinobu Mita 	memset(readbuf, 0, pgsize);
24366b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr0, pgsize, readbuf);
244abc173adSAkinobu Mita 	if (err)
24566b28183SAkinobu Mita 		return err;
246a995c792SAkinobu Mita 
247a995c792SAkinobu Mita 	pr_info("verifying 1st page of block %d\n", ebnum);
248a995c792SAkinobu Mita 	if (memcmp(writebuf, readbuf, pgsize)) {
249a995c792SAkinobu Mita 		pr_err("verify failed!\n");
250a995c792SAkinobu Mita 		errcnt += 1;
251a995c792SAkinobu Mita 		return -1;
252a995c792SAkinobu Mita 	}
253a995c792SAkinobu Mita 
254a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum);
25566b28183SAkinobu Mita 	err = mtdtest_erase_eraseblock(mtd, ebnum);
256a995c792SAkinobu Mita 	if (err)
257a995c792SAkinobu Mita 		return err;
258a995c792SAkinobu Mita 
259a995c792SAkinobu Mita 	pr_info("writing 1st page of block %d\n", ebnum);
260a995c792SAkinobu Mita 	prandom_bytes_state(&rnd_state, writebuf, pgsize);
261a995c792SAkinobu Mita 	strcpy(writebuf, "There is no data like this!");
26266b28183SAkinobu Mita 	err = mtdtest_write(mtd, addr0, pgsize, writebuf);
26366b28183SAkinobu Mita 	if (err) {
264a995c792SAkinobu Mita 		pr_err("error: write failed at %#llx\n",
265a995c792SAkinobu Mita 		       (long long)addr0);
26666b28183SAkinobu Mita 		return err;
267a995c792SAkinobu Mita 	}
268a995c792SAkinobu Mita 
269a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum2);
27066b28183SAkinobu Mita 	err = mtdtest_erase_eraseblock(mtd, ebnum2);
271a995c792SAkinobu Mita 	if (err)
272a995c792SAkinobu Mita 		return err;
273a995c792SAkinobu Mita 
274a995c792SAkinobu Mita 	pr_info("reading 1st page of block %d\n", ebnum);
275a995c792SAkinobu Mita 	memset(readbuf, 0, pgsize);
27666b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr0, pgsize, readbuf);
277abc173adSAkinobu Mita 	if (err)
27866b28183SAkinobu Mita 		return err;
279a995c792SAkinobu Mita 
280a995c792SAkinobu Mita 	pr_info("verifying 1st page of block %d\n", ebnum);
281a995c792SAkinobu Mita 	if (memcmp(writebuf, readbuf, pgsize)) {
282a995c792SAkinobu Mita 		pr_err("verify failed!\n");
283a995c792SAkinobu Mita 		errcnt += 1;
284a995c792SAkinobu Mita 		return -1;
285a995c792SAkinobu Mita 	}
286a995c792SAkinobu Mita 
287a995c792SAkinobu Mita 	if (!err)
288a995c792SAkinobu Mita 		pr_info("erasecrosstest ok\n");
289a995c792SAkinobu Mita 	return err;
290a995c792SAkinobu Mita }
291a995c792SAkinobu Mita 
292a995c792SAkinobu Mita static int erasetest(void)
293a995c792SAkinobu Mita {
294a995c792SAkinobu Mita 	int err = 0, i, ebnum, ok = 1;
295a995c792SAkinobu Mita 	loff_t addr0;
296a995c792SAkinobu Mita 
297a995c792SAkinobu Mita 	pr_info("erasetest\n");
298a995c792SAkinobu Mita 
299a995c792SAkinobu Mita 	ebnum = 0;
300a995c792SAkinobu Mita 	addr0 = 0;
301a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[i]; ++i) {
302a995c792SAkinobu Mita 		addr0 += mtd->erasesize;
303a995c792SAkinobu Mita 		ebnum += 1;
304a995c792SAkinobu Mita 	}
305a995c792SAkinobu Mita 
306a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum);
30766b28183SAkinobu Mita 	err = mtdtest_erase_eraseblock(mtd, ebnum);
308a995c792SAkinobu Mita 	if (err)
309a995c792SAkinobu Mita 		return err;
310a995c792SAkinobu Mita 
311a995c792SAkinobu Mita 	pr_info("writing 1st page of block %d\n", ebnum);
312a995c792SAkinobu Mita 	prandom_bytes_state(&rnd_state, writebuf, pgsize);
31366b28183SAkinobu Mita 	err = mtdtest_write(mtd, addr0, pgsize, writebuf);
31466b28183SAkinobu Mita 	if (err) {
315a995c792SAkinobu Mita 		pr_err("error: write failed at %#llx\n",
316a995c792SAkinobu Mita 		       (long long)addr0);
31766b28183SAkinobu Mita 		return err;
318a995c792SAkinobu Mita 	}
319a995c792SAkinobu Mita 
320a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum);
32166b28183SAkinobu Mita 	err = mtdtest_erase_eraseblock(mtd, ebnum);
322a995c792SAkinobu Mita 	if (err)
323a995c792SAkinobu Mita 		return err;
324a995c792SAkinobu Mita 
325a995c792SAkinobu Mita 	pr_info("reading 1st page of block %d\n", ebnum);
32666b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr0, pgsize, twopages);
327abc173adSAkinobu Mita 	if (err)
32866b28183SAkinobu Mita 		return err;
329a995c792SAkinobu Mita 
330a995c792SAkinobu Mita 	pr_info("verifying 1st page of block %d is all 0xff\n",
331a995c792SAkinobu Mita 	       ebnum);
332a995c792SAkinobu Mita 	for (i = 0; i < pgsize; ++i)
333a995c792SAkinobu Mita 		if (twopages[i] != 0xff) {
334a995c792SAkinobu Mita 			pr_err("verifying all 0xff failed at %d\n",
335a995c792SAkinobu Mita 			       i);
336a995c792SAkinobu Mita 			errcnt += 1;
337a995c792SAkinobu Mita 			ok = 0;
338a995c792SAkinobu Mita 			break;
339a995c792SAkinobu Mita 		}
340a995c792SAkinobu Mita 
341a995c792SAkinobu Mita 	if (ok && !err)
342a995c792SAkinobu Mita 		pr_info("erasetest ok\n");
343a995c792SAkinobu Mita 
344a995c792SAkinobu Mita 	return err;
345a995c792SAkinobu Mita }
346a995c792SAkinobu Mita 
347a995c792SAkinobu Mita static int __init mtd_pagetest_init(void)
348a995c792SAkinobu Mita {
349a995c792SAkinobu Mita 	int err = 0;
350a995c792SAkinobu Mita 	uint64_t tmp;
351a995c792SAkinobu Mita 	uint32_t i;
352a995c792SAkinobu Mita 
353a995c792SAkinobu Mita 	printk(KERN_INFO "\n");
354a995c792SAkinobu Mita 	printk(KERN_INFO "=================================================\n");
355a995c792SAkinobu Mita 
356a995c792SAkinobu Mita 	if (dev < 0) {
357a995c792SAkinobu Mita 		pr_info("Please specify a valid mtd-device via module parameter\n");
358a995c792SAkinobu Mita 		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
359a995c792SAkinobu Mita 		return -EINVAL;
360a995c792SAkinobu Mita 	}
361a995c792SAkinobu Mita 
362a995c792SAkinobu Mita 	pr_info("MTD device: %d\n", dev);
363a995c792SAkinobu Mita 
364a995c792SAkinobu Mita 	mtd = get_mtd_device(NULL, dev);
365a995c792SAkinobu Mita 	if (IS_ERR(mtd)) {
366a995c792SAkinobu Mita 		err = PTR_ERR(mtd);
367a995c792SAkinobu Mita 		pr_err("error: cannot get MTD device\n");
368a995c792SAkinobu Mita 		return err;
369a995c792SAkinobu Mita 	}
370a995c792SAkinobu Mita 
371a995c792SAkinobu Mita 	if (mtd->type != MTD_NANDFLASH) {
372a995c792SAkinobu Mita 		pr_info("this test requires NAND flash\n");
373a995c792SAkinobu Mita 		goto out;
374a995c792SAkinobu Mita 	}
375a995c792SAkinobu Mita 
376a995c792SAkinobu Mita 	tmp = mtd->size;
377a995c792SAkinobu Mita 	do_div(tmp, mtd->erasesize);
378a995c792SAkinobu Mita 	ebcnt = tmp;
379a995c792SAkinobu Mita 	pgcnt = mtd->erasesize / mtd->writesize;
380a995c792SAkinobu Mita 	pgsize = mtd->writesize;
381a995c792SAkinobu Mita 
382a995c792SAkinobu Mita 	pr_info("MTD device size %llu, eraseblock size %u, "
383a995c792SAkinobu Mita 	       "page size %u, count of eraseblocks %u, pages per "
384a995c792SAkinobu Mita 	       "eraseblock %u, OOB size %u\n",
385a995c792SAkinobu Mita 	       (unsigned long long)mtd->size, mtd->erasesize,
386a995c792SAkinobu Mita 	       pgsize, ebcnt, pgcnt, mtd->oobsize);
387a995c792SAkinobu Mita 
388a995c792SAkinobu Mita 	err = -ENOMEM;
389a995c792SAkinobu Mita 	bufsize = pgsize * 2;
390a995c792SAkinobu Mita 	writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
391a995c792SAkinobu Mita 	if (!writebuf)
392a995c792SAkinobu Mita 		goto out;
393a995c792SAkinobu Mita 	twopages = kmalloc(bufsize, GFP_KERNEL);
394a995c792SAkinobu Mita 	if (!twopages)
395a995c792SAkinobu Mita 		goto out;
396a995c792SAkinobu Mita 	boundary = kmalloc(bufsize, GFP_KERNEL);
397a995c792SAkinobu Mita 	if (!boundary)
398a995c792SAkinobu Mita 		goto out;
399a995c792SAkinobu Mita 
40066b28183SAkinobu Mita 	bbt = kzalloc(ebcnt, GFP_KERNEL);
40166b28183SAkinobu Mita 	if (!bbt)
40266b28183SAkinobu Mita 		goto out;
40366b28183SAkinobu Mita 	err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
404a995c792SAkinobu Mita 	if (err)
405a995c792SAkinobu Mita 		goto out;
406a995c792SAkinobu Mita 
407a995c792SAkinobu Mita 	/* Erase all eraseblocks */
408a995c792SAkinobu Mita 	pr_info("erasing whole device\n");
40966b28183SAkinobu Mita 	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
410a995c792SAkinobu Mita 	if (err)
411a995c792SAkinobu Mita 		goto out;
41266b28183SAkinobu Mita 	pr_info("erased %u eraseblocks\n", ebcnt);
413a995c792SAkinobu Mita 
414a995c792SAkinobu Mita 	/* Write all eraseblocks */
415a995c792SAkinobu Mita 	prandom_seed_state(&rnd_state, 1);
416a995c792SAkinobu Mita 	pr_info("writing whole device\n");
417a995c792SAkinobu Mita 	for (i = 0; i < ebcnt; ++i) {
418a995c792SAkinobu Mita 		if (bbt[i])
419a995c792SAkinobu Mita 			continue;
420a995c792SAkinobu Mita 		err = write_eraseblock(i);
421a995c792SAkinobu Mita 		if (err)
422a995c792SAkinobu Mita 			goto out;
423a995c792SAkinobu Mita 		if (i % 256 == 0)
424a995c792SAkinobu Mita 			pr_info("written up to eraseblock %u\n", i);
425a995c792SAkinobu Mita 		cond_resched();
426a995c792SAkinobu Mita 	}
427a995c792SAkinobu Mita 	pr_info("written %u eraseblocks\n", i);
428a995c792SAkinobu Mita 
429a995c792SAkinobu Mita 	/* Check all eraseblocks */
430a995c792SAkinobu Mita 	prandom_seed_state(&rnd_state, 1);
431a995c792SAkinobu Mita 	pr_info("verifying all eraseblocks\n");
432a995c792SAkinobu Mita 	for (i = 0; i < ebcnt; ++i) {
433a995c792SAkinobu Mita 		if (bbt[i])
434a995c792SAkinobu Mita 			continue;
435a995c792SAkinobu Mita 		err = verify_eraseblock(i);
436a995c792SAkinobu Mita 		if (err)
437a995c792SAkinobu Mita 			goto out;
438a995c792SAkinobu Mita 		if (i % 256 == 0)
439a995c792SAkinobu Mita 			pr_info("verified up to eraseblock %u\n", i);
440a995c792SAkinobu Mita 		cond_resched();
441a995c792SAkinobu Mita 	}
442a995c792SAkinobu Mita 	pr_info("verified %u eraseblocks\n", i);
443a995c792SAkinobu Mita 
444a995c792SAkinobu Mita 	err = crosstest();
445a995c792SAkinobu Mita 	if (err)
446a995c792SAkinobu Mita 		goto out;
447a995c792SAkinobu Mita 
448a995c792SAkinobu Mita 	err = erasecrosstest();
449a995c792SAkinobu Mita 	if (err)
450a995c792SAkinobu Mita 		goto out;
451a995c792SAkinobu Mita 
452a995c792SAkinobu Mita 	err = erasetest();
453a995c792SAkinobu Mita 	if (err)
454a995c792SAkinobu Mita 		goto out;
455a995c792SAkinobu Mita 
456a995c792SAkinobu Mita 	pr_info("finished with %d errors\n", errcnt);
457a995c792SAkinobu Mita out:
458a995c792SAkinobu Mita 
459a995c792SAkinobu Mita 	kfree(bbt);
460a995c792SAkinobu Mita 	kfree(boundary);
461a995c792SAkinobu Mita 	kfree(twopages);
462a995c792SAkinobu Mita 	kfree(writebuf);
463a995c792SAkinobu Mita 	put_mtd_device(mtd);
464a995c792SAkinobu Mita 	if (err)
465a995c792SAkinobu Mita 		pr_info("error %d occurred\n", err);
466a995c792SAkinobu Mita 	printk(KERN_INFO "=================================================\n");
467a995c792SAkinobu Mita 	return err;
468a995c792SAkinobu Mita }
469a995c792SAkinobu Mita module_init(mtd_pagetest_init);
470a995c792SAkinobu Mita 
471a995c792SAkinobu Mita static void __exit mtd_pagetest_exit(void)
472a995c792SAkinobu Mita {
473a995c792SAkinobu Mita 	return;
474a995c792SAkinobu Mita }
475a995c792SAkinobu Mita module_exit(mtd_pagetest_exit);
476a995c792SAkinobu Mita 
477a995c792SAkinobu Mita MODULE_DESCRIPTION("NAND page test");
478a995c792SAkinobu Mita MODULE_AUTHOR("Adrian Hunter");
479a995c792SAkinobu Mita MODULE_LICENSE("GPL");
480