xref: /openbmc/linux/drivers/mtd/tests/pagetest.c (revision 66b28183)
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);
8766b28183SAkinobu Mita 		if (err) {
88a995c792SAkinobu Mita 			pr_err("error: read failed at %#llx\n",
89a995c792SAkinobu Mita 			       (long long)addr0);
90a995c792SAkinobu Mita 			return err;
91a995c792SAkinobu Mita 		}
9266b28183SAkinobu Mita 		err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages);
9366b28183SAkinobu Mita 		if (err) {
94a995c792SAkinobu Mita 			pr_err("error: read failed at %#llx\n",
95a995c792SAkinobu Mita 			       (long long)(addrn - bufsize));
96a995c792SAkinobu Mita 			return err;
97a995c792SAkinobu Mita 		}
98a995c792SAkinobu Mita 		memset(twopages, 0, bufsize);
9966b28183SAkinobu Mita 		err = mtdtest_read(mtd, addr, bufsize, twopages);
10066b28183SAkinobu Mita 		if (err) {
101a995c792SAkinobu Mita 			pr_err("error: read failed at %#llx\n",
102a995c792SAkinobu Mita 			       (long long)addr);
103a995c792SAkinobu Mita 			break;
104a995c792SAkinobu Mita 		}
105a995c792SAkinobu Mita 		if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) {
106a995c792SAkinobu Mita 			pr_err("error: verify failed at %#llx\n",
107a995c792SAkinobu Mita 			       (long long)addr);
108a995c792SAkinobu Mita 			errcnt += 1;
109a995c792SAkinobu Mita 		}
110a995c792SAkinobu Mita 	}
111a995c792SAkinobu Mita 	/* Check boundary between eraseblocks */
112a995c792SAkinobu Mita 	if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) {
113a995c792SAkinobu Mita 		struct rnd_state old_state = rnd_state;
114a995c792SAkinobu Mita 
115a995c792SAkinobu Mita 		/* Do a read to set the internal dataRAMs to different data */
11666b28183SAkinobu Mita 		err = mtdtest_read(mtd, addr0, bufsize, twopages);
11766b28183SAkinobu Mita 		if (err) {
118a995c792SAkinobu Mita 			pr_err("error: read failed at %#llx\n",
119a995c792SAkinobu Mita 			       (long long)addr0);
120a995c792SAkinobu Mita 			return err;
121a995c792SAkinobu Mita 		}
12266b28183SAkinobu Mita 		err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages);
12366b28183SAkinobu Mita 		if (err) {
124a995c792SAkinobu Mita 			pr_err("error: read failed at %#llx\n",
125a995c792SAkinobu Mita 			       (long long)(addrn - bufsize));
126a995c792SAkinobu Mita 			return err;
127a995c792SAkinobu Mita 		}
128a995c792SAkinobu Mita 		memset(twopages, 0, bufsize);
12966b28183SAkinobu Mita 		err = mtdtest_read(mtd, addr, bufsize, twopages);
13066b28183SAkinobu Mita 		if (err) {
131a995c792SAkinobu Mita 			pr_err("error: read failed at %#llx\n",
132a995c792SAkinobu Mita 			       (long long)addr);
133a995c792SAkinobu Mita 			return err;
134a995c792SAkinobu Mita 		}
135a995c792SAkinobu Mita 		memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize);
136a995c792SAkinobu Mita 		prandom_bytes_state(&rnd_state, boundary + pgsize, pgsize);
137a995c792SAkinobu Mita 		if (memcmp(twopages, boundary, bufsize)) {
138a995c792SAkinobu Mita 			pr_err("error: verify failed at %#llx\n",
139a995c792SAkinobu Mita 			       (long long)addr);
140a995c792SAkinobu Mita 			errcnt += 1;
141a995c792SAkinobu Mita 		}
142a995c792SAkinobu Mita 		rnd_state = old_state;
143a995c792SAkinobu Mita 	}
144a995c792SAkinobu Mita 	return err;
145a995c792SAkinobu Mita }
146a995c792SAkinobu Mita 
147a995c792SAkinobu Mita static int crosstest(void)
148a995c792SAkinobu Mita {
149a995c792SAkinobu Mita 	int err = 0, i;
150a995c792SAkinobu Mita 	loff_t addr, addr0, addrn;
151a995c792SAkinobu Mita 	unsigned char *pp1, *pp2, *pp3, *pp4;
152a995c792SAkinobu Mita 
153a995c792SAkinobu Mita 	pr_info("crosstest\n");
154a995c792SAkinobu Mita 	pp1 = kmalloc(pgsize * 4, GFP_KERNEL);
155a995c792SAkinobu Mita 	if (!pp1)
156a995c792SAkinobu Mita 		return -ENOMEM;
157a995c792SAkinobu Mita 	pp2 = pp1 + pgsize;
158a995c792SAkinobu Mita 	pp3 = pp2 + pgsize;
159a995c792SAkinobu Mita 	pp4 = pp3 + pgsize;
160a995c792SAkinobu Mita 	memset(pp1, 0, pgsize * 4);
161a995c792SAkinobu Mita 
162a995c792SAkinobu Mita 	addr0 = 0;
163a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[i]; ++i)
164a995c792SAkinobu Mita 		addr0 += mtd->erasesize;
165a995c792SAkinobu Mita 
166a995c792SAkinobu Mita 	addrn = mtd->size;
167a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
168a995c792SAkinobu Mita 		addrn -= mtd->erasesize;
169a995c792SAkinobu Mita 
170a995c792SAkinobu Mita 	/* Read 2nd-to-last page to pp1 */
171a995c792SAkinobu Mita 	addr = addrn - pgsize - pgsize;
17266b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr, pgsize, pp1);
17366b28183SAkinobu Mita 	if (err) {
174a995c792SAkinobu Mita 		pr_err("error: read failed at %#llx\n",
175a995c792SAkinobu Mita 		       (long long)addr);
176a995c792SAkinobu Mita 		kfree(pp1);
177a995c792SAkinobu Mita 		return err;
178a995c792SAkinobu Mita 	}
179a995c792SAkinobu Mita 
180a995c792SAkinobu Mita 	/* Read 3rd-to-last page to pp1 */
181a995c792SAkinobu Mita 	addr = addrn - pgsize - pgsize - pgsize;
18266b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr, pgsize, pp1);
18366b28183SAkinobu Mita 	if (err) {
184a995c792SAkinobu Mita 		pr_err("error: read failed at %#llx\n",
185a995c792SAkinobu Mita 		       (long long)addr);
186a995c792SAkinobu Mita 		kfree(pp1);
187a995c792SAkinobu Mita 		return err;
188a995c792SAkinobu Mita 	}
189a995c792SAkinobu Mita 
190a995c792SAkinobu Mita 	/* Read first page to pp2 */
191a995c792SAkinobu Mita 	addr = addr0;
192a995c792SAkinobu Mita 	pr_info("reading page at %#llx\n", (long long)addr);
19366b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr, pgsize, pp2);
19466b28183SAkinobu Mita 	if (err) {
195a995c792SAkinobu Mita 		pr_err("error: read failed at %#llx\n",
196a995c792SAkinobu Mita 		       (long long)addr);
197a995c792SAkinobu Mita 		kfree(pp1);
198a995c792SAkinobu Mita 		return err;
199a995c792SAkinobu Mita 	}
200a995c792SAkinobu Mita 
201a995c792SAkinobu Mita 	/* Read last page to pp3 */
202a995c792SAkinobu Mita 	addr = addrn - pgsize;
203a995c792SAkinobu Mita 	pr_info("reading page at %#llx\n", (long long)addr);
20466b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr, pgsize, pp3);
20566b28183SAkinobu Mita 	if (err) {
206a995c792SAkinobu Mita 		pr_err("error: read failed at %#llx\n",
207a995c792SAkinobu Mita 		       (long long)addr);
208a995c792SAkinobu Mita 		kfree(pp1);
209a995c792SAkinobu Mita 		return err;
210a995c792SAkinobu Mita 	}
211a995c792SAkinobu Mita 
212a995c792SAkinobu Mita 	/* Read first page again to pp4 */
213a995c792SAkinobu Mita 	addr = addr0;
214a995c792SAkinobu Mita 	pr_info("reading page at %#llx\n", (long long)addr);
21566b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr, pgsize, pp4);
21666b28183SAkinobu Mita 	if (err) {
217a995c792SAkinobu Mita 		pr_err("error: read failed at %#llx\n",
218a995c792SAkinobu Mita 		       (long long)addr);
219a995c792SAkinobu Mita 		kfree(pp1);
220a995c792SAkinobu Mita 		return err;
221a995c792SAkinobu Mita 	}
222a995c792SAkinobu Mita 
223a995c792SAkinobu Mita 	/* pp2 and pp4 should be the same */
224a995c792SAkinobu Mita 	pr_info("verifying pages read at %#llx match\n",
225a995c792SAkinobu Mita 	       (long long)addr0);
226a995c792SAkinobu Mita 	if (memcmp(pp2, pp4, pgsize)) {
227a995c792SAkinobu Mita 		pr_err("verify failed!\n");
228a995c792SAkinobu Mita 		errcnt += 1;
229a995c792SAkinobu Mita 	} else if (!err)
230a995c792SAkinobu Mita 		pr_info("crosstest ok\n");
231a995c792SAkinobu Mita 	kfree(pp1);
232a995c792SAkinobu Mita 	return err;
233a995c792SAkinobu Mita }
234a995c792SAkinobu Mita 
235a995c792SAkinobu Mita static int erasecrosstest(void)
236a995c792SAkinobu Mita {
237a995c792SAkinobu Mita 	int err = 0, i, ebnum, ebnum2;
238a995c792SAkinobu Mita 	loff_t addr0;
239a995c792SAkinobu Mita 	char *readbuf = twopages;
240a995c792SAkinobu Mita 
241a995c792SAkinobu Mita 	pr_info("erasecrosstest\n");
242a995c792SAkinobu Mita 
243a995c792SAkinobu Mita 	ebnum = 0;
244a995c792SAkinobu Mita 	addr0 = 0;
245a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[i]; ++i) {
246a995c792SAkinobu Mita 		addr0 += mtd->erasesize;
247a995c792SAkinobu Mita 		ebnum += 1;
248a995c792SAkinobu Mita 	}
249a995c792SAkinobu Mita 
250a995c792SAkinobu Mita 	ebnum2 = ebcnt - 1;
251a995c792SAkinobu Mita 	while (ebnum2 && bbt[ebnum2])
252a995c792SAkinobu Mita 		ebnum2 -= 1;
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_info("error: write failed at %#llx\n",
265a995c792SAkinobu Mita 		       (long long)addr0);
26666b28183SAkinobu Mita 		return err;
267a995c792SAkinobu Mita 	}
268a995c792SAkinobu Mita 
269a995c792SAkinobu Mita 	pr_info("reading 1st page of block %d\n", ebnum);
270a995c792SAkinobu Mita 	memset(readbuf, 0, pgsize);
27166b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr0, pgsize, readbuf);
27266b28183SAkinobu Mita 	if (err) {
273a995c792SAkinobu Mita 		pr_err("error: read failed at %#llx\n",
274a995c792SAkinobu Mita 		       (long long)addr0);
27566b28183SAkinobu Mita 		return err;
276a995c792SAkinobu Mita 	}
277a995c792SAkinobu Mita 
278a995c792SAkinobu Mita 	pr_info("verifying 1st page of block %d\n", ebnum);
279a995c792SAkinobu Mita 	if (memcmp(writebuf, readbuf, pgsize)) {
280a995c792SAkinobu Mita 		pr_err("verify failed!\n");
281a995c792SAkinobu Mita 		errcnt += 1;
282a995c792SAkinobu Mita 		return -1;
283a995c792SAkinobu Mita 	}
284a995c792SAkinobu Mita 
285a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum);
28666b28183SAkinobu Mita 	err = mtdtest_erase_eraseblock(mtd, ebnum);
287a995c792SAkinobu Mita 	if (err)
288a995c792SAkinobu Mita 		return err;
289a995c792SAkinobu Mita 
290a995c792SAkinobu Mita 	pr_info("writing 1st page of block %d\n", ebnum);
291a995c792SAkinobu Mita 	prandom_bytes_state(&rnd_state, writebuf, pgsize);
292a995c792SAkinobu Mita 	strcpy(writebuf, "There is no data like this!");
29366b28183SAkinobu Mita 	err = mtdtest_write(mtd, addr0, pgsize, writebuf);
29466b28183SAkinobu Mita 	if (err) {
295a995c792SAkinobu Mita 		pr_err("error: write failed at %#llx\n",
296a995c792SAkinobu Mita 		       (long long)addr0);
29766b28183SAkinobu Mita 		return err;
298a995c792SAkinobu Mita 	}
299a995c792SAkinobu Mita 
300a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum2);
30166b28183SAkinobu Mita 	err = mtdtest_erase_eraseblock(mtd, ebnum2);
302a995c792SAkinobu Mita 	if (err)
303a995c792SAkinobu Mita 		return err;
304a995c792SAkinobu Mita 
305a995c792SAkinobu Mita 	pr_info("reading 1st page of block %d\n", ebnum);
306a995c792SAkinobu Mita 	memset(readbuf, 0, pgsize);
30766b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr0, pgsize, readbuf);
30866b28183SAkinobu Mita 	if (err) {
309a995c792SAkinobu Mita 		pr_err("error: read failed at %#llx\n",
310a995c792SAkinobu Mita 		       (long long)addr0);
31166b28183SAkinobu Mita 		return err;
312a995c792SAkinobu Mita 	}
313a995c792SAkinobu Mita 
314a995c792SAkinobu Mita 	pr_info("verifying 1st page of block %d\n", ebnum);
315a995c792SAkinobu Mita 	if (memcmp(writebuf, readbuf, pgsize)) {
316a995c792SAkinobu Mita 		pr_err("verify failed!\n");
317a995c792SAkinobu Mita 		errcnt += 1;
318a995c792SAkinobu Mita 		return -1;
319a995c792SAkinobu Mita 	}
320a995c792SAkinobu Mita 
321a995c792SAkinobu Mita 	if (!err)
322a995c792SAkinobu Mita 		pr_info("erasecrosstest ok\n");
323a995c792SAkinobu Mita 	return err;
324a995c792SAkinobu Mita }
325a995c792SAkinobu Mita 
326a995c792SAkinobu Mita static int erasetest(void)
327a995c792SAkinobu Mita {
328a995c792SAkinobu Mita 	int err = 0, i, ebnum, ok = 1;
329a995c792SAkinobu Mita 	loff_t addr0;
330a995c792SAkinobu Mita 
331a995c792SAkinobu Mita 	pr_info("erasetest\n");
332a995c792SAkinobu Mita 
333a995c792SAkinobu Mita 	ebnum = 0;
334a995c792SAkinobu Mita 	addr0 = 0;
335a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[i]; ++i) {
336a995c792SAkinobu Mita 		addr0 += mtd->erasesize;
337a995c792SAkinobu Mita 		ebnum += 1;
338a995c792SAkinobu Mita 	}
339a995c792SAkinobu Mita 
340a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum);
34166b28183SAkinobu Mita 	err = mtdtest_erase_eraseblock(mtd, ebnum);
342a995c792SAkinobu Mita 	if (err)
343a995c792SAkinobu Mita 		return err;
344a995c792SAkinobu Mita 
345a995c792SAkinobu Mita 	pr_info("writing 1st page of block %d\n", ebnum);
346a995c792SAkinobu Mita 	prandom_bytes_state(&rnd_state, writebuf, pgsize);
34766b28183SAkinobu Mita 	err = mtdtest_write(mtd, addr0, pgsize, writebuf);
34866b28183SAkinobu Mita 	if (err) {
349a995c792SAkinobu Mita 		pr_err("error: write failed at %#llx\n",
350a995c792SAkinobu Mita 		       (long long)addr0);
35166b28183SAkinobu Mita 		return err;
352a995c792SAkinobu Mita 	}
353a995c792SAkinobu Mita 
354a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum);
35566b28183SAkinobu Mita 	err = mtdtest_erase_eraseblock(mtd, ebnum);
356a995c792SAkinobu Mita 	if (err)
357a995c792SAkinobu Mita 		return err;
358a995c792SAkinobu Mita 
359a995c792SAkinobu Mita 	pr_info("reading 1st page of block %d\n", ebnum);
36066b28183SAkinobu Mita 	err = mtdtest_read(mtd, addr0, pgsize, twopages);
36166b28183SAkinobu Mita 	if (err) {
362a995c792SAkinobu Mita 		pr_err("error: read failed at %#llx\n",
363a995c792SAkinobu Mita 		       (long long)addr0);
36466b28183SAkinobu Mita 		return err;
365a995c792SAkinobu Mita 	}
366a995c792SAkinobu Mita 
367a995c792SAkinobu Mita 	pr_info("verifying 1st page of block %d is all 0xff\n",
368a995c792SAkinobu Mita 	       ebnum);
369a995c792SAkinobu Mita 	for (i = 0; i < pgsize; ++i)
370a995c792SAkinobu Mita 		if (twopages[i] != 0xff) {
371a995c792SAkinobu Mita 			pr_err("verifying all 0xff failed at %d\n",
372a995c792SAkinobu Mita 			       i);
373a995c792SAkinobu Mita 			errcnt += 1;
374a995c792SAkinobu Mita 			ok = 0;
375a995c792SAkinobu Mita 			break;
376a995c792SAkinobu Mita 		}
377a995c792SAkinobu Mita 
378a995c792SAkinobu Mita 	if (ok && !err)
379a995c792SAkinobu Mita 		pr_info("erasetest ok\n");
380a995c792SAkinobu Mita 
381a995c792SAkinobu Mita 	return err;
382a995c792SAkinobu Mita }
383a995c792SAkinobu Mita 
384a995c792SAkinobu Mita static int __init mtd_pagetest_init(void)
385a995c792SAkinobu Mita {
386a995c792SAkinobu Mita 	int err = 0;
387a995c792SAkinobu Mita 	uint64_t tmp;
388a995c792SAkinobu Mita 	uint32_t i;
389a995c792SAkinobu Mita 
390a995c792SAkinobu Mita 	printk(KERN_INFO "\n");
391a995c792SAkinobu Mita 	printk(KERN_INFO "=================================================\n");
392a995c792SAkinobu Mita 
393a995c792SAkinobu Mita 	if (dev < 0) {
394a995c792SAkinobu Mita 		pr_info("Please specify a valid mtd-device via module parameter\n");
395a995c792SAkinobu Mita 		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
396a995c792SAkinobu Mita 		return -EINVAL;
397a995c792SAkinobu Mita 	}
398a995c792SAkinobu Mita 
399a995c792SAkinobu Mita 	pr_info("MTD device: %d\n", dev);
400a995c792SAkinobu Mita 
401a995c792SAkinobu Mita 	mtd = get_mtd_device(NULL, dev);
402a995c792SAkinobu Mita 	if (IS_ERR(mtd)) {
403a995c792SAkinobu Mita 		err = PTR_ERR(mtd);
404a995c792SAkinobu Mita 		pr_err("error: cannot get MTD device\n");
405a995c792SAkinobu Mita 		return err;
406a995c792SAkinobu Mita 	}
407a995c792SAkinobu Mita 
408a995c792SAkinobu Mita 	if (mtd->type != MTD_NANDFLASH) {
409a995c792SAkinobu Mita 		pr_info("this test requires NAND flash\n");
410a995c792SAkinobu Mita 		goto out;
411a995c792SAkinobu Mita 	}
412a995c792SAkinobu Mita 
413a995c792SAkinobu Mita 	tmp = mtd->size;
414a995c792SAkinobu Mita 	do_div(tmp, mtd->erasesize);
415a995c792SAkinobu Mita 	ebcnt = tmp;
416a995c792SAkinobu Mita 	pgcnt = mtd->erasesize / mtd->writesize;
417a995c792SAkinobu Mita 	pgsize = mtd->writesize;
418a995c792SAkinobu Mita 
419a995c792SAkinobu Mita 	pr_info("MTD device size %llu, eraseblock size %u, "
420a995c792SAkinobu Mita 	       "page size %u, count of eraseblocks %u, pages per "
421a995c792SAkinobu Mita 	       "eraseblock %u, OOB size %u\n",
422a995c792SAkinobu Mita 	       (unsigned long long)mtd->size, mtd->erasesize,
423a995c792SAkinobu Mita 	       pgsize, ebcnt, pgcnt, mtd->oobsize);
424a995c792SAkinobu Mita 
425a995c792SAkinobu Mita 	err = -ENOMEM;
426a995c792SAkinobu Mita 	bufsize = pgsize * 2;
427a995c792SAkinobu Mita 	writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
428a995c792SAkinobu Mita 	if (!writebuf)
429a995c792SAkinobu Mita 		goto out;
430a995c792SAkinobu Mita 	twopages = kmalloc(bufsize, GFP_KERNEL);
431a995c792SAkinobu Mita 	if (!twopages)
432a995c792SAkinobu Mita 		goto out;
433a995c792SAkinobu Mita 	boundary = kmalloc(bufsize, GFP_KERNEL);
434a995c792SAkinobu Mita 	if (!boundary)
435a995c792SAkinobu Mita 		goto out;
436a995c792SAkinobu Mita 
43766b28183SAkinobu Mita 	bbt = kzalloc(ebcnt, GFP_KERNEL);
43866b28183SAkinobu Mita 	if (!bbt)
43966b28183SAkinobu Mita 		goto out;
44066b28183SAkinobu Mita 	err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
441a995c792SAkinobu Mita 	if (err)
442a995c792SAkinobu Mita 		goto out;
443a995c792SAkinobu Mita 
444a995c792SAkinobu Mita 	/* Erase all eraseblocks */
445a995c792SAkinobu Mita 	pr_info("erasing whole device\n");
44666b28183SAkinobu Mita 	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
447a995c792SAkinobu Mita 	if (err)
448a995c792SAkinobu Mita 		goto out;
44966b28183SAkinobu Mita 	pr_info("erased %u eraseblocks\n", ebcnt);
450a995c792SAkinobu Mita 
451a995c792SAkinobu Mita 	/* Write all eraseblocks */
452a995c792SAkinobu Mita 	prandom_seed_state(&rnd_state, 1);
453a995c792SAkinobu Mita 	pr_info("writing whole device\n");
454a995c792SAkinobu Mita 	for (i = 0; i < ebcnt; ++i) {
455a995c792SAkinobu Mita 		if (bbt[i])
456a995c792SAkinobu Mita 			continue;
457a995c792SAkinobu Mita 		err = write_eraseblock(i);
458a995c792SAkinobu Mita 		if (err)
459a995c792SAkinobu Mita 			goto out;
460a995c792SAkinobu Mita 		if (i % 256 == 0)
461a995c792SAkinobu Mita 			pr_info("written up to eraseblock %u\n", i);
462a995c792SAkinobu Mita 		cond_resched();
463a995c792SAkinobu Mita 	}
464a995c792SAkinobu Mita 	pr_info("written %u eraseblocks\n", i);
465a995c792SAkinobu Mita 
466a995c792SAkinobu Mita 	/* Check all eraseblocks */
467a995c792SAkinobu Mita 	prandom_seed_state(&rnd_state, 1);
468a995c792SAkinobu Mita 	pr_info("verifying all eraseblocks\n");
469a995c792SAkinobu Mita 	for (i = 0; i < ebcnt; ++i) {
470a995c792SAkinobu Mita 		if (bbt[i])
471a995c792SAkinobu Mita 			continue;
472a995c792SAkinobu Mita 		err = verify_eraseblock(i);
473a995c792SAkinobu Mita 		if (err)
474a995c792SAkinobu Mita 			goto out;
475a995c792SAkinobu Mita 		if (i % 256 == 0)
476a995c792SAkinobu Mita 			pr_info("verified up to eraseblock %u\n", i);
477a995c792SAkinobu Mita 		cond_resched();
478a995c792SAkinobu Mita 	}
479a995c792SAkinobu Mita 	pr_info("verified %u eraseblocks\n", i);
480a995c792SAkinobu Mita 
481a995c792SAkinobu Mita 	err = crosstest();
482a995c792SAkinobu Mita 	if (err)
483a995c792SAkinobu Mita 		goto out;
484a995c792SAkinobu Mita 
485a995c792SAkinobu Mita 	err = erasecrosstest();
486a995c792SAkinobu Mita 	if (err)
487a995c792SAkinobu Mita 		goto out;
488a995c792SAkinobu Mita 
489a995c792SAkinobu Mita 	err = erasetest();
490a995c792SAkinobu Mita 	if (err)
491a995c792SAkinobu Mita 		goto out;
492a995c792SAkinobu Mita 
493a995c792SAkinobu Mita 	pr_info("finished with %d errors\n", errcnt);
494a995c792SAkinobu Mita out:
495a995c792SAkinobu Mita 
496a995c792SAkinobu Mita 	kfree(bbt);
497a995c792SAkinobu Mita 	kfree(boundary);
498a995c792SAkinobu Mita 	kfree(twopages);
499a995c792SAkinobu Mita 	kfree(writebuf);
500a995c792SAkinobu Mita 	put_mtd_device(mtd);
501a995c792SAkinobu Mita 	if (err)
502a995c792SAkinobu Mita 		pr_info("error %d occurred\n", err);
503a995c792SAkinobu Mita 	printk(KERN_INFO "=================================================\n");
504a995c792SAkinobu Mita 	return err;
505a995c792SAkinobu Mita }
506a995c792SAkinobu Mita module_init(mtd_pagetest_init);
507a995c792SAkinobu Mita 
508a995c792SAkinobu Mita static void __exit mtd_pagetest_exit(void)
509a995c792SAkinobu Mita {
510a995c792SAkinobu Mita 	return;
511a995c792SAkinobu Mita }
512a995c792SAkinobu Mita module_exit(mtd_pagetest_exit);
513a995c792SAkinobu Mita 
514a995c792SAkinobu Mita MODULE_DESCRIPTION("NAND page test");
515a995c792SAkinobu Mita MODULE_AUTHOR("Adrian Hunter");
516a995c792SAkinobu Mita MODULE_LICENSE("GPL");
517