xref: /openbmc/linux/drivers/mtd/tests/pagetest.c (revision a995c792)
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 
34a995c792SAkinobu Mita static int dev = -EINVAL;
35a995c792SAkinobu Mita module_param(dev, int, S_IRUGO);
36a995c792SAkinobu Mita MODULE_PARM_DESC(dev, "MTD device number to use");
37a995c792SAkinobu Mita 
38a995c792SAkinobu Mita static struct mtd_info *mtd;
39a995c792SAkinobu Mita static unsigned char *twopages;
40a995c792SAkinobu Mita static unsigned char *writebuf;
41a995c792SAkinobu Mita static unsigned char *boundary;
42a995c792SAkinobu Mita static unsigned char *bbt;
43a995c792SAkinobu Mita 
44a995c792SAkinobu Mita static int pgsize;
45a995c792SAkinobu Mita static int bufsize;
46a995c792SAkinobu Mita static int ebcnt;
47a995c792SAkinobu Mita static int pgcnt;
48a995c792SAkinobu Mita static int errcnt;
49a995c792SAkinobu Mita static struct rnd_state rnd_state;
50a995c792SAkinobu Mita 
51a995c792SAkinobu Mita static int erase_eraseblock(int ebnum)
52a995c792SAkinobu Mita {
53a995c792SAkinobu Mita 	int err;
54a995c792SAkinobu Mita 	struct erase_info ei;
55a995c792SAkinobu Mita 	loff_t addr = ebnum * mtd->erasesize;
56a995c792SAkinobu Mita 
57a995c792SAkinobu Mita 	memset(&ei, 0, sizeof(struct erase_info));
58a995c792SAkinobu Mita 	ei.mtd  = mtd;
59a995c792SAkinobu Mita 	ei.addr = addr;
60a995c792SAkinobu Mita 	ei.len  = mtd->erasesize;
61a995c792SAkinobu Mita 
62a995c792SAkinobu Mita 	err = mtd_erase(mtd, &ei);
63a995c792SAkinobu Mita 	if (err) {
64a995c792SAkinobu Mita 		pr_err("error %d while erasing EB %d\n", err, ebnum);
65a995c792SAkinobu Mita 		return err;
66a995c792SAkinobu Mita 	}
67a995c792SAkinobu Mita 
68a995c792SAkinobu Mita 	if (ei.state == MTD_ERASE_FAILED) {
69a995c792SAkinobu Mita 		pr_err("some erase error occurred at EB %d\n",
70a995c792SAkinobu Mita 		       ebnum);
71a995c792SAkinobu Mita 		return -EIO;
72a995c792SAkinobu Mita 	}
73a995c792SAkinobu Mita 
74a995c792SAkinobu Mita 	return 0;
75a995c792SAkinobu Mita }
76a995c792SAkinobu Mita 
77a995c792SAkinobu Mita static int write_eraseblock(int ebnum)
78a995c792SAkinobu Mita {
79a995c792SAkinobu Mita 	int err = 0;
80a995c792SAkinobu Mita 	size_t written;
81a995c792SAkinobu Mita 	loff_t addr = ebnum * mtd->erasesize;
82a995c792SAkinobu Mita 
83a995c792SAkinobu Mita 	prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
84a995c792SAkinobu Mita 	cond_resched();
85a995c792SAkinobu Mita 	err = mtd_write(mtd, addr, mtd->erasesize, &written, writebuf);
86a995c792SAkinobu Mita 	if (err || written != mtd->erasesize)
87a995c792SAkinobu Mita 		pr_err("error: write failed at %#llx\n",
88a995c792SAkinobu Mita 		       (long long)addr);
89a995c792SAkinobu Mita 
90a995c792SAkinobu Mita 	return err;
91a995c792SAkinobu Mita }
92a995c792SAkinobu Mita 
93a995c792SAkinobu Mita static int verify_eraseblock(int ebnum)
94a995c792SAkinobu Mita {
95a995c792SAkinobu Mita 	uint32_t j;
96a995c792SAkinobu Mita 	size_t read;
97a995c792SAkinobu Mita 	int err = 0, i;
98a995c792SAkinobu Mita 	loff_t addr0, addrn;
99a995c792SAkinobu Mita 	loff_t addr = ebnum * mtd->erasesize;
100a995c792SAkinobu Mita 
101a995c792SAkinobu Mita 	addr0 = 0;
102a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[i]; ++i)
103a995c792SAkinobu Mita 		addr0 += mtd->erasesize;
104a995c792SAkinobu Mita 
105a995c792SAkinobu Mita 	addrn = mtd->size;
106a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
107a995c792SAkinobu Mita 		addrn -= mtd->erasesize;
108a995c792SAkinobu Mita 
109a995c792SAkinobu Mita 	prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
110a995c792SAkinobu Mita 	for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) {
111a995c792SAkinobu Mita 		/* Do a read to set the internal dataRAMs to different data */
112a995c792SAkinobu Mita 		err = mtd_read(mtd, addr0, bufsize, &read, twopages);
113a995c792SAkinobu Mita 		if (mtd_is_bitflip(err))
114a995c792SAkinobu Mita 			err = 0;
115a995c792SAkinobu Mita 		if (err || read != bufsize) {
116a995c792SAkinobu Mita 			pr_err("error: read failed at %#llx\n",
117a995c792SAkinobu Mita 			       (long long)addr0);
118a995c792SAkinobu Mita 			return err;
119a995c792SAkinobu Mita 		}
120a995c792SAkinobu Mita 		err = mtd_read(mtd, addrn - bufsize, bufsize, &read, twopages);
121a995c792SAkinobu Mita 		if (mtd_is_bitflip(err))
122a995c792SAkinobu Mita 			err = 0;
123a995c792SAkinobu Mita 		if (err || read != bufsize) {
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);
129a995c792SAkinobu Mita 		err = mtd_read(mtd, addr, bufsize, &read, twopages);
130a995c792SAkinobu Mita 		if (mtd_is_bitflip(err))
131a995c792SAkinobu Mita 			err = 0;
132a995c792SAkinobu Mita 		if (err || read != bufsize) {
133a995c792SAkinobu Mita 			pr_err("error: read failed at %#llx\n",
134a995c792SAkinobu Mita 			       (long long)addr);
135a995c792SAkinobu Mita 			break;
136a995c792SAkinobu Mita 		}
137a995c792SAkinobu Mita 		if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) {
138a995c792SAkinobu Mita 			pr_err("error: verify failed at %#llx\n",
139a995c792SAkinobu Mita 			       (long long)addr);
140a995c792SAkinobu Mita 			errcnt += 1;
141a995c792SAkinobu Mita 		}
142a995c792SAkinobu Mita 	}
143a995c792SAkinobu Mita 	/* Check boundary between eraseblocks */
144a995c792SAkinobu Mita 	if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) {
145a995c792SAkinobu Mita 		struct rnd_state old_state = rnd_state;
146a995c792SAkinobu Mita 
147a995c792SAkinobu Mita 		/* Do a read to set the internal dataRAMs to different data */
148a995c792SAkinobu Mita 		err = mtd_read(mtd, addr0, bufsize, &read, twopages);
149a995c792SAkinobu Mita 		if (mtd_is_bitflip(err))
150a995c792SAkinobu Mita 			err = 0;
151a995c792SAkinobu Mita 		if (err || read != bufsize) {
152a995c792SAkinobu Mita 			pr_err("error: read failed at %#llx\n",
153a995c792SAkinobu Mita 			       (long long)addr0);
154a995c792SAkinobu Mita 			return err;
155a995c792SAkinobu Mita 		}
156a995c792SAkinobu Mita 		err = mtd_read(mtd, addrn - bufsize, bufsize, &read, twopages);
157a995c792SAkinobu Mita 		if (mtd_is_bitflip(err))
158a995c792SAkinobu Mita 			err = 0;
159a995c792SAkinobu Mita 		if (err || read != bufsize) {
160a995c792SAkinobu Mita 			pr_err("error: read failed at %#llx\n",
161a995c792SAkinobu Mita 			       (long long)(addrn - bufsize));
162a995c792SAkinobu Mita 			return err;
163a995c792SAkinobu Mita 		}
164a995c792SAkinobu Mita 		memset(twopages, 0, bufsize);
165a995c792SAkinobu Mita 		err = mtd_read(mtd, addr, bufsize, &read, twopages);
166a995c792SAkinobu Mita 		if (mtd_is_bitflip(err))
167a995c792SAkinobu Mita 			err = 0;
168a995c792SAkinobu Mita 		if (err || read != bufsize) {
169a995c792SAkinobu Mita 			pr_err("error: read failed at %#llx\n",
170a995c792SAkinobu Mita 			       (long long)addr);
171a995c792SAkinobu Mita 			return err;
172a995c792SAkinobu Mita 		}
173a995c792SAkinobu Mita 		memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize);
174a995c792SAkinobu Mita 		prandom_bytes_state(&rnd_state, boundary + pgsize, pgsize);
175a995c792SAkinobu Mita 		if (memcmp(twopages, boundary, bufsize)) {
176a995c792SAkinobu Mita 			pr_err("error: verify failed at %#llx\n",
177a995c792SAkinobu Mita 			       (long long)addr);
178a995c792SAkinobu Mita 			errcnt += 1;
179a995c792SAkinobu Mita 		}
180a995c792SAkinobu Mita 		rnd_state = old_state;
181a995c792SAkinobu Mita 	}
182a995c792SAkinobu Mita 	return err;
183a995c792SAkinobu Mita }
184a995c792SAkinobu Mita 
185a995c792SAkinobu Mita static int crosstest(void)
186a995c792SAkinobu Mita {
187a995c792SAkinobu Mita 	size_t read;
188a995c792SAkinobu Mita 	int err = 0, i;
189a995c792SAkinobu Mita 	loff_t addr, addr0, addrn;
190a995c792SAkinobu Mita 	unsigned char *pp1, *pp2, *pp3, *pp4;
191a995c792SAkinobu Mita 
192a995c792SAkinobu Mita 	pr_info("crosstest\n");
193a995c792SAkinobu Mita 	pp1 = kmalloc(pgsize * 4, GFP_KERNEL);
194a995c792SAkinobu Mita 	if (!pp1)
195a995c792SAkinobu Mita 		return -ENOMEM;
196a995c792SAkinobu Mita 	pp2 = pp1 + pgsize;
197a995c792SAkinobu Mita 	pp3 = pp2 + pgsize;
198a995c792SAkinobu Mita 	pp4 = pp3 + pgsize;
199a995c792SAkinobu Mita 	memset(pp1, 0, pgsize * 4);
200a995c792SAkinobu Mita 
201a995c792SAkinobu Mita 	addr0 = 0;
202a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[i]; ++i)
203a995c792SAkinobu Mita 		addr0 += mtd->erasesize;
204a995c792SAkinobu Mita 
205a995c792SAkinobu Mita 	addrn = mtd->size;
206a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
207a995c792SAkinobu Mita 		addrn -= mtd->erasesize;
208a995c792SAkinobu Mita 
209a995c792SAkinobu Mita 	/* Read 2nd-to-last page to pp1 */
210a995c792SAkinobu Mita 	addr = addrn - pgsize - pgsize;
211a995c792SAkinobu Mita 	err = mtd_read(mtd, addr, pgsize, &read, pp1);
212a995c792SAkinobu Mita 	if (mtd_is_bitflip(err))
213a995c792SAkinobu Mita 		err = 0;
214a995c792SAkinobu Mita 	if (err || read != pgsize) {
215a995c792SAkinobu Mita 		pr_err("error: read failed at %#llx\n",
216a995c792SAkinobu Mita 		       (long long)addr);
217a995c792SAkinobu Mita 		kfree(pp1);
218a995c792SAkinobu Mita 		return err;
219a995c792SAkinobu Mita 	}
220a995c792SAkinobu Mita 
221a995c792SAkinobu Mita 	/* Read 3rd-to-last page to pp1 */
222a995c792SAkinobu Mita 	addr = addrn - pgsize - pgsize - pgsize;
223a995c792SAkinobu Mita 	err = mtd_read(mtd, addr, pgsize, &read, pp1);
224a995c792SAkinobu Mita 	if (mtd_is_bitflip(err))
225a995c792SAkinobu Mita 		err = 0;
226a995c792SAkinobu Mita 	if (err || read != pgsize) {
227a995c792SAkinobu Mita 		pr_err("error: read failed at %#llx\n",
228a995c792SAkinobu Mita 		       (long long)addr);
229a995c792SAkinobu Mita 		kfree(pp1);
230a995c792SAkinobu Mita 		return err;
231a995c792SAkinobu Mita 	}
232a995c792SAkinobu Mita 
233a995c792SAkinobu Mita 	/* Read first page to pp2 */
234a995c792SAkinobu Mita 	addr = addr0;
235a995c792SAkinobu Mita 	pr_info("reading page at %#llx\n", (long long)addr);
236a995c792SAkinobu Mita 	err = mtd_read(mtd, addr, pgsize, &read, pp2);
237a995c792SAkinobu Mita 	if (mtd_is_bitflip(err))
238a995c792SAkinobu Mita 		err = 0;
239a995c792SAkinobu Mita 	if (err || read != pgsize) {
240a995c792SAkinobu Mita 		pr_err("error: read failed at %#llx\n",
241a995c792SAkinobu Mita 		       (long long)addr);
242a995c792SAkinobu Mita 		kfree(pp1);
243a995c792SAkinobu Mita 		return err;
244a995c792SAkinobu Mita 	}
245a995c792SAkinobu Mita 
246a995c792SAkinobu Mita 	/* Read last page to pp3 */
247a995c792SAkinobu Mita 	addr = addrn - pgsize;
248a995c792SAkinobu Mita 	pr_info("reading page at %#llx\n", (long long)addr);
249a995c792SAkinobu Mita 	err = mtd_read(mtd, addr, pgsize, &read, pp3);
250a995c792SAkinobu Mita 	if (mtd_is_bitflip(err))
251a995c792SAkinobu Mita 		err = 0;
252a995c792SAkinobu Mita 	if (err || read != pgsize) {
253a995c792SAkinobu Mita 		pr_err("error: read failed at %#llx\n",
254a995c792SAkinobu Mita 		       (long long)addr);
255a995c792SAkinobu Mita 		kfree(pp1);
256a995c792SAkinobu Mita 		return err;
257a995c792SAkinobu Mita 	}
258a995c792SAkinobu Mita 
259a995c792SAkinobu Mita 	/* Read first page again to pp4 */
260a995c792SAkinobu Mita 	addr = addr0;
261a995c792SAkinobu Mita 	pr_info("reading page at %#llx\n", (long long)addr);
262a995c792SAkinobu Mita 	err = mtd_read(mtd, addr, pgsize, &read, pp4);
263a995c792SAkinobu Mita 	if (mtd_is_bitflip(err))
264a995c792SAkinobu Mita 		err = 0;
265a995c792SAkinobu Mita 	if (err || read != pgsize) {
266a995c792SAkinobu Mita 		pr_err("error: read failed at %#llx\n",
267a995c792SAkinobu Mita 		       (long long)addr);
268a995c792SAkinobu Mita 		kfree(pp1);
269a995c792SAkinobu Mita 		return err;
270a995c792SAkinobu Mita 	}
271a995c792SAkinobu Mita 
272a995c792SAkinobu Mita 	/* pp2 and pp4 should be the same */
273a995c792SAkinobu Mita 	pr_info("verifying pages read at %#llx match\n",
274a995c792SAkinobu Mita 	       (long long)addr0);
275a995c792SAkinobu Mita 	if (memcmp(pp2, pp4, pgsize)) {
276a995c792SAkinobu Mita 		pr_err("verify failed!\n");
277a995c792SAkinobu Mita 		errcnt += 1;
278a995c792SAkinobu Mita 	} else if (!err)
279a995c792SAkinobu Mita 		pr_info("crosstest ok\n");
280a995c792SAkinobu Mita 	kfree(pp1);
281a995c792SAkinobu Mita 	return err;
282a995c792SAkinobu Mita }
283a995c792SAkinobu Mita 
284a995c792SAkinobu Mita static int erasecrosstest(void)
285a995c792SAkinobu Mita {
286a995c792SAkinobu Mita 	size_t read, written;
287a995c792SAkinobu Mita 	int err = 0, i, ebnum, ebnum2;
288a995c792SAkinobu Mita 	loff_t addr0;
289a995c792SAkinobu Mita 	char *readbuf = twopages;
290a995c792SAkinobu Mita 
291a995c792SAkinobu Mita 	pr_info("erasecrosstest\n");
292a995c792SAkinobu Mita 
293a995c792SAkinobu Mita 	ebnum = 0;
294a995c792SAkinobu Mita 	addr0 = 0;
295a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[i]; ++i) {
296a995c792SAkinobu Mita 		addr0 += mtd->erasesize;
297a995c792SAkinobu Mita 		ebnum += 1;
298a995c792SAkinobu Mita 	}
299a995c792SAkinobu Mita 
300a995c792SAkinobu Mita 	ebnum2 = ebcnt - 1;
301a995c792SAkinobu Mita 	while (ebnum2 && bbt[ebnum2])
302a995c792SAkinobu Mita 		ebnum2 -= 1;
303a995c792SAkinobu Mita 
304a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum);
305a995c792SAkinobu Mita 	err = erase_eraseblock(ebnum);
306a995c792SAkinobu Mita 	if (err)
307a995c792SAkinobu Mita 		return err;
308a995c792SAkinobu Mita 
309a995c792SAkinobu Mita 	pr_info("writing 1st page of block %d\n", ebnum);
310a995c792SAkinobu Mita 	prandom_bytes_state(&rnd_state, writebuf, pgsize);
311a995c792SAkinobu Mita 	strcpy(writebuf, "There is no data like this!");
312a995c792SAkinobu Mita 	err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
313a995c792SAkinobu Mita 	if (err || written != pgsize) {
314a995c792SAkinobu Mita 		pr_info("error: write failed at %#llx\n",
315a995c792SAkinobu Mita 		       (long long)addr0);
316a995c792SAkinobu Mita 		return err ? err : -1;
317a995c792SAkinobu Mita 	}
318a995c792SAkinobu Mita 
319a995c792SAkinobu Mita 	pr_info("reading 1st page of block %d\n", ebnum);
320a995c792SAkinobu Mita 	memset(readbuf, 0, pgsize);
321a995c792SAkinobu Mita 	err = mtd_read(mtd, addr0, pgsize, &read, readbuf);
322a995c792SAkinobu Mita 	if (mtd_is_bitflip(err))
323a995c792SAkinobu Mita 		err = 0;
324a995c792SAkinobu Mita 	if (err || read != pgsize) {
325a995c792SAkinobu Mita 		pr_err("error: read failed at %#llx\n",
326a995c792SAkinobu Mita 		       (long long)addr0);
327a995c792SAkinobu Mita 		return err ? err : -1;
328a995c792SAkinobu Mita 	}
329a995c792SAkinobu Mita 
330a995c792SAkinobu Mita 	pr_info("verifying 1st page of block %d\n", ebnum);
331a995c792SAkinobu Mita 	if (memcmp(writebuf, readbuf, pgsize)) {
332a995c792SAkinobu Mita 		pr_err("verify failed!\n");
333a995c792SAkinobu Mita 		errcnt += 1;
334a995c792SAkinobu Mita 		return -1;
335a995c792SAkinobu Mita 	}
336a995c792SAkinobu Mita 
337a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum);
338a995c792SAkinobu Mita 	err = erase_eraseblock(ebnum);
339a995c792SAkinobu Mita 	if (err)
340a995c792SAkinobu Mita 		return err;
341a995c792SAkinobu Mita 
342a995c792SAkinobu Mita 	pr_info("writing 1st page of block %d\n", ebnum);
343a995c792SAkinobu Mita 	prandom_bytes_state(&rnd_state, writebuf, pgsize);
344a995c792SAkinobu Mita 	strcpy(writebuf, "There is no data like this!");
345a995c792SAkinobu Mita 	err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
346a995c792SAkinobu Mita 	if (err || written != pgsize) {
347a995c792SAkinobu Mita 		pr_err("error: write failed at %#llx\n",
348a995c792SAkinobu Mita 		       (long long)addr0);
349a995c792SAkinobu Mita 		return err ? err : -1;
350a995c792SAkinobu Mita 	}
351a995c792SAkinobu Mita 
352a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum2);
353a995c792SAkinobu Mita 	err = erase_eraseblock(ebnum2);
354a995c792SAkinobu Mita 	if (err)
355a995c792SAkinobu Mita 		return err;
356a995c792SAkinobu Mita 
357a995c792SAkinobu Mita 	pr_info("reading 1st page of block %d\n", ebnum);
358a995c792SAkinobu Mita 	memset(readbuf, 0, pgsize);
359a995c792SAkinobu Mita 	err = mtd_read(mtd, addr0, pgsize, &read, readbuf);
360a995c792SAkinobu Mita 	if (mtd_is_bitflip(err))
361a995c792SAkinobu Mita 		err = 0;
362a995c792SAkinobu Mita 	if (err || read != pgsize) {
363a995c792SAkinobu Mita 		pr_err("error: read failed at %#llx\n",
364a995c792SAkinobu Mita 		       (long long)addr0);
365a995c792SAkinobu Mita 		return err ? err : -1;
366a995c792SAkinobu Mita 	}
367a995c792SAkinobu Mita 
368a995c792SAkinobu Mita 	pr_info("verifying 1st page of block %d\n", ebnum);
369a995c792SAkinobu Mita 	if (memcmp(writebuf, readbuf, pgsize)) {
370a995c792SAkinobu Mita 		pr_err("verify failed!\n");
371a995c792SAkinobu Mita 		errcnt += 1;
372a995c792SAkinobu Mita 		return -1;
373a995c792SAkinobu Mita 	}
374a995c792SAkinobu Mita 
375a995c792SAkinobu Mita 	if (!err)
376a995c792SAkinobu Mita 		pr_info("erasecrosstest ok\n");
377a995c792SAkinobu Mita 	return err;
378a995c792SAkinobu Mita }
379a995c792SAkinobu Mita 
380a995c792SAkinobu Mita static int erasetest(void)
381a995c792SAkinobu Mita {
382a995c792SAkinobu Mita 	size_t read, written;
383a995c792SAkinobu Mita 	int err = 0, i, ebnum, ok = 1;
384a995c792SAkinobu Mita 	loff_t addr0;
385a995c792SAkinobu Mita 
386a995c792SAkinobu Mita 	pr_info("erasetest\n");
387a995c792SAkinobu Mita 
388a995c792SAkinobu Mita 	ebnum = 0;
389a995c792SAkinobu Mita 	addr0 = 0;
390a995c792SAkinobu Mita 	for (i = 0; i < ebcnt && bbt[i]; ++i) {
391a995c792SAkinobu Mita 		addr0 += mtd->erasesize;
392a995c792SAkinobu Mita 		ebnum += 1;
393a995c792SAkinobu Mita 	}
394a995c792SAkinobu Mita 
395a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum);
396a995c792SAkinobu Mita 	err = erase_eraseblock(ebnum);
397a995c792SAkinobu Mita 	if (err)
398a995c792SAkinobu Mita 		return err;
399a995c792SAkinobu Mita 
400a995c792SAkinobu Mita 	pr_info("writing 1st page of block %d\n", ebnum);
401a995c792SAkinobu Mita 	prandom_bytes_state(&rnd_state, writebuf, pgsize);
402a995c792SAkinobu Mita 	err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
403a995c792SAkinobu Mita 	if (err || written != pgsize) {
404a995c792SAkinobu Mita 		pr_err("error: write failed at %#llx\n",
405a995c792SAkinobu Mita 		       (long long)addr0);
406a995c792SAkinobu Mita 		return err ? err : -1;
407a995c792SAkinobu Mita 	}
408a995c792SAkinobu Mita 
409a995c792SAkinobu Mita 	pr_info("erasing block %d\n", ebnum);
410a995c792SAkinobu Mita 	err = erase_eraseblock(ebnum);
411a995c792SAkinobu Mita 	if (err)
412a995c792SAkinobu Mita 		return err;
413a995c792SAkinobu Mita 
414a995c792SAkinobu Mita 	pr_info("reading 1st page of block %d\n", ebnum);
415a995c792SAkinobu Mita 	err = mtd_read(mtd, addr0, pgsize, &read, twopages);
416a995c792SAkinobu Mita 	if (mtd_is_bitflip(err))
417a995c792SAkinobu Mita 		err = 0;
418a995c792SAkinobu Mita 	if (err || read != pgsize) {
419a995c792SAkinobu Mita 		pr_err("error: read failed at %#llx\n",
420a995c792SAkinobu Mita 		       (long long)addr0);
421a995c792SAkinobu Mita 		return err ? err : -1;
422a995c792SAkinobu Mita 	}
423a995c792SAkinobu Mita 
424a995c792SAkinobu Mita 	pr_info("verifying 1st page of block %d is all 0xff\n",
425a995c792SAkinobu Mita 	       ebnum);
426a995c792SAkinobu Mita 	for (i = 0; i < pgsize; ++i)
427a995c792SAkinobu Mita 		if (twopages[i] != 0xff) {
428a995c792SAkinobu Mita 			pr_err("verifying all 0xff failed at %d\n",
429a995c792SAkinobu Mita 			       i);
430a995c792SAkinobu Mita 			errcnt += 1;
431a995c792SAkinobu Mita 			ok = 0;
432a995c792SAkinobu Mita 			break;
433a995c792SAkinobu Mita 		}
434a995c792SAkinobu Mita 
435a995c792SAkinobu Mita 	if (ok && !err)
436a995c792SAkinobu Mita 		pr_info("erasetest ok\n");
437a995c792SAkinobu Mita 
438a995c792SAkinobu Mita 	return err;
439a995c792SAkinobu Mita }
440a995c792SAkinobu Mita 
441a995c792SAkinobu Mita static int is_block_bad(int ebnum)
442a995c792SAkinobu Mita {
443a995c792SAkinobu Mita 	loff_t addr = ebnum * mtd->erasesize;
444a995c792SAkinobu Mita 	int ret;
445a995c792SAkinobu Mita 
446a995c792SAkinobu Mita 	ret = mtd_block_isbad(mtd, addr);
447a995c792SAkinobu Mita 	if (ret)
448a995c792SAkinobu Mita 		pr_info("block %d is bad\n", ebnum);
449a995c792SAkinobu Mita 	return ret;
450a995c792SAkinobu Mita }
451a995c792SAkinobu Mita 
452a995c792SAkinobu Mita static int scan_for_bad_eraseblocks(void)
453a995c792SAkinobu Mita {
454a995c792SAkinobu Mita 	int i, bad = 0;
455a995c792SAkinobu Mita 
456a995c792SAkinobu Mita 	bbt = kzalloc(ebcnt, GFP_KERNEL);
457a995c792SAkinobu Mita 	if (!bbt)
458a995c792SAkinobu Mita 		return -ENOMEM;
459a995c792SAkinobu Mita 
460a995c792SAkinobu Mita 	pr_info("scanning for bad eraseblocks\n");
461a995c792SAkinobu Mita 	for (i = 0; i < ebcnt; ++i) {
462a995c792SAkinobu Mita 		bbt[i] = is_block_bad(i) ? 1 : 0;
463a995c792SAkinobu Mita 		if (bbt[i])
464a995c792SAkinobu Mita 			bad += 1;
465a995c792SAkinobu Mita 		cond_resched();
466a995c792SAkinobu Mita 	}
467a995c792SAkinobu Mita 	pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
468a995c792SAkinobu Mita 	return 0;
469a995c792SAkinobu Mita }
470a995c792SAkinobu Mita 
471a995c792SAkinobu Mita static int __init mtd_pagetest_init(void)
472a995c792SAkinobu Mita {
473a995c792SAkinobu Mita 	int err = 0;
474a995c792SAkinobu Mita 	uint64_t tmp;
475a995c792SAkinobu Mita 	uint32_t i;
476a995c792SAkinobu Mita 
477a995c792SAkinobu Mita 	printk(KERN_INFO "\n");
478a995c792SAkinobu Mita 	printk(KERN_INFO "=================================================\n");
479a995c792SAkinobu Mita 
480a995c792SAkinobu Mita 	if (dev < 0) {
481a995c792SAkinobu Mita 		pr_info("Please specify a valid mtd-device via module parameter\n");
482a995c792SAkinobu Mita 		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
483a995c792SAkinobu Mita 		return -EINVAL;
484a995c792SAkinobu Mita 	}
485a995c792SAkinobu Mita 
486a995c792SAkinobu Mita 	pr_info("MTD device: %d\n", dev);
487a995c792SAkinobu Mita 
488a995c792SAkinobu Mita 	mtd = get_mtd_device(NULL, dev);
489a995c792SAkinobu Mita 	if (IS_ERR(mtd)) {
490a995c792SAkinobu Mita 		err = PTR_ERR(mtd);
491a995c792SAkinobu Mita 		pr_err("error: cannot get MTD device\n");
492a995c792SAkinobu Mita 		return err;
493a995c792SAkinobu Mita 	}
494a995c792SAkinobu Mita 
495a995c792SAkinobu Mita 	if (mtd->type != MTD_NANDFLASH) {
496a995c792SAkinobu Mita 		pr_info("this test requires NAND flash\n");
497a995c792SAkinobu Mita 		goto out;
498a995c792SAkinobu Mita 	}
499a995c792SAkinobu Mita 
500a995c792SAkinobu Mita 	tmp = mtd->size;
501a995c792SAkinobu Mita 	do_div(tmp, mtd->erasesize);
502a995c792SAkinobu Mita 	ebcnt = tmp;
503a995c792SAkinobu Mita 	pgcnt = mtd->erasesize / mtd->writesize;
504a995c792SAkinobu Mita 	pgsize = mtd->writesize;
505a995c792SAkinobu Mita 
506a995c792SAkinobu Mita 	pr_info("MTD device size %llu, eraseblock size %u, "
507a995c792SAkinobu Mita 	       "page size %u, count of eraseblocks %u, pages per "
508a995c792SAkinobu Mita 	       "eraseblock %u, OOB size %u\n",
509a995c792SAkinobu Mita 	       (unsigned long long)mtd->size, mtd->erasesize,
510a995c792SAkinobu Mita 	       pgsize, ebcnt, pgcnt, mtd->oobsize);
511a995c792SAkinobu Mita 
512a995c792SAkinobu Mita 	err = -ENOMEM;
513a995c792SAkinobu Mita 	bufsize = pgsize * 2;
514a995c792SAkinobu Mita 	writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
515a995c792SAkinobu Mita 	if (!writebuf)
516a995c792SAkinobu Mita 		goto out;
517a995c792SAkinobu Mita 	twopages = kmalloc(bufsize, GFP_KERNEL);
518a995c792SAkinobu Mita 	if (!twopages)
519a995c792SAkinobu Mita 		goto out;
520a995c792SAkinobu Mita 	boundary = kmalloc(bufsize, GFP_KERNEL);
521a995c792SAkinobu Mita 	if (!boundary)
522a995c792SAkinobu Mita 		goto out;
523a995c792SAkinobu Mita 
524a995c792SAkinobu Mita 	err = scan_for_bad_eraseblocks();
525a995c792SAkinobu Mita 	if (err)
526a995c792SAkinobu Mita 		goto out;
527a995c792SAkinobu Mita 
528a995c792SAkinobu Mita 	/* Erase all eraseblocks */
529a995c792SAkinobu Mita 	pr_info("erasing whole device\n");
530a995c792SAkinobu Mita 	for (i = 0; i < ebcnt; ++i) {
531a995c792SAkinobu Mita 		if (bbt[i])
532a995c792SAkinobu Mita 			continue;
533a995c792SAkinobu Mita 		err = erase_eraseblock(i);
534a995c792SAkinobu Mita 		if (err)
535a995c792SAkinobu Mita 			goto out;
536a995c792SAkinobu Mita 		cond_resched();
537a995c792SAkinobu Mita 	}
538a995c792SAkinobu Mita 	pr_info("erased %u eraseblocks\n", i);
539a995c792SAkinobu Mita 
540a995c792SAkinobu Mita 	/* Write all eraseblocks */
541a995c792SAkinobu Mita 	prandom_seed_state(&rnd_state, 1);
542a995c792SAkinobu Mita 	pr_info("writing whole device\n");
543a995c792SAkinobu Mita 	for (i = 0; i < ebcnt; ++i) {
544a995c792SAkinobu Mita 		if (bbt[i])
545a995c792SAkinobu Mita 			continue;
546a995c792SAkinobu Mita 		err = write_eraseblock(i);
547a995c792SAkinobu Mita 		if (err)
548a995c792SAkinobu Mita 			goto out;
549a995c792SAkinobu Mita 		if (i % 256 == 0)
550a995c792SAkinobu Mita 			pr_info("written up to eraseblock %u\n", i);
551a995c792SAkinobu Mita 		cond_resched();
552a995c792SAkinobu Mita 	}
553a995c792SAkinobu Mita 	pr_info("written %u eraseblocks\n", i);
554a995c792SAkinobu Mita 
555a995c792SAkinobu Mita 	/* Check all eraseblocks */
556a995c792SAkinobu Mita 	prandom_seed_state(&rnd_state, 1);
557a995c792SAkinobu Mita 	pr_info("verifying all eraseblocks\n");
558a995c792SAkinobu Mita 	for (i = 0; i < ebcnt; ++i) {
559a995c792SAkinobu Mita 		if (bbt[i])
560a995c792SAkinobu Mita 			continue;
561a995c792SAkinobu Mita 		err = verify_eraseblock(i);
562a995c792SAkinobu Mita 		if (err)
563a995c792SAkinobu Mita 			goto out;
564a995c792SAkinobu Mita 		if (i % 256 == 0)
565a995c792SAkinobu Mita 			pr_info("verified up to eraseblock %u\n", i);
566a995c792SAkinobu Mita 		cond_resched();
567a995c792SAkinobu Mita 	}
568a995c792SAkinobu Mita 	pr_info("verified %u eraseblocks\n", i);
569a995c792SAkinobu Mita 
570a995c792SAkinobu Mita 	err = crosstest();
571a995c792SAkinobu Mita 	if (err)
572a995c792SAkinobu Mita 		goto out;
573a995c792SAkinobu Mita 
574a995c792SAkinobu Mita 	err = erasecrosstest();
575a995c792SAkinobu Mita 	if (err)
576a995c792SAkinobu Mita 		goto out;
577a995c792SAkinobu Mita 
578a995c792SAkinobu Mita 	err = erasetest();
579a995c792SAkinobu Mita 	if (err)
580a995c792SAkinobu Mita 		goto out;
581a995c792SAkinobu Mita 
582a995c792SAkinobu Mita 	pr_info("finished with %d errors\n", errcnt);
583a995c792SAkinobu Mita out:
584a995c792SAkinobu Mita 
585a995c792SAkinobu Mita 	kfree(bbt);
586a995c792SAkinobu Mita 	kfree(boundary);
587a995c792SAkinobu Mita 	kfree(twopages);
588a995c792SAkinobu Mita 	kfree(writebuf);
589a995c792SAkinobu Mita 	put_mtd_device(mtd);
590a995c792SAkinobu Mita 	if (err)
591a995c792SAkinobu Mita 		pr_info("error %d occurred\n", err);
592a995c792SAkinobu Mita 	printk(KERN_INFO "=================================================\n");
593a995c792SAkinobu Mita 	return err;
594a995c792SAkinobu Mita }
595a995c792SAkinobu Mita module_init(mtd_pagetest_init);
596a995c792SAkinobu Mita 
597a995c792SAkinobu Mita static void __exit mtd_pagetest_exit(void)
598a995c792SAkinobu Mita {
599a995c792SAkinobu Mita 	return;
600a995c792SAkinobu Mita }
601a995c792SAkinobu Mita module_exit(mtd_pagetest_exit);
602a995c792SAkinobu Mita 
603a995c792SAkinobu Mita MODULE_DESCRIPTION("NAND page test");
604a995c792SAkinobu Mita MODULE_AUTHOR("Adrian Hunter");
605a995c792SAkinobu Mita MODULE_LICENSE("GPL");
606