1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2006-2008 Nokia Corporation
5 * Test page read and write on MTD device.
7 * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 #include <asm/div64.h>
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/moduleparam.h>
16 #include <linux/err.h>
17 #include <linux/mtd/mtd.h>
18 #include <linux/slab.h>
19 #include <linux/sched.h>
20 #include <linux/random.h>
24 static int dev
= -EINVAL
;
25 module_param(dev
, int, S_IRUGO
);
26 MODULE_PARM_DESC(dev
, "MTD device number to use");
28 static struct mtd_info
*mtd
;
29 static unsigned char *twopages
;
30 static unsigned char *writebuf
;
31 static unsigned char *boundary
;
32 static unsigned char *bbt
;
39 static struct rnd_state rnd_state
;
41 static int write_eraseblock(int ebnum
)
43 loff_t addr
= (loff_t
)ebnum
* mtd
->erasesize
;
45 prandom_bytes_state(&rnd_state
, writebuf
, mtd
->erasesize
);
47 return mtdtest_write(mtd
, addr
, mtd
->erasesize
, writebuf
);
50 static int verify_eraseblock(int ebnum
)
55 loff_t addr
= (loff_t
)ebnum
* mtd
->erasesize
;
58 for (i
= 0; i
< ebcnt
&& bbt
[i
]; ++i
)
59 addr0
+= mtd
->erasesize
;
62 for (i
= 0; i
< ebcnt
&& bbt
[ebcnt
- i
- 1]; ++i
)
63 addrn
-= mtd
->erasesize
;
65 prandom_bytes_state(&rnd_state
, writebuf
, mtd
->erasesize
);
66 for (j
= 0; j
< pgcnt
- 1; ++j
, addr
+= pgsize
) {
67 /* Do a read to set the internal dataRAMs to different data */
68 err
= mtdtest_read(mtd
, addr0
, bufsize
, twopages
);
71 err
= mtdtest_read(mtd
, addrn
- bufsize
, bufsize
, twopages
);
74 memset(twopages
, 0, bufsize
);
75 err
= mtdtest_read(mtd
, addr
, bufsize
, twopages
);
78 if (memcmp(twopages
, writebuf
+ (j
* pgsize
), bufsize
)) {
79 pr_err("error: verify failed at %#llx\n",
84 /* Check boundary between eraseblocks */
85 if (addr
<= addrn
- pgsize
- pgsize
&& !bbt
[ebnum
+ 1]) {
86 struct rnd_state old_state
= rnd_state
;
88 /* Do a read to set the internal dataRAMs to different data */
89 err
= mtdtest_read(mtd
, addr0
, bufsize
, twopages
);
92 err
= mtdtest_read(mtd
, addrn
- bufsize
, bufsize
, twopages
);
95 memset(twopages
, 0, bufsize
);
96 err
= mtdtest_read(mtd
, addr
, bufsize
, twopages
);
99 memcpy(boundary
, writebuf
+ mtd
->erasesize
- pgsize
, pgsize
);
100 prandom_bytes_state(&rnd_state
, boundary
+ pgsize
, pgsize
);
101 if (memcmp(twopages
, boundary
, bufsize
)) {
102 pr_err("error: verify failed at %#llx\n",
106 rnd_state
= old_state
;
111 static int crosstest(void)
114 loff_t addr
, addr0
, addrn
;
115 unsigned char *pp1
, *pp2
, *pp3
, *pp4
;
117 pr_info("crosstest\n");
118 pp1
= kcalloc(pgsize
, 4, GFP_KERNEL
);
126 for (i
= 0; i
< ebcnt
&& bbt
[i
]; ++i
)
127 addr0
+= mtd
->erasesize
;
130 for (i
= 0; i
< ebcnt
&& bbt
[ebcnt
- i
- 1]; ++i
)
131 addrn
-= mtd
->erasesize
;
133 /* Read 2nd-to-last page to pp1 */
134 addr
= addrn
- pgsize
- pgsize
;
135 err
= mtdtest_read(mtd
, addr
, pgsize
, pp1
);
141 /* Read 3rd-to-last page to pp1 */
142 addr
= addrn
- pgsize
- pgsize
- pgsize
;
143 err
= mtdtest_read(mtd
, addr
, pgsize
, pp1
);
149 /* Read first page to pp2 */
151 pr_info("reading page at %#llx\n", (long long)addr
);
152 err
= mtdtest_read(mtd
, addr
, pgsize
, pp2
);
158 /* Read last page to pp3 */
159 addr
= addrn
- pgsize
;
160 pr_info("reading page at %#llx\n", (long long)addr
);
161 err
= mtdtest_read(mtd
, addr
, pgsize
, pp3
);
167 /* Read first page again to pp4 */
169 pr_info("reading page at %#llx\n", (long long)addr
);
170 err
= mtdtest_read(mtd
, addr
, pgsize
, pp4
);
176 /* pp2 and pp4 should be the same */
177 pr_info("verifying pages read at %#llx match\n",
179 if (memcmp(pp2
, pp4
, pgsize
)) {
180 pr_err("verify failed!\n");
183 pr_info("crosstest ok\n");
188 static int erasecrosstest(void)
190 int err
= 0, i
, ebnum
, ebnum2
;
192 char *readbuf
= twopages
;
194 pr_info("erasecrosstest\n");
198 for (i
= 0; i
< ebcnt
&& bbt
[i
]; ++i
) {
199 addr0
+= mtd
->erasesize
;
204 while (ebnum2
&& bbt
[ebnum2
])
207 pr_info("erasing block %d\n", ebnum
);
208 err
= mtdtest_erase_eraseblock(mtd
, ebnum
);
212 pr_info("writing 1st page of block %d\n", ebnum
);
213 prandom_bytes_state(&rnd_state
, writebuf
, pgsize
);
214 strcpy(writebuf
, "There is no data like this!");
215 err
= mtdtest_write(mtd
, addr0
, pgsize
, writebuf
);
219 pr_info("reading 1st page of block %d\n", ebnum
);
220 memset(readbuf
, 0, pgsize
);
221 err
= mtdtest_read(mtd
, addr0
, pgsize
, readbuf
);
225 pr_info("verifying 1st page of block %d\n", ebnum
);
226 if (memcmp(writebuf
, readbuf
, pgsize
)) {
227 pr_err("verify failed!\n");
232 pr_info("erasing block %d\n", ebnum
);
233 err
= mtdtest_erase_eraseblock(mtd
, ebnum
);
237 pr_info("writing 1st page of block %d\n", ebnum
);
238 prandom_bytes_state(&rnd_state
, writebuf
, pgsize
);
239 strcpy(writebuf
, "There is no data like this!");
240 err
= mtdtest_write(mtd
, addr0
, pgsize
, writebuf
);
244 pr_info("erasing block %d\n", ebnum2
);
245 err
= mtdtest_erase_eraseblock(mtd
, ebnum2
);
249 pr_info("reading 1st page of block %d\n", ebnum
);
250 memset(readbuf
, 0, pgsize
);
251 err
= mtdtest_read(mtd
, addr0
, pgsize
, readbuf
);
255 pr_info("verifying 1st page of block %d\n", ebnum
);
256 if (memcmp(writebuf
, readbuf
, pgsize
)) {
257 pr_err("verify failed!\n");
263 pr_info("erasecrosstest ok\n");
267 static int erasetest(void)
269 int err
= 0, i
, ebnum
, ok
= 1;
272 pr_info("erasetest\n");
276 for (i
= 0; i
< ebcnt
&& bbt
[i
]; ++i
) {
277 addr0
+= mtd
->erasesize
;
281 pr_info("erasing block %d\n", ebnum
);
282 err
= mtdtest_erase_eraseblock(mtd
, ebnum
);
286 pr_info("writing 1st page of block %d\n", ebnum
);
287 prandom_bytes_state(&rnd_state
, writebuf
, pgsize
);
288 err
= mtdtest_write(mtd
, addr0
, pgsize
, writebuf
);
292 pr_info("erasing block %d\n", ebnum
);
293 err
= mtdtest_erase_eraseblock(mtd
, ebnum
);
297 pr_info("reading 1st page of block %d\n", ebnum
);
298 err
= mtdtest_read(mtd
, addr0
, pgsize
, twopages
);
302 pr_info("verifying 1st page of block %d is all 0xff\n",
304 for (i
= 0; i
< pgsize
; ++i
)
305 if (twopages
[i
] != 0xff) {
306 pr_err("verifying all 0xff failed at %d\n",
314 pr_info("erasetest ok\n");
319 static int __init
mtd_pagetest_init(void)
325 printk(KERN_INFO
"\n");
326 printk(KERN_INFO
"=================================================\n");
329 pr_info("Please specify a valid mtd-device via module parameter\n");
330 pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
334 pr_info("MTD device: %d\n", dev
);
336 mtd
= get_mtd_device(NULL
, dev
);
339 pr_err("error: cannot get MTD device\n");
343 if (!mtd_type_is_nand(mtd
)) {
344 pr_info("this test requires NAND flash\n");
349 do_div(tmp
, mtd
->erasesize
);
351 pgcnt
= mtd
->erasesize
/ mtd
->writesize
;
352 pgsize
= mtd
->writesize
;
354 pr_info("MTD device size %llu, eraseblock size %u, "
355 "page size %u, count of eraseblocks %u, pages per "
356 "eraseblock %u, OOB size %u\n",
357 (unsigned long long)mtd
->size
, mtd
->erasesize
,
358 pgsize
, ebcnt
, pgcnt
, mtd
->oobsize
);
361 bufsize
= pgsize
* 2;
362 writebuf
= kmalloc(mtd
->erasesize
, GFP_KERNEL
);
365 twopages
= kmalloc(bufsize
, GFP_KERNEL
);
368 boundary
= kmalloc(bufsize
, GFP_KERNEL
);
372 bbt
= kzalloc(ebcnt
, GFP_KERNEL
);
375 err
= mtdtest_scan_for_bad_eraseblocks(mtd
, bbt
, 0, ebcnt
);
379 /* Erase all eraseblocks */
380 pr_info("erasing whole device\n");
381 err
= mtdtest_erase_good_eraseblocks(mtd
, bbt
, 0, ebcnt
);
384 pr_info("erased %u eraseblocks\n", ebcnt
);
386 /* Write all eraseblocks */
387 prandom_seed_state(&rnd_state
, 1);
388 pr_info("writing whole device\n");
389 for (i
= 0; i
< ebcnt
; ++i
) {
392 err
= write_eraseblock(i
);
396 pr_info("written up to eraseblock %u\n", i
);
398 err
= mtdtest_relax();
402 pr_info("written %u eraseblocks\n", i
);
404 /* Check all eraseblocks */
405 prandom_seed_state(&rnd_state
, 1);
406 pr_info("verifying all eraseblocks\n");
407 for (i
= 0; i
< ebcnt
; ++i
) {
410 err
= verify_eraseblock(i
);
414 pr_info("verified up to eraseblock %u\n", i
);
416 err
= mtdtest_relax();
420 pr_info("verified %u eraseblocks\n", i
);
427 err
= erasecrosstest();
431 pr_info("skipping erasecrosstest, 2 erase blocks needed\n");
438 pr_info("finished with %d errors\n", errcnt
);
447 pr_info("error %d occurred\n", err
);
448 printk(KERN_INFO
"=================================================\n");
451 module_init(mtd_pagetest_init
);
453 static void __exit
mtd_pagetest_exit(void)
457 module_exit(mtd_pagetest_exit
);
459 MODULE_DESCRIPTION("NAND page test");
460 MODULE_AUTHOR("Adrian Hunter");
461 MODULE_LICENSE("GPL");