Merge remote-tracking branch 'torvalds/master' into perf/urgent
[linux-2.6-microblaze.git] / drivers / mtd / tests / pagetest.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2006-2008 Nokia Corporation
4  *
5  * Test page read and write on MTD device.
6  *
7  * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
8  */
9
10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11
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>
21
22 #include "mtd_test.h"
23
24 static int dev = -EINVAL;
25 module_param(dev, int, S_IRUGO);
26 MODULE_PARM_DESC(dev, "MTD device number to use");
27
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;
33
34 static int pgsize;
35 static int bufsize;
36 static int ebcnt;
37 static int pgcnt;
38 static int errcnt;
39 static struct rnd_state rnd_state;
40
41 static int write_eraseblock(int ebnum)
42 {
43         loff_t addr = (loff_t)ebnum * mtd->erasesize;
44
45         prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
46         cond_resched();
47         return mtdtest_write(mtd, addr, mtd->erasesize, writebuf);
48 }
49
50 static int verify_eraseblock(int ebnum)
51 {
52         uint32_t j;
53         int err = 0, i;
54         loff_t addr0, addrn;
55         loff_t addr = (loff_t)ebnum * mtd->erasesize;
56
57         addr0 = 0;
58         for (i = 0; i < ebcnt && bbt[i]; ++i)
59                 addr0 += mtd->erasesize;
60
61         addrn = mtd->size;
62         for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
63                 addrn -= mtd->erasesize;
64
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);
69                 if (err)
70                         return err;
71                 err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages);
72                 if (err)
73                         return err;
74                 memset(twopages, 0, bufsize);
75                 err = mtdtest_read(mtd, addr, bufsize, twopages);
76                 if (err)
77                         break;
78                 if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) {
79                         pr_err("error: verify failed at %#llx\n",
80                                (long long)addr);
81                         errcnt += 1;
82                 }
83         }
84         /* Check boundary between eraseblocks */
85         if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) {
86                 struct rnd_state old_state = rnd_state;
87
88                 /* Do a read to set the internal dataRAMs to different data */
89                 err = mtdtest_read(mtd, addr0, bufsize, twopages);
90                 if (err)
91                         return err;
92                 err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages);
93                 if (err)
94                         return err;
95                 memset(twopages, 0, bufsize);
96                 err = mtdtest_read(mtd, addr, bufsize, twopages);
97                 if (err)
98                         return err;
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",
103                                (long long)addr);
104                         errcnt += 1;
105                 }
106                 rnd_state = old_state;
107         }
108         return err;
109 }
110
111 static int crosstest(void)
112 {
113         int err = 0, i;
114         loff_t addr, addr0, addrn;
115         unsigned char *pp1, *pp2, *pp3, *pp4;
116
117         pr_info("crosstest\n");
118         pp1 = kcalloc(pgsize, 4, GFP_KERNEL);
119         if (!pp1)
120                 return -ENOMEM;
121         pp2 = pp1 + pgsize;
122         pp3 = pp2 + pgsize;
123         pp4 = pp3 + pgsize;
124
125         addr0 = 0;
126         for (i = 0; i < ebcnt && bbt[i]; ++i)
127                 addr0 += mtd->erasesize;
128
129         addrn = mtd->size;
130         for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
131                 addrn -= mtd->erasesize;
132
133         /* Read 2nd-to-last page to pp1 */
134         addr = addrn - pgsize - pgsize;
135         err = mtdtest_read(mtd, addr, pgsize, pp1);
136         if (err) {
137                 kfree(pp1);
138                 return err;
139         }
140
141         /* Read 3rd-to-last page to pp1 */
142         addr = addrn - pgsize - pgsize - pgsize;
143         err = mtdtest_read(mtd, addr, pgsize, pp1);
144         if (err) {
145                 kfree(pp1);
146                 return err;
147         }
148
149         /* Read first page to pp2 */
150         addr = addr0;
151         pr_info("reading page at %#llx\n", (long long)addr);
152         err = mtdtest_read(mtd, addr, pgsize, pp2);
153         if (err) {
154                 kfree(pp1);
155                 return err;
156         }
157
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);
162         if (err) {
163                 kfree(pp1);
164                 return err;
165         }
166
167         /* Read first page again to pp4 */
168         addr = addr0;
169         pr_info("reading page at %#llx\n", (long long)addr);
170         err = mtdtest_read(mtd, addr, pgsize, pp4);
171         if (err) {
172                 kfree(pp1);
173                 return err;
174         }
175
176         /* pp2 and pp4 should be the same */
177         pr_info("verifying pages read at %#llx match\n",
178                (long long)addr0);
179         if (memcmp(pp2, pp4, pgsize)) {
180                 pr_err("verify failed!\n");
181                 errcnt += 1;
182         } else if (!err)
183                 pr_info("crosstest ok\n");
184         kfree(pp1);
185         return err;
186 }
187
188 static int erasecrosstest(void)
189 {
190         int err = 0, i, ebnum, ebnum2;
191         loff_t addr0;
192         char *readbuf = twopages;
193
194         pr_info("erasecrosstest\n");
195
196         ebnum = 0;
197         addr0 = 0;
198         for (i = 0; i < ebcnt && bbt[i]; ++i) {
199                 addr0 += mtd->erasesize;
200                 ebnum += 1;
201         }
202
203         ebnum2 = ebcnt - 1;
204         while (ebnum2 && bbt[ebnum2])
205                 ebnum2 -= 1;
206
207         pr_info("erasing block %d\n", ebnum);
208         err = mtdtest_erase_eraseblock(mtd, ebnum);
209         if (err)
210                 return err;
211
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);
216         if (err)
217                 return err;
218
219         pr_info("reading 1st page of block %d\n", ebnum);
220         memset(readbuf, 0, pgsize);
221         err = mtdtest_read(mtd, addr0, pgsize, readbuf);
222         if (err)
223                 return err;
224
225         pr_info("verifying 1st page of block %d\n", ebnum);
226         if (memcmp(writebuf, readbuf, pgsize)) {
227                 pr_err("verify failed!\n");
228                 errcnt += 1;
229                 return -1;
230         }
231
232         pr_info("erasing block %d\n", ebnum);
233         err = mtdtest_erase_eraseblock(mtd, ebnum);
234         if (err)
235                 return err;
236
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);
241         if (err)
242                 return err;
243
244         pr_info("erasing block %d\n", ebnum2);
245         err = mtdtest_erase_eraseblock(mtd, ebnum2);
246         if (err)
247                 return err;
248
249         pr_info("reading 1st page of block %d\n", ebnum);
250         memset(readbuf, 0, pgsize);
251         err = mtdtest_read(mtd, addr0, pgsize, readbuf);
252         if (err)
253                 return err;
254
255         pr_info("verifying 1st page of block %d\n", ebnum);
256         if (memcmp(writebuf, readbuf, pgsize)) {
257                 pr_err("verify failed!\n");
258                 errcnt += 1;
259                 return -1;
260         }
261
262         if (!err)
263                 pr_info("erasecrosstest ok\n");
264         return err;
265 }
266
267 static int erasetest(void)
268 {
269         int err = 0, i, ebnum, ok = 1;
270         loff_t addr0;
271
272         pr_info("erasetest\n");
273
274         ebnum = 0;
275         addr0 = 0;
276         for (i = 0; i < ebcnt && bbt[i]; ++i) {
277                 addr0 += mtd->erasesize;
278                 ebnum += 1;
279         }
280
281         pr_info("erasing block %d\n", ebnum);
282         err = mtdtest_erase_eraseblock(mtd, ebnum);
283         if (err)
284                 return err;
285
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);
289         if (err)
290                 return err;
291
292         pr_info("erasing block %d\n", ebnum);
293         err = mtdtest_erase_eraseblock(mtd, ebnum);
294         if (err)
295                 return err;
296
297         pr_info("reading 1st page of block %d\n", ebnum);
298         err = mtdtest_read(mtd, addr0, pgsize, twopages);
299         if (err)
300                 return err;
301
302         pr_info("verifying 1st page of block %d is all 0xff\n",
303                ebnum);
304         for (i = 0; i < pgsize; ++i)
305                 if (twopages[i] != 0xff) {
306                         pr_err("verifying all 0xff failed at %d\n",
307                                i);
308                         errcnt += 1;
309                         ok = 0;
310                         break;
311                 }
312
313         if (ok && !err)
314                 pr_info("erasetest ok\n");
315
316         return err;
317 }
318
319 static int __init mtd_pagetest_init(void)
320 {
321         int err = 0;
322         uint64_t tmp;
323         uint32_t i;
324
325         printk(KERN_INFO "\n");
326         printk(KERN_INFO "=================================================\n");
327
328         if (dev < 0) {
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");
331                 return -EINVAL;
332         }
333
334         pr_info("MTD device: %d\n", dev);
335
336         mtd = get_mtd_device(NULL, dev);
337         if (IS_ERR(mtd)) {
338                 err = PTR_ERR(mtd);
339                 pr_err("error: cannot get MTD device\n");
340                 return err;
341         }
342
343         if (!mtd_type_is_nand(mtd)) {
344                 pr_info("this test requires NAND flash\n");
345                 goto out;
346         }
347
348         tmp = mtd->size;
349         do_div(tmp, mtd->erasesize);
350         ebcnt = tmp;
351         pgcnt = mtd->erasesize / mtd->writesize;
352         pgsize = mtd->writesize;
353
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);
359
360         err = -ENOMEM;
361         bufsize = pgsize * 2;
362         writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
363         if (!writebuf)
364                 goto out;
365         twopages = kmalloc(bufsize, GFP_KERNEL);
366         if (!twopages)
367                 goto out;
368         boundary = kmalloc(bufsize, GFP_KERNEL);
369         if (!boundary)
370                 goto out;
371
372         bbt = kzalloc(ebcnt, GFP_KERNEL);
373         if (!bbt)
374                 goto out;
375         err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
376         if (err)
377                 goto out;
378
379         /* Erase all eraseblocks */
380         pr_info("erasing whole device\n");
381         err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
382         if (err)
383                 goto out;
384         pr_info("erased %u eraseblocks\n", ebcnt);
385
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) {
390                 if (bbt[i])
391                         continue;
392                 err = write_eraseblock(i);
393                 if (err)
394                         goto out;
395                 if (i % 256 == 0)
396                         pr_info("written up to eraseblock %u\n", i);
397
398                 err = mtdtest_relax();
399                 if (err)
400                         goto out;
401         }
402         pr_info("written %u eraseblocks\n", i);
403
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) {
408                 if (bbt[i])
409                         continue;
410                 err = verify_eraseblock(i);
411                 if (err)
412                         goto out;
413                 if (i % 256 == 0)
414                         pr_info("verified up to eraseblock %u\n", i);
415
416                 err = mtdtest_relax();
417                 if (err)
418                         goto out;
419         }
420         pr_info("verified %u eraseblocks\n", i);
421
422         err = crosstest();
423         if (err)
424                 goto out;
425
426         if (ebcnt > 1) {
427                 err = erasecrosstest();
428                 if (err)
429                         goto out;
430         } else {
431                 pr_info("skipping erasecrosstest, 2 erase blocks needed\n");
432         }
433
434         err = erasetest();
435         if (err)
436                 goto out;
437
438         pr_info("finished with %d errors\n", errcnt);
439 out:
440
441         kfree(bbt);
442         kfree(boundary);
443         kfree(twopages);
444         kfree(writebuf);
445         put_mtd_device(mtd);
446         if (err)
447                 pr_info("error %d occurred\n", err);
448         printk(KERN_INFO "=================================================\n");
449         return err;
450 }
451 module_init(mtd_pagetest_init);
452
453 static void __exit mtd_pagetest_exit(void)
454 {
455         return;
456 }
457 module_exit(mtd_pagetest_exit);
458
459 MODULE_DESCRIPTION("NAND page test");
460 MODULE_AUTHOR("Adrian Hunter");
461 MODULE_LICENSE("GPL");