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