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