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