xref: /openbmc/linux/drivers/mtd/tests/pagetest.c (revision abc173ad)
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 			return err;
89 		err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages);
90 		if (err)
91 			return err;
92 		memset(twopages, 0, bufsize);
93 		err = mtdtest_read(mtd, addr, bufsize, twopages);
94 		if (err)
95 			break;
96 		if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) {
97 			pr_err("error: verify failed at %#llx\n",
98 			       (long long)addr);
99 			errcnt += 1;
100 		}
101 	}
102 	/* Check boundary between eraseblocks */
103 	if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) {
104 		struct rnd_state old_state = rnd_state;
105 
106 		/* Do a read to set the internal dataRAMs to different data */
107 		err = mtdtest_read(mtd, addr0, bufsize, twopages);
108 		if (err)
109 			return err;
110 		err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages);
111 		if (err)
112 			return err;
113 		memset(twopages, 0, bufsize);
114 		err = mtdtest_read(mtd, addr, bufsize, twopages);
115 		if (err)
116 			return err;
117 		memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize);
118 		prandom_bytes_state(&rnd_state, boundary + pgsize, pgsize);
119 		if (memcmp(twopages, boundary, bufsize)) {
120 			pr_err("error: verify failed at %#llx\n",
121 			       (long long)addr);
122 			errcnt += 1;
123 		}
124 		rnd_state = old_state;
125 	}
126 	return err;
127 }
128 
129 static int crosstest(void)
130 {
131 	int err = 0, i;
132 	loff_t addr, addr0, addrn;
133 	unsigned char *pp1, *pp2, *pp3, *pp4;
134 
135 	pr_info("crosstest\n");
136 	pp1 = kmalloc(pgsize * 4, GFP_KERNEL);
137 	if (!pp1)
138 		return -ENOMEM;
139 	pp2 = pp1 + pgsize;
140 	pp3 = pp2 + pgsize;
141 	pp4 = pp3 + pgsize;
142 	memset(pp1, 0, pgsize * 4);
143 
144 	addr0 = 0;
145 	for (i = 0; i < ebcnt && bbt[i]; ++i)
146 		addr0 += mtd->erasesize;
147 
148 	addrn = mtd->size;
149 	for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
150 		addrn -= mtd->erasesize;
151 
152 	/* Read 2nd-to-last page to pp1 */
153 	addr = addrn - pgsize - pgsize;
154 	err = mtdtest_read(mtd, addr, pgsize, pp1);
155 	if (err) {
156 		kfree(pp1);
157 		return err;
158 	}
159 
160 	/* Read 3rd-to-last page to pp1 */
161 	addr = addrn - pgsize - pgsize - pgsize;
162 	err = mtdtest_read(mtd, addr, pgsize, pp1);
163 	if (err) {
164 		kfree(pp1);
165 		return err;
166 	}
167 
168 	/* Read first page to pp2 */
169 	addr = addr0;
170 	pr_info("reading page at %#llx\n", (long long)addr);
171 	err = mtdtest_read(mtd, addr, pgsize, pp2);
172 	if (err) {
173 		kfree(pp1);
174 		return err;
175 	}
176 
177 	/* Read last page to pp3 */
178 	addr = addrn - pgsize;
179 	pr_info("reading page at %#llx\n", (long long)addr);
180 	err = mtdtest_read(mtd, addr, pgsize, pp3);
181 	if (err) {
182 		kfree(pp1);
183 		return err;
184 	}
185 
186 	/* Read first page again to pp4 */
187 	addr = addr0;
188 	pr_info("reading page at %#llx\n", (long long)addr);
189 	err = mtdtest_read(mtd, addr, pgsize, pp4);
190 	if (err) {
191 		kfree(pp1);
192 		return err;
193 	}
194 
195 	/* pp2 and pp4 should be the same */
196 	pr_info("verifying pages read at %#llx match\n",
197 	       (long long)addr0);
198 	if (memcmp(pp2, pp4, pgsize)) {
199 		pr_err("verify failed!\n");
200 		errcnt += 1;
201 	} else if (!err)
202 		pr_info("crosstest ok\n");
203 	kfree(pp1);
204 	return err;
205 }
206 
207 static int erasecrosstest(void)
208 {
209 	int err = 0, i, ebnum, ebnum2;
210 	loff_t addr0;
211 	char *readbuf = twopages;
212 
213 	pr_info("erasecrosstest\n");
214 
215 	ebnum = 0;
216 	addr0 = 0;
217 	for (i = 0; i < ebcnt && bbt[i]; ++i) {
218 		addr0 += mtd->erasesize;
219 		ebnum += 1;
220 	}
221 
222 	ebnum2 = ebcnt - 1;
223 	while (ebnum2 && bbt[ebnum2])
224 		ebnum2 -= 1;
225 
226 	pr_info("erasing block %d\n", ebnum);
227 	err = mtdtest_erase_eraseblock(mtd, ebnum);
228 	if (err)
229 		return err;
230 
231 	pr_info("writing 1st page of block %d\n", ebnum);
232 	prandom_bytes_state(&rnd_state, writebuf, pgsize);
233 	strcpy(writebuf, "There is no data like this!");
234 	err = mtdtest_write(mtd, addr0, pgsize, writebuf);
235 	if (err) {
236 		pr_info("error: write failed at %#llx\n",
237 		       (long long)addr0);
238 		return err;
239 	}
240 
241 	pr_info("reading 1st page of block %d\n", ebnum);
242 	memset(readbuf, 0, pgsize);
243 	err = mtdtest_read(mtd, addr0, pgsize, readbuf);
244 	if (err)
245 		return err;
246 
247 	pr_info("verifying 1st page of block %d\n", ebnum);
248 	if (memcmp(writebuf, readbuf, pgsize)) {
249 		pr_err("verify failed!\n");
250 		errcnt += 1;
251 		return -1;
252 	}
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_err("error: write failed at %#llx\n",
265 		       (long long)addr0);
266 		return err;
267 	}
268 
269 	pr_info("erasing block %d\n", ebnum2);
270 	err = mtdtest_erase_eraseblock(mtd, ebnum2);
271 	if (err)
272 		return err;
273 
274 	pr_info("reading 1st page of block %d\n", ebnum);
275 	memset(readbuf, 0, pgsize);
276 	err = mtdtest_read(mtd, addr0, pgsize, readbuf);
277 	if (err)
278 		return err;
279 
280 	pr_info("verifying 1st page of block %d\n", ebnum);
281 	if (memcmp(writebuf, readbuf, pgsize)) {
282 		pr_err("verify failed!\n");
283 		errcnt += 1;
284 		return -1;
285 	}
286 
287 	if (!err)
288 		pr_info("erasecrosstest ok\n");
289 	return err;
290 }
291 
292 static int erasetest(void)
293 {
294 	int err = 0, i, ebnum, ok = 1;
295 	loff_t addr0;
296 
297 	pr_info("erasetest\n");
298 
299 	ebnum = 0;
300 	addr0 = 0;
301 	for (i = 0; i < ebcnt && bbt[i]; ++i) {
302 		addr0 += mtd->erasesize;
303 		ebnum += 1;
304 	}
305 
306 	pr_info("erasing block %d\n", ebnum);
307 	err = mtdtest_erase_eraseblock(mtd, ebnum);
308 	if (err)
309 		return err;
310 
311 	pr_info("writing 1st page of block %d\n", ebnum);
312 	prandom_bytes_state(&rnd_state, writebuf, pgsize);
313 	err = mtdtest_write(mtd, addr0, pgsize, writebuf);
314 	if (err) {
315 		pr_err("error: write failed at %#llx\n",
316 		       (long long)addr0);
317 		return err;
318 	}
319 
320 	pr_info("erasing block %d\n", ebnum);
321 	err = mtdtest_erase_eraseblock(mtd, ebnum);
322 	if (err)
323 		return err;
324 
325 	pr_info("reading 1st page of block %d\n", ebnum);
326 	err = mtdtest_read(mtd, addr0, pgsize, twopages);
327 	if (err)
328 		return err;
329 
330 	pr_info("verifying 1st page of block %d is all 0xff\n",
331 	       ebnum);
332 	for (i = 0; i < pgsize; ++i)
333 		if (twopages[i] != 0xff) {
334 			pr_err("verifying all 0xff failed at %d\n",
335 			       i);
336 			errcnt += 1;
337 			ok = 0;
338 			break;
339 		}
340 
341 	if (ok && !err)
342 		pr_info("erasetest ok\n");
343 
344 	return err;
345 }
346 
347 static int __init mtd_pagetest_init(void)
348 {
349 	int err = 0;
350 	uint64_t tmp;
351 	uint32_t i;
352 
353 	printk(KERN_INFO "\n");
354 	printk(KERN_INFO "=================================================\n");
355 
356 	if (dev < 0) {
357 		pr_info("Please specify a valid mtd-device via module parameter\n");
358 		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
359 		return -EINVAL;
360 	}
361 
362 	pr_info("MTD device: %d\n", dev);
363 
364 	mtd = get_mtd_device(NULL, dev);
365 	if (IS_ERR(mtd)) {
366 		err = PTR_ERR(mtd);
367 		pr_err("error: cannot get MTD device\n");
368 		return err;
369 	}
370 
371 	if (mtd->type != MTD_NANDFLASH) {
372 		pr_info("this test requires NAND flash\n");
373 		goto out;
374 	}
375 
376 	tmp = mtd->size;
377 	do_div(tmp, mtd->erasesize);
378 	ebcnt = tmp;
379 	pgcnt = mtd->erasesize / mtd->writesize;
380 	pgsize = mtd->writesize;
381 
382 	pr_info("MTD device size %llu, eraseblock size %u, "
383 	       "page size %u, count of eraseblocks %u, pages per "
384 	       "eraseblock %u, OOB size %u\n",
385 	       (unsigned long long)mtd->size, mtd->erasesize,
386 	       pgsize, ebcnt, pgcnt, mtd->oobsize);
387 
388 	err = -ENOMEM;
389 	bufsize = pgsize * 2;
390 	writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
391 	if (!writebuf)
392 		goto out;
393 	twopages = kmalloc(bufsize, GFP_KERNEL);
394 	if (!twopages)
395 		goto out;
396 	boundary = kmalloc(bufsize, GFP_KERNEL);
397 	if (!boundary)
398 		goto out;
399 
400 	bbt = kzalloc(ebcnt, GFP_KERNEL);
401 	if (!bbt)
402 		goto out;
403 	err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
404 	if (err)
405 		goto out;
406 
407 	/* Erase all eraseblocks */
408 	pr_info("erasing whole device\n");
409 	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
410 	if (err)
411 		goto out;
412 	pr_info("erased %u eraseblocks\n", ebcnt);
413 
414 	/* Write all eraseblocks */
415 	prandom_seed_state(&rnd_state, 1);
416 	pr_info("writing whole device\n");
417 	for (i = 0; i < ebcnt; ++i) {
418 		if (bbt[i])
419 			continue;
420 		err = write_eraseblock(i);
421 		if (err)
422 			goto out;
423 		if (i % 256 == 0)
424 			pr_info("written up to eraseblock %u\n", i);
425 		cond_resched();
426 	}
427 	pr_info("written %u eraseblocks\n", i);
428 
429 	/* Check all eraseblocks */
430 	prandom_seed_state(&rnd_state, 1);
431 	pr_info("verifying all eraseblocks\n");
432 	for (i = 0; i < ebcnt; ++i) {
433 		if (bbt[i])
434 			continue;
435 		err = verify_eraseblock(i);
436 		if (err)
437 			goto out;
438 		if (i % 256 == 0)
439 			pr_info("verified up to eraseblock %u\n", i);
440 		cond_resched();
441 	}
442 	pr_info("verified %u eraseblocks\n", i);
443 
444 	err = crosstest();
445 	if (err)
446 		goto out;
447 
448 	err = erasecrosstest();
449 	if (err)
450 		goto out;
451 
452 	err = erasetest();
453 	if (err)
454 		goto out;
455 
456 	pr_info("finished with %d errors\n", errcnt);
457 out:
458 
459 	kfree(bbt);
460 	kfree(boundary);
461 	kfree(twopages);
462 	kfree(writebuf);
463 	put_mtd_device(mtd);
464 	if (err)
465 		pr_info("error %d occurred\n", err);
466 	printk(KERN_INFO "=================================================\n");
467 	return err;
468 }
469 module_init(mtd_pagetest_init);
470 
471 static void __exit mtd_pagetest_exit(void)
472 {
473 	return;
474 }
475 module_exit(mtd_pagetest_exit);
476 
477 MODULE_DESCRIPTION("NAND page test");
478 MODULE_AUTHOR("Adrian Hunter");
479 MODULE_LICENSE("GPL");
480