2 * Copyright (C) 2006-2008 Nokia Corporation
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.
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
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.
17 * Test page read and write on MTD device.
19 * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
22 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
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>
36 static int dev = -EINVAL;
37 module_param(dev, int, S_IRUGO);
38 MODULE_PARM_DESC(dev, "MTD device number to use");
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;
51 static struct rnd_state rnd_state;
53 static int write_eraseblock(int ebnum)
56 loff_t addr = ebnum * mtd->erasesize;
58 prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
60 err = mtdtest_write(mtd, addr, mtd->erasesize, writebuf);
62 pr_err("error: write failed at %#llx\n",
68 static int verify_eraseblock(int ebnum)
73 loff_t addr = ebnum * mtd->erasesize;
76 for (i = 0; i < ebcnt && bbt[i]; ++i)
77 addr0 += mtd->erasesize;
80 for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
81 addrn -= mtd->erasesize;
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);
88 pr_err("error: read failed at %#llx\n",
92 err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages);
94 pr_err("error: read failed at %#llx\n",
95 (long long)(addrn - bufsize));
98 memset(twopages, 0, bufsize);
99 err = mtdtest_read(mtd, addr, bufsize, twopages);
101 pr_err("error: read failed at %#llx\n",
105 if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) {
106 pr_err("error: verify failed at %#llx\n",
111 /* Check boundary between eraseblocks */
112 if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) {
113 struct rnd_state old_state = rnd_state;
115 /* Do a read to set the internal dataRAMs to different data */
116 err = mtdtest_read(mtd, addr0, bufsize, twopages);
118 pr_err("error: read failed at %#llx\n",
122 err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages);
124 pr_err("error: read failed at %#llx\n",
125 (long long)(addrn - bufsize));
128 memset(twopages, 0, bufsize);
129 err = mtdtest_read(mtd, addr, bufsize, twopages);
131 pr_err("error: read failed at %#llx\n",
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",
142 rnd_state = old_state;
147 static int crosstest(void)
150 loff_t addr, addr0, addrn;
151 unsigned char *pp1, *pp2, *pp3, *pp4;
153 pr_info("crosstest\n");
154 pp1 = kmalloc(pgsize * 4, GFP_KERNEL);
160 memset(pp1, 0, pgsize * 4);
163 for (i = 0; i < ebcnt && bbt[i]; ++i)
164 addr0 += mtd->erasesize;
167 for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
168 addrn -= mtd->erasesize;
170 /* Read 2nd-to-last page to pp1 */
171 addr = addrn - pgsize - pgsize;
172 err = mtdtest_read(mtd, addr, pgsize, pp1);
174 pr_err("error: read failed at %#llx\n",
180 /* Read 3rd-to-last page to pp1 */
181 addr = addrn - pgsize - pgsize - pgsize;
182 err = mtdtest_read(mtd, addr, pgsize, pp1);
184 pr_err("error: read failed at %#llx\n",
190 /* Read first page to pp2 */
192 pr_info("reading page at %#llx\n", (long long)addr);
193 err = mtdtest_read(mtd, addr, pgsize, pp2);
195 pr_err("error: read failed at %#llx\n",
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);
206 pr_err("error: read failed at %#llx\n",
212 /* Read first page again to pp4 */
214 pr_info("reading page at %#llx\n", (long long)addr);
215 err = mtdtest_read(mtd, addr, pgsize, pp4);
217 pr_err("error: read failed at %#llx\n",
223 /* pp2 and pp4 should be the same */
224 pr_info("verifying pages read at %#llx match\n",
226 if (memcmp(pp2, pp4, pgsize)) {
227 pr_err("verify failed!\n");
230 pr_info("crosstest ok\n");
235 static int erasecrosstest(void)
237 int err = 0, i, ebnum, ebnum2;
239 char *readbuf = twopages;
241 pr_info("erasecrosstest\n");
245 for (i = 0; i < ebcnt && bbt[i]; ++i) {
246 addr0 += mtd->erasesize;
251 while (ebnum2 && bbt[ebnum2])
254 pr_info("erasing block %d\n", ebnum);
255 err = mtdtest_erase_eraseblock(mtd, ebnum);
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);
264 pr_info("error: write failed at %#llx\n",
269 pr_info("reading 1st page of block %d\n", ebnum);
270 memset(readbuf, 0, pgsize);
271 err = mtdtest_read(mtd, addr0, pgsize, readbuf);
273 pr_err("error: read failed at %#llx\n",
278 pr_info("verifying 1st page of block %d\n", ebnum);
279 if (memcmp(writebuf, readbuf, pgsize)) {
280 pr_err("verify failed!\n");
285 pr_info("erasing block %d\n", ebnum);
286 err = mtdtest_erase_eraseblock(mtd, ebnum);
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);
295 pr_err("error: write failed at %#llx\n",
300 pr_info("erasing block %d\n", ebnum2);
301 err = mtdtest_erase_eraseblock(mtd, ebnum2);
305 pr_info("reading 1st page of block %d\n", ebnum);
306 memset(readbuf, 0, pgsize);
307 err = mtdtest_read(mtd, addr0, pgsize, readbuf);
309 pr_err("error: read failed at %#llx\n",
314 pr_info("verifying 1st page of block %d\n", ebnum);
315 if (memcmp(writebuf, readbuf, pgsize)) {
316 pr_err("verify failed!\n");
322 pr_info("erasecrosstest ok\n");
326 static int erasetest(void)
328 int err = 0, i, ebnum, ok = 1;
331 pr_info("erasetest\n");
335 for (i = 0; i < ebcnt && bbt[i]; ++i) {
336 addr0 += mtd->erasesize;
340 pr_info("erasing block %d\n", ebnum);
341 err = mtdtest_erase_eraseblock(mtd, ebnum);
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);
349 pr_err("error: write failed at %#llx\n",
354 pr_info("erasing block %d\n", ebnum);
355 err = mtdtest_erase_eraseblock(mtd, ebnum);
359 pr_info("reading 1st page of block %d\n", ebnum);
360 err = mtdtest_read(mtd, addr0, pgsize, twopages);
362 pr_err("error: read failed at %#llx\n",
367 pr_info("verifying 1st page of block %d is all 0xff\n",
369 for (i = 0; i < pgsize; ++i)
370 if (twopages[i] != 0xff) {
371 pr_err("verifying all 0xff failed at %d\n",
379 pr_info("erasetest ok\n");
384 static int __init mtd_pagetest_init(void)
390 printk(KERN_INFO "\n");
391 printk(KERN_INFO "=================================================\n");
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");
399 pr_info("MTD device: %d\n", dev);
401 mtd = get_mtd_device(NULL, dev);
404 pr_err("error: cannot get MTD device\n");
408 if (mtd->type != MTD_NANDFLASH) {
409 pr_info("this test requires NAND flash\n");
414 do_div(tmp, mtd->erasesize);
416 pgcnt = mtd->erasesize / mtd->writesize;
417 pgsize = mtd->writesize;
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);
426 bufsize = pgsize * 2;
427 writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
430 twopages = kmalloc(bufsize, GFP_KERNEL);
433 boundary = kmalloc(bufsize, GFP_KERNEL);
437 bbt = kzalloc(ebcnt, GFP_KERNEL);
440 err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
444 /* Erase all eraseblocks */
445 pr_info("erasing whole device\n");
446 err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
449 pr_info("erased %u eraseblocks\n", ebcnt);
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) {
457 err = write_eraseblock(i);
461 pr_info("written up to eraseblock %u\n", i);
464 pr_info("written %u eraseblocks\n", i);
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) {
472 err = verify_eraseblock(i);
476 pr_info("verified up to eraseblock %u\n", i);
479 pr_info("verified %u eraseblocks\n", i);
485 err = erasecrosstest();
493 pr_info("finished with %d errors\n", errcnt);
502 pr_info("error %d occurred\n", err);
503 printk(KERN_INFO "=================================================\n");
506 module_init(mtd_pagetest_init);
508 static void __exit mtd_pagetest_exit(void)
512 module_exit(mtd_pagetest_exit);
514 MODULE_DESCRIPTION("NAND page test");
515 MODULE_AUTHOR("Adrian Hunter");
516 MODULE_LICENSE("GPL");