2 * Copyright (C) 2006-2007 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 sub-page read and write on MTD device.
18 * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
22 #include <linux/init.h>
23 #include <linux/module.h>
24 #include <linux/moduleparam.h>
25 #include <linux/err.h>
26 #include <linux/mtd/mtd.h>
27 #include <linux/slab.h>
28 #include <linux/sched.h>
30 #define PRINT_PREF KERN_INFO "mtd_subpagetest: "
32 static int dev = -EINVAL;
33 module_param(dev, int, S_IRUGO);
34 MODULE_PARM_DESC(dev, "MTD device number to use");
36 static struct mtd_info *mtd;
37 static unsigned char *writebuf;
38 static unsigned char *readbuf;
39 static unsigned char *bbt;
46 static unsigned long next = 1;
48 static inline unsigned int simple_rand(void)
50 next = next * 1103515245 + 12345;
51 return (unsigned int)((next / 65536) % 32768);
54 static inline void simple_srand(unsigned long seed)
59 static void set_random_data(unsigned char *buf, size_t len)
63 for (i = 0; i < len; ++i)
64 buf[i] = simple_rand();
67 static inline void clear_data(unsigned char *buf, size_t len)
72 static int erase_eraseblock(int ebnum)
76 loff_t addr = ebnum * mtd->erasesize;
78 memset(&ei, 0, sizeof(struct erase_info));
81 ei.len = mtd->erasesize;
83 err = mtd_erase(mtd, &ei);
85 printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
89 if (ei.state == MTD_ERASE_FAILED) {
90 printk(PRINT_PREF "some erase error occurred at EB %d\n",
98 static int erase_whole_device(void)
103 printk(PRINT_PREF "erasing whole device\n");
104 for (i = 0; i < ebcnt; ++i) {
107 err = erase_eraseblock(i);
112 printk(PRINT_PREF "erased %u eraseblocks\n", i);
116 static int write_eraseblock(int ebnum)
120 loff_t addr = ebnum * mtd->erasesize;
122 set_random_data(writebuf, subpgsize);
123 err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
124 if (unlikely(err || written != subpgsize)) {
125 printk(PRINT_PREF "error: write failed at %#llx\n",
127 if (written != subpgsize) {
128 printk(PRINT_PREF " write size: %#x\n", subpgsize);
129 printk(PRINT_PREF " written: %#zx\n", written);
131 return err ? err : -1;
136 set_random_data(writebuf, subpgsize);
137 err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
138 if (unlikely(err || written != subpgsize)) {
139 printk(PRINT_PREF "error: write failed at %#llx\n",
141 if (written != subpgsize) {
142 printk(PRINT_PREF " write size: %#x\n", subpgsize);
143 printk(PRINT_PREF " written: %#zx\n", written);
145 return err ? err : -1;
151 static int write_eraseblock2(int ebnum)
155 loff_t addr = ebnum * mtd->erasesize;
157 for (k = 1; k < 33; ++k) {
158 if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
160 set_random_data(writebuf, subpgsize * k);
161 err = mtd_write(mtd, addr, subpgsize * k, &written, writebuf);
162 if (unlikely(err || written != subpgsize * k)) {
163 printk(PRINT_PREF "error: write failed at %#llx\n",
165 if (written != subpgsize) {
166 printk(PRINT_PREF " write size: %#x\n",
168 printk(PRINT_PREF " written: %#08zx\n",
171 return err ? err : -1;
173 addr += subpgsize * k;
179 static void print_subpage(unsigned char *p)
183 for (i = 0; i < subpgsize; ) {
184 for (j = 0; i < subpgsize && j < 32; ++i, ++j)
185 printk("%02x", *p++);
190 static int verify_eraseblock(int ebnum)
194 loff_t addr = ebnum * mtd->erasesize;
196 set_random_data(writebuf, subpgsize);
197 clear_data(readbuf, subpgsize);
198 err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
199 if (unlikely(err || read != subpgsize)) {
200 if (mtd_is_bitflip(err) && read == subpgsize) {
201 printk(PRINT_PREF "ECC correction at %#llx\n",
205 printk(PRINT_PREF "error: read failed at %#llx\n",
207 return err ? err : -1;
210 if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
211 printk(PRINT_PREF "error: verify failed at %#llx\n",
213 printk(PRINT_PREF "------------- written----------------\n");
214 print_subpage(writebuf);
215 printk(PRINT_PREF "------------- read ------------------\n");
216 print_subpage(readbuf);
217 printk(PRINT_PREF "-------------------------------------\n");
223 set_random_data(writebuf, subpgsize);
224 clear_data(readbuf, subpgsize);
225 err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
226 if (unlikely(err || read != subpgsize)) {
227 if (mtd_is_bitflip(err) && read == subpgsize) {
228 printk(PRINT_PREF "ECC correction at %#llx\n",
232 printk(PRINT_PREF "error: read failed at %#llx\n",
234 return err ? err : -1;
237 if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
238 printk(PRINT_PREF "error: verify failed at %#llx\n",
240 printk(PRINT_PREF "------------- written----------------\n");
241 print_subpage(writebuf);
242 printk(PRINT_PREF "------------- read ------------------\n");
243 print_subpage(readbuf);
244 printk(PRINT_PREF "-------------------------------------\n");
251 static int verify_eraseblock2(int ebnum)
255 loff_t addr = ebnum * mtd->erasesize;
257 for (k = 1; k < 33; ++k) {
258 if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
260 set_random_data(writebuf, subpgsize * k);
261 clear_data(readbuf, subpgsize * k);
262 err = mtd_read(mtd, addr, subpgsize * k, &read, readbuf);
263 if (unlikely(err || read != subpgsize * k)) {
264 if (mtd_is_bitflip(err) && read == subpgsize * k) {
265 printk(PRINT_PREF "ECC correction at %#llx\n",
269 printk(PRINT_PREF "error: read failed at "
270 "%#llx\n", (long long)addr);
271 return err ? err : -1;
274 if (unlikely(memcmp(readbuf, writebuf, subpgsize * k))) {
275 printk(PRINT_PREF "error: verify failed at %#llx\n",
279 addr += subpgsize * k;
285 static int verify_eraseblock_ff(int ebnum)
290 loff_t addr = ebnum * mtd->erasesize;
292 memset(writebuf, 0xff, subpgsize);
293 for (j = 0; j < mtd->erasesize / subpgsize; ++j) {
294 clear_data(readbuf, subpgsize);
295 err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
296 if (unlikely(err || read != subpgsize)) {
297 if (mtd_is_bitflip(err) && read == subpgsize) {
298 printk(PRINT_PREF "ECC correction at %#llx\n",
302 printk(PRINT_PREF "error: read failed at "
303 "%#llx\n", (long long)addr);
304 return err ? err : -1;
307 if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
308 printk(PRINT_PREF "error: verify 0xff failed at "
309 "%#llx\n", (long long)addr);
318 static int verify_all_eraseblocks_ff(void)
323 printk(PRINT_PREF "verifying all eraseblocks for 0xff\n");
324 for (i = 0; i < ebcnt; ++i) {
327 err = verify_eraseblock_ff(i);
331 printk(PRINT_PREF "verified up to eraseblock %u\n", i);
334 printk(PRINT_PREF "verified %u eraseblocks\n", i);
338 static int is_block_bad(int ebnum)
340 loff_t addr = ebnum * mtd->erasesize;
343 ret = mtd_block_isbad(mtd, addr);
345 printk(PRINT_PREF "block %d is bad\n", ebnum);
349 static int scan_for_bad_eraseblocks(void)
353 bbt = kzalloc(ebcnt, GFP_KERNEL);
355 printk(PRINT_PREF "error: cannot allocate memory\n");
359 printk(PRINT_PREF "scanning for bad eraseblocks\n");
360 for (i = 0; i < ebcnt; ++i) {
361 bbt[i] = is_block_bad(i) ? 1 : 0;
366 printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
370 static int __init mtd_subpagetest_init(void)
376 printk(KERN_INFO "\n");
377 printk(KERN_INFO "=================================================\n");
380 printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
381 printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
385 printk(PRINT_PREF "MTD device: %d\n", dev);
387 mtd = get_mtd_device(NULL, dev);
390 printk(PRINT_PREF "error: cannot get MTD device\n");
394 if (mtd->type != MTD_NANDFLASH) {
395 printk(PRINT_PREF "this test requires NAND flash\n");
399 subpgsize = mtd->writesize >> mtd->subpage_sft;
401 do_div(tmp, mtd->erasesize);
403 pgcnt = mtd->erasesize / mtd->writesize;
405 printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
406 "page size %u, subpage size %u, count of eraseblocks %u, "
407 "pages per eraseblock %u, OOB size %u\n",
408 (unsigned long long)mtd->size, mtd->erasesize,
409 mtd->writesize, subpgsize, ebcnt, pgcnt, mtd->oobsize);
412 bufsize = subpgsize * 32;
413 writebuf = kmalloc(bufsize, GFP_KERNEL);
415 printk(PRINT_PREF "error: cannot allocate memory\n");
418 readbuf = kmalloc(bufsize, GFP_KERNEL);
420 printk(PRINT_PREF "error: cannot allocate memory\n");
424 err = scan_for_bad_eraseblocks();
428 err = erase_whole_device();
432 printk(PRINT_PREF "writing whole device\n");
434 for (i = 0; i < ebcnt; ++i) {
437 err = write_eraseblock(i);
441 printk(PRINT_PREF "written up to eraseblock %u\n", i);
444 printk(PRINT_PREF "written %u eraseblocks\n", i);
447 printk(PRINT_PREF "verifying all eraseblocks\n");
448 for (i = 0; i < ebcnt; ++i) {
451 err = verify_eraseblock(i);
455 printk(PRINT_PREF "verified up to eraseblock %u\n", i);
458 printk(PRINT_PREF "verified %u eraseblocks\n", i);
460 err = erase_whole_device();
464 err = verify_all_eraseblocks_ff();
468 /* Write all eraseblocks */
470 printk(PRINT_PREF "writing whole device\n");
471 for (i = 0; i < ebcnt; ++i) {
474 err = write_eraseblock2(i);
478 printk(PRINT_PREF "written up to eraseblock %u\n", i);
481 printk(PRINT_PREF "written %u eraseblocks\n", i);
483 /* Check all eraseblocks */
485 printk(PRINT_PREF "verifying all eraseblocks\n");
486 for (i = 0; i < ebcnt; ++i) {
489 err = verify_eraseblock2(i);
493 printk(PRINT_PREF "verified up to eraseblock %u\n", i);
496 printk(PRINT_PREF "verified %u eraseblocks\n", i);
498 err = erase_whole_device();
502 err = verify_all_eraseblocks_ff();
506 printk(PRINT_PREF "finished with %d errors\n", errcnt);
514 printk(PRINT_PREF "error %d occurred\n", err);
515 printk(KERN_INFO "=================================================\n");
518 module_init(mtd_subpagetest_init);
520 static void __exit mtd_subpagetest_exit(void)
524 module_exit(mtd_subpagetest_exit);
526 MODULE_DESCRIPTION("Subpage test module");
527 MODULE_AUTHOR("Adrian Hunter");
528 MODULE_LICENSE("GPL");