tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / mtd / tests / sprd_mtdtest / nandflash_stdtest / nandflash_stdtest.c
1 #include <linux/init.h>\r
2 #include <linux/slab.h>\r
3 #include <linux/fs.h>\r
4 #include <asm/uaccess.h>\r
5 #include <linux/types.h>\r
6 #include <linux/moduleparam.h>\r
7 #include <linux/kernel.h>\r
8 #include <linux/module.h>\r
9 #include <linux/mtd/mtd.h>\r
10 #include <linux/delay.h>\r
11 #include <asm/div64.h>\r
12 #include <linux/err.h>\r
13 #include <linux/sched.h>\r
14 #include <linux/random.h>\r
15 #include <linux/vmalloc.h>\r
16 \r
17 #undef pr_fmt\r
18 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt\r
19 \r
20 static int dev = 4;\r
21 module_param(dev, int, S_IRUGO);\r
22 MODULE_PARM_DESC(dev, "MTD device number to use");\r
23 \r
24 static struct mtd_info *mtd = NULL;\r
25 static unsigned char *bbt = NULL;\r
26 \r
27 static int ebcnt;\r
28 static int pgcnt;\r
29 static int errcnt;\r
30 static int pgsize;\r
31 static int subpgsize;\r
32 static int use_offset;\r
33 static int use_len;\r
34 static int use_len_max;\r
35 static int vary_offset;\r
36 static struct rnd_state rnd_state;\r
37 static struct timeval start, finish;\r
38 static int goodebcnt;\r
39 static int subsize;\r
40 static int subcount;\r
41 static int bufsize;\r
42 static unsigned char * writebuf;\r
43 static unsigned char *readbuf;\r
44 static int *offsets;\r
45 static unsigned char *twopages;\r
46 static unsigned char *boundary;\r
47 \r
48 static inline void mtd_test_start_timing(void)\r
49 {\r
50         do_gettimeofday(&start);\r
51 }\r
52 \r
53 static inline void mtd_test_stop_timing(void)\r
54 {\r
55         do_gettimeofday(&finish);\r
56 }\r
57 \r
58 void mtd_test_dump_buf(unsigned char *buf, unsigned int num, unsigned int col_num)\r
59 {\r
60         unsigned int i = 0, j = 0;\r
61 \r
62         if(col_num == 0)\r
63                 col_num = 32;\r
64 \r
65         for(i = 0; i < num; i ++)\r
66         {\r
67                 if((i%col_num) == 0) {\r
68                         if(i != 0)\r
69                                 pr_info("\n");\r
70                         pr_info("%.8x:", j);\r
71                         j += col_num;\r
72                 }\r
73                 if((i%4) == 0)\r
74                         pr_info(" ");\r
75                 pr_info("%.2x", buf[i]);\r
76         }\r
77         pr_info("\n");\r
78 }\r
79 \r
80 static int mtd_test_erase_eraseblock(int ebnum, int blocks)\r
81 {\r
82         int err = 0;\r
83         struct erase_info ei = {0};\r
84 \r
85         if(blocks == 0)\r
86                 blocks = 1;\r
87 \r
88         ei.mtd  = mtd;\r
89         ei.addr = ebnum * mtd->erasesize;\r
90         ei.len  = mtd->erasesize * blocks;\r
91 \r
92         err = mtd_erase(mtd, &ei);\r
93         if (err) {\r
94                 pr_err("error %d while erasing EB %d\n", err, ebnum);\r
95                 return err;\r
96         }\r
97 \r
98         if (ei.state == MTD_ERASE_FAILED) {\r
99                 pr_err("Some erase error occurred at EB %d\n", ebnum);\r
100                 return -EIO;\r
101         }\r
102 \r
103         return 0;\r
104 }\r
105 \r
106 static int mtd_test_erase_whole_device(void)\r
107 {\r
108         int err = 0;\r
109         unsigned int i = 0;\r
110 \r
111         for (i = 0; i < ebcnt; ++i) {\r
112                 if (bbt[i])\r
113                         continue;\r
114                 err = mtd_test_erase_eraseblock(i, 0);\r
115                 if (err)\r
116                         return err;\r
117                 cond_resched();\r
118         }\r
119         return 0;\r
120 }\r
121 \r
122 static int mtd_test_scan_bad_block(void)\r
123 {\r
124         unsigned int i = 0, bad = 0;\r
125 \r
126         bbt = (unsigned char *)vmalloc(ebcnt);\r
127         if (!bbt) {\r
128                 pr_info("error: cannot allocate memory\n");\r
129                 return -ENOMEM;\r
130         }\r
131 \r
132         pr_info("scanning for bad eraseblocks first\n");\r
133         for (i = 0; i < ebcnt; ++i) {\r
134                 bbt[i] = mtd_block_isbad(mtd, i * mtd->erasesize) ? 1 : 0;\r
135                 if (bbt[i])\r
136                         bad += 1;\r
137                 cond_resched();\r
138         }\r
139         pr_info("scanned %d eraseblocks, %d are bad\n", ebcnt, bad);\r
140         goodebcnt = ebcnt - bad;\r
141         return 0;\r
142 }\r
143 \r
144 static int readtest_read_page(int ebnum, unsigned char *databuf, unsigned char *oobbuf)\r
145 {\r
146         int i = 0, ret = 0;\r
147         unsigned int read = 0;\r
148         struct mtd_oob_ops ops = {0};\r
149         loff_t addr = ebnum * mtd->erasesize;\r
150 \r
151         memset(databuf, 0 , mtd->erasesize);\r
152         memset(oobbuf, 0 , mtd->erasesize);\r
153         for (i = 0; i < pgcnt; i++) {\r
154                 ret = mtd_read(mtd, addr, pgsize, &read, databuf);\r
155                 if (ret || read != pgsize) {\r
156                         pr_err("error: read failed at %#llx, ret: %d read: %d\n",\r
157                                (long long)addr, ret, read);\r
158                         return ret ? ret : -EINVAL;\r
159                 }\r
160 \r
161                 ops.mode      = MTD_OPS_PLACE_OOB;\r
162                 ops.len       = 0;\r
163                 ops.retlen    = 0;\r
164                 ops.ooblen    = mtd->oobsize;\r
165                 ops.oobretlen = 0;\r
166                 ops.ooboffs   = 0;\r
167                 ops.datbuf    = NULL;\r
168                 ops.oobbuf    = oobbuf;\r
169                 ret = mtd_read_oob(mtd, addr, &ops);\r
170                 if (ret || ops.oobretlen != mtd->oobsize) {\r
171                         pr_err("error: read oob failed at "\r
172                                           "%#llx, ret: %d oobretlen: %d\n", (long long)addr, ret, ops.oobretlen);\r
173                         return ret ? ret : -EINVAL;\r
174                 }\r
175                 databuf += mtd->writesize;\r
176                 oobbuf += mtd->oobsize;\r
177                 addr += mtd->writesize;\r
178         }\r
179 \r
180         return ret;\r
181 }\r
182 \r
183 static int mtd_test_readtest(void)\r
184 {\r
185         int ret = 0;\r
186         unsigned int i = 0;\r
187         unsigned char *iobuf = NULL, *iobuf1 = NULL;\r
188 \r
189         iobuf = (unsigned char *)kmalloc(mtd->erasesize, GFP_KERNEL);\r
190         iobuf1 = (unsigned char *)kmalloc(mtd->erasesize, GFP_KERNEL);\r
191         if (!iobuf1 || !iobuf) {\r
192                 pr_err("error: cannot allocate enough memory, %d, 0x%.8x, 0x%.8x!\n", mtd->erasesize, (unsigned int)iobuf, (unsigned int)iobuf1);\r
193                 goto out;\r
194         }\r
195 \r
196         pr_info("readtest begin!\n");\r
197         for (i = 0; i < ebcnt; ++i) {\r
198 \r
199                 if (bbt[i])\r
200                         continue;\r
201                 ret = readtest_read_page(i, iobuf, iobuf1);\r
202                 if (ret) {\r
203                         pr_err("read block %d failed!\n", i);\r
204                         mtd_test_dump_buf(iobuf, mtd->erasesize, 32);\r
205                         mtd_test_dump_buf(iobuf1, mtd->oobsize, 32);\r
206                         goto out;\r
207                 }\r
208                 cond_resched();\r
209         }\r
210 \r
211         pr_info("readtest finished successfully!\n");\r
212 out:\r
213         kfree(iobuf);\r
214         kfree(iobuf1);\r
215         return ret;\r
216 }\r
217 \r
218 static int pagetest_write_eraseblock(int ebnum)\r
219 {\r
220         int err = 0;\r
221         size_t written = 0;\r
222         loff_t addr = ebnum * mtd->erasesize;\r
223 \r
224         prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);\r
225         cond_resched();\r
226         err = mtd_write(mtd, addr, mtd->erasesize, &written, writebuf);\r
227         if (err || written != mtd->erasesize) {\r
228                 pr_err("%s, write failed at %#llx\n", __func__, (long long)addr);\r
229                 return err ? err : -EINVAL;\r
230         }\r
231 \r
232         return err;\r
233 }\r
234 \r
235 static int pagetest_verify_eraseblock(int ebnum)\r
236 {\r
237         int err = 0;\r
238         size_t read = 0;\r
239         uint32_t j = 0, i = 0;\r
240         loff_t addr0 = 0, addrn = 0;\r
241         loff_t addr = ebnum * mtd->erasesize;\r
242 \r
243         for (i = 0; i < ebcnt && bbt[i]; ++i)\r
244                 addr0 += mtd->erasesize;\r
245 \r
246         addrn = mtd->size;\r
247         for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)\r
248                 addrn -= mtd->erasesize;\r
249 \r
250         prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);\r
251         for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) {\r
252                 /* Do a read to set the internal dataRAMs to different data */\r
253                 err = mtd_read(mtd, addr0, bufsize, &read, twopages);\r
254                 if (mtd_is_bitflip(err))\r
255                         err = 0;\r
256                 if (err || read != bufsize) {\r
257                         pr_err("2.1 error: read failed at %#llx\n",\r
258                                (long long)addr0);\r
259                         return err;\r
260                 }\r
261                 err = mtd_read(mtd, addrn - bufsize, bufsize, &read, twopages);\r
262                 if (mtd_is_bitflip(err))\r
263                         err = 0;\r
264                 if (err || read != bufsize) {\r
265                         pr_err("2.2 error: read failed at %#llx\n",\r
266                                (long long)(addrn - bufsize));\r
267                         return err;\r
268                 }\r
269                 memset(twopages, 0, bufsize);\r
270                 err = mtd_read(mtd, addr, bufsize, &read, twopages);\r
271                 if (mtd_is_bitflip(err))\r
272                         err = 0;\r
273                 if (err || read != bufsize) {\r
274                         pr_err("2.3 error: read failed at %#llx\n",\r
275                                (long long)addr);\r
276                         break;\r
277                 }\r
278                 if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) {\r
279                         pr_err("2.4 error: verify failed at %#llx\n",\r
280                                (long long)addr);\r
281                 }\r
282         }\r
283         /* Check boundary between eraseblocks */\r
284         if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) {\r
285                 struct rnd_state old_state = rnd_state;\r
286 \r
287                 /* Do a read to set the internal dataRAMs to different data */\r
288                 err = mtd_read(mtd, addr0, bufsize, &read, twopages);\r
289                 if (mtd_is_bitflip(err))\r
290                         err = 0;\r
291                 if (err || read != bufsize) {\r
292                         pr_err("2.5 error: read failed at %#llx\n",\r
293                                (long long)addr0);\r
294                         return err;\r
295                 }\r
296                 err = mtd_read(mtd, addrn - bufsize, bufsize, &read, twopages);\r
297                 if (mtd_is_bitflip(err))\r
298                         err = 0;\r
299                 if (err || read != bufsize) {\r
300                         pr_err("2.6 error: read failed at %#llx\n",\r
301                                (long long)(addrn - bufsize));\r
302                         return err;\r
303                 }\r
304                 memset(twopages, 0, bufsize);\r
305                 err = mtd_read(mtd, addr, bufsize, &read, twopages);\r
306                 if (mtd_is_bitflip(err))\r
307                         err = 0;\r
308                 if (err || read != bufsize) {\r
309                         pr_err("2.7 error: read failed at %#llx\n",\r
310                                (long long)addr);\r
311                         return err;\r
312                 }\r
313                 memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize);\r
314                 prandom_bytes_state(&rnd_state, boundary + pgsize, pgsize);\r
315                 if (memcmp(twopages, boundary, bufsize)) {\r
316                         pr_err("2.8 error: verify failed at %#llx\n",\r
317                                (long long)addr);\r
318                 }\r
319                 rnd_state = old_state;\r
320         }\r
321         return err;\r
322 }\r
323 \r
324 static int pagetest_crosstest(void)\r
325 {\r
326         int err = 0;\r
327         size_t read = 0;\r
328         unsigned int i = 0;\r
329         loff_t addr = 0, addr0 = 0, addrn = 0;\r
330         unsigned char *pp1 = NULL, *pp2 = NULL, *pp3 = NULL, *pp4 = NULL;\r
331 \r
332 //      pr_info("crosstest\n");\r
333         pp1 = kmalloc(pgsize * 4, GFP_KERNEL);\r
334         if (!pp1) {\r
335                 pr_err("2.9 error: cannot allocate memory\n");\r
336                 return -ENOMEM;\r
337         }\r
338         pp2 = pp1 + pgsize;\r
339         pp3 = pp2 + pgsize;\r
340         pp4 = pp3 + pgsize;\r
341         memset(pp1, 0, pgsize * 4);\r
342 \r
343         addr0 = 0;\r
344         for (i = 0; i < ebcnt && bbt[i]; ++i)\r
345                 addr0 += mtd->erasesize;\r
346 \r
347         addrn = mtd->size;\r
348         for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)\r
349                 addrn -= mtd->erasesize;\r
350 \r
351         /* Read 2nd-to-last page to pp1 */\r
352         addr = addrn - pgsize - pgsize;\r
353         err = mtd_read(mtd, addr, pgsize, &read, pp1);\r
354         if (mtd_is_bitflip(err))\r
355                 err = 0;\r
356         if (err || read != pgsize) {\r
357                 pr_err("2.10 error: read failed at %#llx\n",\r
358                        (long long)addr);\r
359                 kfree(pp1);\r
360                 return err;\r
361         }\r
362 \r
363         /* Read 3rd-to-last page to pp1 */\r
364         addr = addrn - pgsize - pgsize - pgsize;\r
365         err = mtd_read(mtd, addr, pgsize, &read, pp1);\r
366         if (mtd_is_bitflip(err))\r
367                 err = 0;\r
368         if (err || read != pgsize) {\r
369                 pr_err("2.11 error: read failed at %#llx\n",\r
370                        (long long)addr);\r
371                 kfree(pp1);\r
372                 return err;\r
373         }\r
374 \r
375         /* Read first page to pp2 */\r
376         addr = addr0;\r
377 //      pr_info("reading page at %#llx\n", (long long)addr);\r
378         err = mtd_read(mtd, addr, pgsize, &read, pp2);\r
379         if (mtd_is_bitflip(err))\r
380                 err = 0;\r
381         if (err || read != pgsize) {\r
382                 pr_err("2.12 error: read failed at %#llx\n",\r
383                        (long long)addr);\r
384                 kfree(pp1);\r
385                 return err;\r
386         }\r
387 \r
388         /* Read last page to pp3 */\r
389         addr = addrn - pgsize;\r
390 //      pr_info("reading page at %#llx\n", (long long)addr);\r
391         err = mtd_read(mtd, addr, pgsize, &read, pp3);\r
392         if (mtd_is_bitflip(err))\r
393                 err = 0;\r
394         if (err || read != pgsize) {\r
395                 pr_err("2.13 error: read failed at %#llx\n",\r
396                        (long long)addr);\r
397                 kfree(pp1);\r
398                 return err;\r
399         }\r
400 \r
401         /* Read first page again to pp4 */\r
402         addr = addr0;\r
403 //      pr_info("reading page at %#llx\n", (long long)addr);\r
404         err = mtd_read(mtd, addr, pgsize, &read, pp4);\r
405         if (mtd_is_bitflip(err))\r
406                 err = 0;\r
407         if (err || read != pgsize) {\r
408                 pr_err("2.14 error: read failed at %#llx\n",\r
409                        (long long)addr);\r
410                 kfree(pp1);\r
411                 return err;\r
412         }\r
413 \r
414         /* pp2 and pp4 should be the same */\r
415 //      pr_info("verifying pages read at %#llx match\n", (long long)addr0);\r
416         if (memcmp(pp2, pp4, pgsize)) {\r
417                 pr_err("2.15 verify failed!\n");\r
418         }// else if (!err)\r
419 //              pr_info("crosstest ok\n");\r
420         kfree(pp1);\r
421         return err;\r
422 }\r
423 \r
424 static int pagetest_erasecrosstest(void)\r
425 {\r
426         int err = 0;\r
427         loff_t addr0 = 0;\r
428         char *readbuf = twopages;\r
429         size_t read = 0, written = 0;\r
430         unsigned int i = 0, ebnum = 0, ebnum2 = 0;\r
431 \r
432 //      pr_info("erasecrosstest\n");\r
433 \r
434         ebnum = 0;\r
435         addr0 = 0;\r
436         for (i = 0; i < ebcnt && bbt[i]; ++i) {\r
437                 addr0 += mtd->erasesize;\r
438                 ebnum += 1;\r
439         }\r
440 \r
441         ebnum2 = ebcnt - 1;\r
442         while (ebnum2 && bbt[ebnum2])\r
443                 ebnum2 -= 1;\r
444 \r
445 //      pr_info("erasing block %d\n", ebnum);\r
446         err = mtd_test_erase_eraseblock(ebnum, 0);\r
447         if (err)\r
448                 return err;\r
449 \r
450 //      pr_info("writing 1st page of block %d\n", ebnum);\r
451         prandom_bytes_state(&rnd_state, writebuf, pgsize);\r
452         strcpy(writebuf, "There is no data like this!");\r
453         err = mtd_write(mtd, addr0, pgsize, &written, writebuf);\r
454         if (err || written != pgsize) {\r
455                 pr_err("2.16 error: write failed at %#llx\n",\r
456                        (long long)addr0);\r
457                 return err ? err : -EINVAL;\r
458         }\r
459 \r
460 //      pr_info("reading 1st page of block %d\n", ebnum);\r
461         memset(readbuf, 0, pgsize);\r
462         err = mtd_read(mtd, addr0, pgsize, &read, readbuf);\r
463         if (mtd_is_bitflip(err))\r
464                 err = 0;\r
465         if (err || read != pgsize) {\r
466                 pr_err("2.17 error: read failed at %#llx\n",\r
467                        (long long)addr0);\r
468                 return err ? err : -EINVAL;\r
469         }\r
470 \r
471 //      pr_info("verifying 1st page of block %d\n", ebnum);\r
472         if (memcmp(writebuf, readbuf, pgsize)) {\r
473                 pr_err("2.18 verify failed!\n");\r
474                 return -1;\r
475         }\r
476 \r
477 //      pr_info("erasing block %d\n", ebnum);\r
478         err = mtd_test_erase_eraseblock(ebnum, 0);\r
479         if (err)\r
480                 return err;\r
481 \r
482 //      pr_info("writing 1st page of block %d\n", ebnum);\r
483         prandom_bytes_state(&rnd_state, writebuf, pgsize);\r
484         strcpy(writebuf, "There is no data like this!");\r
485         err = mtd_write(mtd, addr0, pgsize, &written, writebuf);\r
486         if (err || written != pgsize) {\r
487                 pr_err("2.19 error: write failed at %#llx\n",\r
488                        (long long)addr0);\r
489                 return err ? err : -EINVAL;\r
490         }\r
491 \r
492 //      pr_info("erasing block %d\n", ebnum2);\r
493         err = mtd_test_erase_eraseblock(ebnum2, 0);\r
494         if (err)\r
495                 return err;\r
496 \r
497 //      pr_info("reading 1st page of block %d\n", ebnum);\r
498         memset(readbuf, 0, pgsize);\r
499         err = mtd_read(mtd, addr0, pgsize, &read, readbuf);\r
500         if (mtd_is_bitflip(err))\r
501                 err = 0;\r
502         if (err || read != pgsize) {\r
503                 pr_err("2.20 error: read failed at %#llx\n",\r
504                        (long long)addr0);\r
505                 return err ? err : -EINVAL;\r
506         }\r
507 \r
508 //      pr_info("verifying 1st page of block %d\n", ebnum);\r
509         if (memcmp(writebuf, readbuf, pgsize)) {\r
510                 pr_err("2.21 verify failed!\n");\r
511                 return -1;\r
512         }\r
513 \r
514 //      if (!err)\r
515 //              pr_info("erasecrosstest ok\n");\r
516         return err;\r
517 }\r
518 \r
519 static int pagetest_erasetest(void)\r
520 {\r
521         int err = 0;\r
522         loff_t addr0 = 0;\r
523         size_t read = 0, written = 0;\r
524         unsigned int i = 0, ebnum = 0, ok = 1;\r
525 \r
526 //      pr_info("erasetest\n");\r
527 \r
528         ebnum = 0;\r
529         addr0 = 0;\r
530         for (i = 0; i < ebcnt && bbt[i]; ++i) {\r
531                 addr0 += mtd->erasesize;\r
532                 ebnum += 1;\r
533         }\r
534 \r
535 //      pr_info("erasing block %d\n", ebnum);\r
536         err = mtd_test_erase_eraseblock(ebnum, 0);\r
537         if (err)\r
538                 return err;\r
539 \r
540 //      pr_info("writing 1st page of block %d\n", ebnum);\r
541         prandom_bytes_state(&rnd_state, writebuf, pgsize);\r
542         err = mtd_write(mtd, addr0, pgsize, &written, writebuf);\r
543         if (err || written != pgsize) {\r
544                 pr_err("2.22 error: write failed at %#llx\n",\r
545                        (long long)addr0);\r
546                 return err ? err : -EINVAL;\r
547         }\r
548 \r
549 //      pr_info("erasing block %d\n", ebnum);\r
550         err = mtd_test_erase_eraseblock(ebnum, 0);\r
551         if (err)\r
552                 return err;\r
553 \r
554 //      pr_info("reading 1st page of block %d\n", ebnum);\r
555         err = mtd_read(mtd, addr0, pgsize, &read, twopages);\r
556         if (mtd_is_bitflip(err))\r
557                 err = 0;\r
558         if (err || read != pgsize) {\r
559                 pr_err("2.23 error: read failed at %#llx\n",\r
560                        (long long)addr0);\r
561                 return err ? err : -EINVAL;\r
562         }\r
563 \r
564 //      pr_info("verifying 1st page of block %d is all 0xff\n", ebnum);\r
565         for (i = 0; i < pgsize; ++i)\r
566                 if (twopages[i] != 0xff) {\r
567                         pr_err("2.24 verifying all 0xff failed at %d\n",\r
568                                i);\r
569                         ok = 0;\r
570                         break;\r
571                 }\r
572 \r
573 //      if (ok && !err)\r
574 //              pr_info("erasetest ok\n");\r
575 \r
576         return err;\r
577 }\r
578 \r
579 static int mtd_test_pagetest(void)\r
580 {\r
581         int err = 0;\r
582         unsigned int i = 0;\r
583 \r
584         bufsize = mtd->writesize * 2;\r
585         writebuf = kzalloc(mtd->erasesize, GFP_KERNEL);\r
586         if (!writebuf) {\r
587                 pr_err("error: alloc writebuf  failed!\n");\r
588                 err = -ENOMEM;\r
589                 goto out;\r
590         }\r
591         twopages = kzalloc(bufsize, GFP_KERNEL);\r
592         if (!twopages) {\r
593                 pr_err("error: alloc twopages failed!\n");\r
594                 err = -ENOMEM;\r
595                 goto out;\r
596         }\r
597         boundary = kzalloc(bufsize, GFP_KERNEL);\r
598         if (!boundary) {\r
599                 pr_err("error: alloc boundary failed!\n");\r
600                 err = -ENOMEM;\r
601                 goto out;\r
602         }\r
603         pr_info("pagetest begin!\n");\r
604 \r
605         err = mtd_test_erase_whole_device();\r
606         if(err)\r
607                 goto out;\r
608 \r
609         prandom_seed_state(&rnd_state, 1);\r
610         for (i = 0; i < ebcnt; ++i) {\r
611                 if (bbt[i])\r
612                         continue;\r
613                 err = pagetest_write_eraseblock(i);\r
614                 if (err)\r
615                         goto out;\r
616                 cond_resched();\r
617         }\r
618 \r
619         prandom_seed_state(&rnd_state, 1);\r
620         for (i = 0; i < ebcnt; ++i) {\r
621                 if (bbt[i])\r
622                         continue;\r
623                 err = pagetest_verify_eraseblock(i);\r
624                 if (err)\r
625                         goto out;\r
626                 cond_resched();\r
627         }\r
628 \r
629         err = pagetest_crosstest();\r
630         if (err)\r
631                 goto out;\r
632 \r
633         err = pagetest_erasecrosstest();\r
634         if (err)\r
635                 goto out;\r
636 \r
637         err = pagetest_erasetest();\r
638         if (err)\r
639                 goto out;\r
640 \r
641         pr_info("pagetest finished successfullly!\n");\r
642 \r
643 out:\r
644         kfree(writebuf);\r
645         kfree(boundary);\r
646         kfree(twopages);\r
647         return err;\r
648 }\r
649 \r
650 static int subpagetest_write_eraseblock(int ebnum)\r
651 {\r
652         int err = 0;\r
653         size_t written = 0;\r
654         loff_t addr = ebnum * mtd->erasesize;\r
655 \r
656         prandom_bytes_state(&rnd_state, writebuf, subpgsize);\r
657         err = mtd_write(mtd, addr, subpgsize, &written, writebuf);\r
658         if (unlikely(err || written != subpgsize)) {\r
659                 pr_err("error: write failed at %#llx, err: %d, written: %d\n",\r
660                        (long long)addr, err, written);\r
661                 return err ? err : -EINVAL;\r
662         }\r
663 \r
664         addr += subpgsize;\r
665         prandom_bytes_state(&rnd_state, writebuf, subpgsize);\r
666         err = mtd_write(mtd, addr, subpgsize, &written, writebuf);\r
667         if (unlikely(err || written != subpgsize)) {\r
668                 pr_err("error: write failed at %#llx, err: %d, written: %d\n",\r
669                        (long long)addr, err, written);\r
670                 return err ? err : -EINVAL;\r
671         }\r
672 \r
673         return err;\r
674 }\r
675 \r
676 static int subpagetest_write_eraseblock2(int ebnum)\r
677 {\r
678         int err = 0;\r
679         size_t written = 0;\r
680         unsigned int k = 0;\r
681         loff_t addr = ebnum * mtd->erasesize;\r
682 \r
683         for (k = 1; k < 33; ++k) {\r
684                 if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)\r
685                         break;\r
686                 prandom_bytes_state(&rnd_state, writebuf, subpgsize * k);\r
687                 err = mtd_write(mtd, addr, subpgsize * k, &written, writebuf);\r
688                 if (unlikely(err || written != subpgsize * k)) {\r
689                         pr_err("error: write failed at %#llx, err: %d, written: %d\n",\r
690                                (long long)addr, err, written);\r
691                         return err ? err : -EINVAL;\r
692                 }\r
693                 addr += subpgsize * k;\r
694         }\r
695 \r
696         return err;\r
697 }\r
698 \r
699 static int subpagetest_verify_eraseblock(int ebnum)\r
700 {\r
701         int err = 0;\r
702         size_t read = 0;\r
703         loff_t addr = ebnum * mtd->erasesize;\r
704 \r
705         prandom_bytes_state(&rnd_state, writebuf, subpgsize);\r
706         memset(readbuf, 0, subpgsize);\r
707         err = mtd_read(mtd, addr, subpgsize, &read, readbuf);\r
708         if (unlikely(err || read != subpgsize)) {\r
709                 if (mtd_is_bitflip(err) && read == subpgsize) {\r
710                         pr_info("ECC correction at %#llx\n",\r
711                                (long long)addr);\r
712                         err = 0;\r
713                 } else {\r
714                         pr_err("error: read failed at %#llx\n",\r
715                                (long long)addr);\r
716                         return err ? err : -EINVAL;\r
717                 }\r
718         }\r
719         if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {\r
720                 pr_err("error: verify failed at %#llx\n",\r
721                        (long long)addr);\r
722                 pr_info("------------- written----------------\n");\r
723                 mtd_test_dump_buf(writebuf, subpgsize, 32);\r
724                 pr_info("------------- read ------------------\n");\r
725                 mtd_test_dump_buf(readbuf, subpgsize, 32);\r
726                 pr_info("-------------------------------------\n");\r
727         }\r
728 \r
729         addr += subpgsize;\r
730 \r
731         prandom_bytes_state(&rnd_state, writebuf, subpgsize);\r
732         memset(readbuf, 0, subpgsize);\r
733         err = mtd_read(mtd, addr, subpgsize, &read, readbuf);\r
734         if (unlikely(err || read != subpgsize)) {\r
735                 if (mtd_is_bitflip(err) && read == subpgsize) {\r
736                         pr_info("ECC correction at %#llx\n",\r
737                                (long long)addr);\r
738                         err = 0;\r
739                 } else {\r
740                         pr_err("error: read failed at %#llx\n",\r
741                                (long long)addr);\r
742                         return err ? err : -EINVAL;\r
743                 }\r
744         }\r
745         if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {\r
746                 pr_info("error: verify failed at %#llx\n",\r
747                        (long long)addr);\r
748                 pr_info("------------- written----------------\n");\r
749                 mtd_test_dump_buf(writebuf, subpgsize, 32);\r
750                 pr_info("------------- read ------------------\n");\r
751                 mtd_test_dump_buf(readbuf, subpgsize, 32);\r
752                 pr_info("-------------------------------------\n");\r
753                 return -1;\r
754         }\r
755 \r
756         return err;\r
757 }\r
758 \r
759 static int subpagetest_verify_eraseblock2(int ebnum)\r
760 {\r
761         int err = 0;\r
762         size_t read = 0;\r
763         unsigned int k = 0;\r
764         loff_t addr = ebnum * mtd->erasesize;\r
765 \r
766         for (k = 1; k < 33; ++k) {\r
767                 if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)\r
768                         break;\r
769                 prandom_bytes_state(&rnd_state, writebuf, subpgsize * k);\r
770                 memset(readbuf, 0, subpgsize * k);\r
771                 err = mtd_read(mtd, addr, subpgsize * k, &read, readbuf);\r
772                 if (unlikely(err || read != subpgsize * k)) {\r
773                         if (mtd_is_bitflip(err) && read == subpgsize * k) {\r
774                                 pr_info("ECC correction at %#llx\n",\r
775                                        (long long)addr);\r
776                                 err = 0;\r
777                         } else {\r
778                                 pr_err("error: read failed at "\r
779                                        "%#llx\n", (long long)addr);\r
780                                 return err ? err : -EINVAL;\r
781                         }\r
782                 }\r
783                 if (unlikely(memcmp(readbuf, writebuf, subpgsize * k))) {\r
784                         pr_err("error: verify failed at %#llx\n",\r
785                                (long long)addr);\r
786                         return -1;\r
787                 }\r
788                 addr += subpgsize * k;\r
789         }\r
790 \r
791         return err;\r
792 }\r
793 \r
794 static int subpagetest_verify_eraseblock_ff(int ebnum)\r
795 {\r
796         int err = 0;\r
797         uint32_t j = 0;\r
798         size_t read = 0;\r
799         loff_t addr = ebnum * mtd->erasesize;\r
800 \r
801         memset(writebuf, 0xff, subpgsize);\r
802         for (j = 0; j < mtd->erasesize / subpgsize; ++j) {\r
803                 memset(readbuf, 0, subpgsize);\r
804                 err = mtd_read(mtd, addr, subpgsize, &read, readbuf);\r
805                 if (unlikely(err || read != subpgsize)) {\r
806                         if (mtd_is_bitflip(err) && read == subpgsize) {\r
807                                 pr_info("ECC correction at %#llx\n",\r
808                                        (long long)addr);\r
809                                 err = 0;\r
810                         } else {\r
811                                 pr_err("error: read failed at "\r
812                                        "%#llx\n", (long long)addr);\r
813                                 return err ? err : -EINVAL;\r
814                         }\r
815                 }\r
816                 if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {\r
817                         pr_err("error: verify 0xff failed at "\r
818                                "%#llx\n", (long long)addr);\r
819                         return -1;\r
820                 }\r
821                 addr += subpgsize;\r
822         }\r
823 \r
824         return err;\r
825 }\r
826 \r
827 static int subpagetest_verify_all_eraseblocks_ff(void)\r
828 {\r
829         int err = 0;\r
830         unsigned int i = 0;\r
831 \r
832 //      pr_info("verifying all eraseblocks for 0xff\n");\r
833         for (i = 0; i < ebcnt; ++i) {\r
834                 if (bbt[i])\r
835                         continue;\r
836                 err = subpagetest_verify_eraseblock_ff(i);\r
837                 if (err)\r
838                         return err;\r
839                 cond_resched();\r
840         }\r
841 //      pr_info("verified %u eraseblocks\n", i);\r
842         return 0;\r
843 }\r
844 \r
845 static int mtd_test_subpagetest(void)\r
846 {\r
847         int err = 0;\r
848         unsigned int i = 0;\r
849 \r
850         writebuf = kmalloc(32 * subpgsize, GFP_KERNEL);\r
851         if (!writebuf) {\r
852                 pr_err("Error: cannot allocate enough memory!\n");\r
853                 err = -ENOMEM;\r
854                 goto out;\r
855         }\r
856         readbuf = kmalloc(32 * subpgsize, GFP_KERNEL);\r
857         if (!readbuf) {\r
858                 pr_err("Error: cannot allocate enough memory!\n");\r
859                 err = -ENOMEM;\r
860                 goto out;\r
861         }\r
862         pr_info("subpagetest begin!\n");\r
863         err = mtd_test_erase_whole_device();\r
864         if (err)\r
865                 goto out;\r
866 \r
867 //      pr_info("writing whole device\n");\r
868         prandom_seed_state(&rnd_state, 1);\r
869         for (i = 0; i < ebcnt; ++i) {\r
870                 if (bbt[i])\r
871                         continue;\r
872                 err = subpagetest_write_eraseblock(i);\r
873                 if (unlikely(err))\r
874                         goto out;\r
875                 cond_resched();\r
876         }\r
877 //      pr_info("written %u eraseblocks\n", i);\r
878 \r
879         prandom_seed_state(&rnd_state, 1);\r
880 //      pr_info("verifying all eraseblocks\n");\r
881         for (i = 0; i < ebcnt; ++i) {\r
882                 if (bbt[i])\r
883                         continue;\r
884                 err = subpagetest_verify_eraseblock(i);\r
885                 if (unlikely(err))\r
886                         goto out;\r
887                 cond_resched();\r
888         }\r
889 //      pr_info("verified %u eraseblocks\n", i);\r
890 \r
891         err = mtd_test_erase_whole_device();\r
892         if (err)\r
893                 goto out;\r
894 \r
895         err = subpagetest_verify_all_eraseblocks_ff();\r
896         if (err)\r
897                 goto out;\r
898 \r
899         /* Write all eraseblocks */\r
900         prandom_seed_state(&rnd_state, 3);\r
901 //      pr_info("writing whole device\n");\r
902         for (i = 0; i < ebcnt; ++i) {\r
903                 if (bbt[i])\r
904                         continue;\r
905                 err = subpagetest_write_eraseblock2(i);\r
906                 if (unlikely(err))\r
907                         goto out;\r
908                 cond_resched();\r
909         }\r
910 //      pr_info("written %u eraseblocks\n", i);\r
911 \r
912         /* Check all eraseblocks */\r
913         prandom_seed_state(&rnd_state, 3);\r
914 //      pr_info("verifying all eraseblocks\n");\r
915         for (i = 0; i < ebcnt; ++i) {\r
916                 if (bbt[i])\r
917                         continue;\r
918                 err = subpagetest_verify_eraseblock2(i);\r
919                 if (unlikely(err))\r
920                         goto out;\r
921                 cond_resched();\r
922         }\r
923 //      pr_info("verified %u eraseblocks\n", i);\r
924 \r
925         err = mtd_test_erase_whole_device();\r
926         if (err)\r
927                 goto out;\r
928 \r
929         err = subpagetest_verify_all_eraseblocks_ff();\r
930         if (err)\r
931                 goto out;\r
932 \r
933         pr_info("subpagetest finished successfully!\n");\r
934 \r
935 out:\r
936         kfree(readbuf);\r
937         kfree(writebuf);\r
938         return err;\r
939 }\r
940 \r
941 static void oobtest_do_vary_offset(void)\r
942 {\r
943         use_len -= 1;\r
944         if (use_len < 1) {\r
945                 use_offset += 1;\r
946                 if (use_offset >= use_len_max)\r
947                         use_offset = 0;\r
948                 use_len = use_len_max - use_offset;\r
949         }\r
950 }\r
951 \r
952 static int oobtest_write_eraseblock(int ebnum)\r
953 {\r
954         int err = 0;\r
955         unsigned int i = 0;\r
956         struct mtd_oob_ops ops;\r
957         loff_t addr = ebnum * mtd->erasesize;\r
958 \r
959         for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {\r
960                 prandom_bytes_state(&rnd_state, writebuf, use_len);\r
961                 ops.mode      = MTD_OPS_AUTO_OOB;\r
962                 ops.len       = 0;\r
963                 ops.retlen    = 0;\r
964                 ops.ooblen    = use_len;\r
965                 ops.oobretlen = 0;\r
966                 ops.ooboffs   = use_offset;\r
967                 ops.datbuf    = NULL;\r
968                 ops.oobbuf    = writebuf;\r
969                 err = mtd_write_oob(mtd, addr, &ops);\r
970                 if (err || ops.oobretlen != use_len) {\r
971                         pr_err("error: writeoob failed at %#llx\n",\r
972                                (long long)addr);\r
973                         pr_err("error: use_len %d, use_offset %d\n",\r
974                                use_len, use_offset);\r
975                         errcnt += 1;\r
976                         return err ? err : -1;\r
977                 }\r
978                 if (vary_offset)\r
979                         oobtest_do_vary_offset();\r
980         }\r
981 \r
982         return err;\r
983 }\r
984 \r
985 static int oobtest_write_whole_device(void)\r
986 {\r
987         int err = 0;\r
988         unsigned int i = 1;\r
989 \r
990 //      pr_info("writing OOBs of whole device\n");\r
991         for (i = 0; i < ebcnt; ++i) {\r
992                 if (bbt[i])\r
993                         continue;\r
994                 err = oobtest_write_eraseblock(i);\r
995                 if (err)\r
996                         return err;\r
997                 cond_resched();\r
998         }\r
999 //      pr_info("written %u eraseblocks\n", i);\r
1000         return 0;\r
1001 }\r
1002 \r
1003 static int oobtest_verify_eraseblock(int ebnum)\r
1004 {\r
1005         int err = 0;\r
1006         unsigned int i = 0;\r
1007         struct mtd_oob_ops ops = {0};\r
1008         loff_t addr = ebnum * mtd->erasesize;\r
1009 \r
1010         for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {\r
1011                 prandom_bytes_state(&rnd_state, writebuf, use_len);\r
1012                 ops.mode      = MTD_OPS_AUTO_OOB;\r
1013                 ops.len       = 0;\r
1014                 ops.retlen    = 0;\r
1015                 ops.ooblen    = use_len;\r
1016                 ops.oobretlen = 0;\r
1017                 ops.ooboffs   = use_offset;\r
1018                 ops.datbuf    = NULL;\r
1019                 ops.oobbuf    = readbuf;\r
1020                 err = mtd_read_oob(mtd, addr, &ops);\r
1021                 if (err || ops.oobretlen != use_len) {\r
1022                         pr_err("error: readoob failed at %#llx\n",\r
1023                                (long long)addr);\r
1024                         errcnt += 1;\r
1025                         return err ? err : -1;\r
1026                 }\r
1027                 if (memcmp(readbuf, writebuf, use_len)) {\r
1028                         pr_err("error: verify failed at %#llx\n",\r
1029                                (long long)addr);\r
1030                         errcnt += 1;\r
1031                         if (errcnt > 1000) {\r
1032                                 pr_err("error: too many errors\n");\r
1033                                 return -1;\r
1034                         }\r
1035                 }\r
1036                 if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) {\r
1037                         int k;\r
1038 \r
1039                         ops.mode      = MTD_OPS_AUTO_OOB;\r
1040                         ops.len       = 0;\r
1041                         ops.retlen    = 0;\r
1042                         ops.ooblen    = mtd->ecclayout->oobavail;\r
1043                         ops.oobretlen = 0;\r
1044                         ops.ooboffs   = 0;\r
1045                         ops.datbuf    = NULL;\r
1046                         ops.oobbuf    = readbuf;\r
1047                         err = mtd_read_oob(mtd, addr, &ops);\r
1048                         if (err || ops.oobretlen != mtd->ecclayout->oobavail) {\r
1049                                 pr_err("error: readoob failed at %#llx\n",\r
1050                                                 (long long)addr);\r
1051                                 errcnt += 1;\r
1052                                 return err ? err : -1;\r
1053                         }\r
1054                         if (memcmp(readbuf + use_offset, writebuf, use_len)) {\r
1055                                 pr_err("error: verify failed at %#llx\n",\r
1056                                                 (long long)addr);\r
1057                                 errcnt += 1;\r
1058                                 if (errcnt > 1000) {\r
1059                                         pr_err("error: too many errors\n");\r
1060                                         return -1;\r
1061                                 }\r
1062                         }\r
1063                         for (k = 0; k < use_offset; ++k)\r
1064                                 if (readbuf[k] != 0xff) {\r
1065                                         pr_err("error: verify 0xff "\r
1066                                                "failed at %#llx\n",\r
1067                                                (long long)addr);\r
1068                                         errcnt += 1;\r
1069                                         if (errcnt > 1000) {\r
1070                                                 pr_err("error: too "\r
1071                                                        "many errors\n");\r
1072                                                 return -1;\r
1073                                         }\r
1074                                 }\r
1075                         for (k = use_offset + use_len;\r
1076                              k < mtd->ecclayout->oobavail; ++k)\r
1077                                 if (readbuf[k] != 0xff) {\r
1078                                         pr_err("error: verify 0xff "\r
1079                                                "failed at %#llx\n",\r
1080                                                (long long)addr);\r
1081                                         errcnt += 1;\r
1082                                         if (errcnt > 1000) {\r
1083                                                 pr_err("error: too "\r
1084                                                        "many errors\n");\r
1085                                                 return -1;\r
1086                                         }\r
1087                                 }\r
1088                 }\r
1089                 if (vary_offset)\r
1090                         oobtest_do_vary_offset();\r
1091         }\r
1092         return err;\r
1093 }\r
1094 \r
1095 /*\r
1096 add by ming.tang\r
1097 adjust the str when mtd->ecclayout->oobavail is not 4bytes alignment\r
1098 @str:the string need to be adjusted\r
1099 @str_len:the string's length\r
1100 @sub_len:mtd->ecclayout->oobavail\r
1101 */\r
1102 static void oobtest_adjust(char *str, unsigned int str_len, unsigned int sub_len)\r
1103 {\r
1104         int i = 0;\r
1105         char *tmp_str = NULL;\r
1106         unsigned int tmp_len = 0;\r
1107 \r
1108         tmp_len = ((sub_len >> 2) + 1) << 2;\r
1109         tmp_str = (char *)vmalloc(str_len);\r
1110         if(!tmp_str) {\r
1111                 pr_err("%s, can't get enough memory!\n", __func__);\r
1112                 return;\r
1113         }\r
1114 \r
1115         memcpy(tmp_str, str, str_len);\r
1116         memset(str, 0, str_len);\r
1117 \r
1118         for(i = 0; i < str_len/tmp_len; i++)\r
1119         {\r
1120                 memcpy(str + (sub_len * i), tmp_str + (tmp_len * i), sub_len);\r
1121         }\r
1122         vfree(tmp_str);\r
1123         return;\r
1124 }\r
1125 \r
1126 static int oobtest_verify_eraseblock_in_one_go(int ebnum)\r
1127 {\r
1128         int err = 0;\r
1129         struct mtd_oob_ops ops = {0};\r
1130         loff_t addr = ebnum * mtd->erasesize;\r
1131         size_t len = mtd->ecclayout->oobavail * pgcnt;\r
1132 \r
1133         prandom_bytes_state(&rnd_state, writebuf, (((mtd->ecclayout->oobavail >> 2) + 1) << 2) * pgcnt);\r
1134         if(mtd->ecclayout->oobavail%4 != 0)\r
1135                 oobtest_adjust(writebuf, (((mtd->ecclayout->oobavail >> 2) + 1) << 2) * pgcnt, mtd->ecclayout->oobavail);\r
1136         ops.mode      = MTD_OPS_AUTO_OOB;\r
1137         ops.len       = 0;\r
1138         ops.retlen    = 0;\r
1139         ops.ooblen    = len;\r
1140         ops.oobretlen = 0;\r
1141         ops.ooboffs   = 0;\r
1142         ops.datbuf    = NULL;\r
1143         ops.oobbuf    = readbuf;\r
1144         err = mtd_read_oob(mtd, addr, &ops);\r
1145         if (err || ops.oobretlen != len) {\r
1146                 pr_err("error: readoob failed at %#llx\n",\r
1147                        (long long)addr);\r
1148                 errcnt += 1;\r
1149                 return err ? err : -1;\r
1150         }\r
1151         if (memcmp(readbuf, writebuf, len)) {\r
1152                 pr_err("error: verify failed at %#llx\n",\r
1153                        (long long)addr);\r
1154                 errcnt += 1;\r
1155                 if (errcnt > 1000) {\r
1156                         pr_err("error: too many errors\n");\r
1157                         return -1;\r
1158                 }\r
1159         }\r
1160 \r
1161         return err;\r
1162 }\r
1163 \r
1164 static int oobtest_verify_all_eraseblocks(void)\r
1165 {\r
1166         int err = 0;\r
1167         unsigned int i = 0;\r
1168 \r
1169 //      pr_info("verifying all eraseblocks\n");\r
1170         for (i = 0; i < ebcnt; ++i) {\r
1171                 if (bbt[i])\r
1172                         continue;\r
1173                 err = oobtest_verify_eraseblock(i);\r
1174                 if (err)\r
1175                         return err;\r
1176                 cond_resched();\r
1177         }\r
1178 //      pr_info("verified %u eraseblocks\n", i);\r
1179         return 0;\r
1180 }\r
1181 \r
1182 static int mtd_test_oobtest(void)\r
1183 {\r
1184         int err = 0;\r
1185         unsigned int i = 0;\r
1186         loff_t addr = 0, addr0 = 0;\r
1187         struct mtd_oob_ops ops = {0};\r
1188 \r
1189         err = -ENOMEM;\r
1190         readbuf = vmalloc(mtd->erasesize);\r
1191         if (!readbuf) {\r
1192                 pr_err("error: alloc readbuf failed!\n");\r
1193                 goto out;\r
1194         }\r
1195         writebuf = vmalloc(mtd->erasesize);\r
1196         if (!writebuf) {\r
1197                 pr_err("error: alloc writebuf failed!\n");\r
1198                 goto out;\r
1199         }\r
1200 \r
1201         use_offset = 0;\r
1202         use_len = mtd->ecclayout->oobavail;\r
1203         use_len_max = mtd->ecclayout->oobavail;\r
1204         vary_offset = 0;\r
1205         pr_info("oobtest begin!\n");\r
1206 \r
1207         /* First test: write all OOB, read it back and verify */\r
1208         pr_info("test 1 of 5\n");\r
1209 \r
1210         err = mtd_test_erase_whole_device();\r
1211         if (err)\r
1212                 goto out;\r
1213 \r
1214         prandom_seed_state(&rnd_state, 1);\r
1215         err = oobtest_write_whole_device();\r
1216         if (err)\r
1217                 goto out;\r
1218 \r
1219         prandom_seed_state(&rnd_state, 1);\r
1220         err = oobtest_verify_all_eraseblocks();\r
1221         if (err)\r
1222                 goto out;\r
1223 \r
1224         /*\r
1225          * Second test: write all OOB, a block at a time, read it back and\r
1226          * verify.\r
1227          */\r
1228         pr_info("test 2 of 5\n");\r
1229 \r
1230         err = mtd_test_erase_whole_device();\r
1231         if (err)\r
1232                 goto out;\r
1233 \r
1234         prandom_seed_state(&rnd_state, 3);\r
1235         err = oobtest_write_whole_device();\r
1236         if (err)\r
1237                 goto out;\r
1238 \r
1239         /* Check all eraseblocks */\r
1240         prandom_seed_state(&rnd_state, 3);\r
1241 //      pr_info("verifying all eraseblocks\n");\r
1242         for (i = 0; i < ebcnt; ++i) {\r
1243                 if (bbt[i])\r
1244                         continue;\r
1245                 err = oobtest_verify_eraseblock_in_one_go(i);\r
1246                 if (err)\r
1247                         goto out;\r
1248                 cond_resched();\r
1249         }\r
1250 //      pr_info("verified %u eraseblocks\n", i);\r
1251 \r
1252         /*\r
1253          * Third test: write OOB at varying offsets and lengths, read it back\r
1254          * and verify.\r
1255          */\r
1256         pr_info("test 3 of 5\n");\r
1257 \r
1258         err = mtd_test_erase_whole_device();\r
1259         if (err)\r
1260                 goto out;\r
1261 \r
1262         /* Write all eraseblocks */\r
1263         use_offset = 0;\r
1264         use_len = mtd->ecclayout->oobavail;\r
1265         use_len_max = mtd->ecclayout->oobavail;\r
1266         vary_offset = 1;\r
1267         prandom_seed_state(&rnd_state, 5);\r
1268 \r
1269         err = oobtest_write_whole_device();\r
1270         if (err)\r
1271                 goto out;\r
1272 \r
1273         /* Check all eraseblocks */\r
1274         use_offset = 0;\r
1275         use_len = mtd->ecclayout->oobavail;\r
1276         use_len_max = mtd->ecclayout->oobavail;\r
1277         vary_offset = 1;\r
1278         prandom_seed_state(&rnd_state, 5);\r
1279         err = oobtest_verify_all_eraseblocks();\r
1280         if (err)\r
1281                 goto out;\r
1282 \r
1283         use_offset = 0;\r
1284         use_len = mtd->ecclayout->oobavail;\r
1285         use_len_max = mtd->ecclayout->oobavail;\r
1286         vary_offset = 0;\r
1287 \r
1288         /* Fourth test: try to write off end of device */\r
1289         pr_info("test 4 of 5\n");\r
1290 \r
1291         err = mtd_test_erase_whole_device();\r
1292         if (err)\r
1293                 goto out;\r
1294 \r
1295         addr0 = 0;\r
1296         for (i = 0; i < ebcnt && bbt[i]; ++i)\r
1297                 addr0 += mtd->erasesize;\r
1298 \r
1299         /* Attempt to write off end of OOB */\r
1300         ops.mode      = MTD_OPS_AUTO_OOB;\r
1301         ops.len       = 0;\r
1302         ops.retlen    = 0;\r
1303         ops.ooblen    = 1;\r
1304         ops.oobretlen = 0;\r
1305         ops.ooboffs   = mtd->ecclayout->oobavail;\r
1306         ops.datbuf    = NULL;\r
1307         ops.oobbuf    = writebuf;\r
1308         pr_info("attempting to start write past end of OOB\n");\r
1309         pr_info("an error is expected...\n");\r
1310         err = mtd_write_oob(mtd, addr0, &ops);\r
1311         if (err) {\r
1312                 pr_info("error occurred as expected\n");\r
1313                 err = 0;\r
1314         } else {\r
1315                 pr_info("error: can write past end of OOB\n");\r
1316                 errcnt += 1;\r
1317         }\r
1318 \r
1319         /* Attempt to read off end of OOB */\r
1320         ops.mode      = MTD_OPS_AUTO_OOB;\r
1321         ops.len       = 0;\r
1322         ops.retlen    = 0;\r
1323         ops.ooblen    = 1;\r
1324         ops.oobretlen = 0;\r
1325         ops.ooboffs   = mtd->ecclayout->oobavail;\r
1326         ops.datbuf    = NULL;\r
1327         ops.oobbuf    = readbuf;\r
1328         pr_info("attempting to start read past end of OOB\n");\r
1329         pr_info("an error is expected...\n");\r
1330         err = mtd_read_oob(mtd, addr0, &ops);\r
1331         if (err) {\r
1332                 pr_info("error occurred as expected\n");\r
1333                 err = 0;\r
1334         } else {\r
1335                 pr_err("error: can read past end of OOB\n");\r
1336                 errcnt += 1;\r
1337         }\r
1338 \r
1339         if (bbt[ebcnt - 1])\r
1340                 pr_info("skipping end of device tests because last "\r
1341                        "block is bad\n");\r
1342         else {\r
1343                 /* Attempt to write off end of device */\r
1344                 ops.mode      = MTD_OPS_AUTO_OOB;\r
1345                 ops.len       = 0;\r
1346                 ops.retlen    = 0;\r
1347                 ops.ooblen    = mtd->ecclayout->oobavail + 1;\r
1348                 ops.oobretlen = 0;\r
1349                 ops.ooboffs   = 0;\r
1350                 ops.datbuf    = NULL;\r
1351                 ops.oobbuf    = writebuf;\r
1352                 pr_info("attempting to write past end of device\n");\r
1353                 pr_info("an error is expected...\n");\r
1354                 err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);\r
1355                 if (err) {\r
1356                         pr_info("error occurred as expected\n");\r
1357                         err = 0;\r
1358                 } else {\r
1359                         pr_err("error: wrote past end of device\n");\r
1360                         errcnt += 1;\r
1361                 }\r
1362 \r
1363                 /* Attempt to read off end of device */\r
1364                 ops.mode      = MTD_OPS_AUTO_OOB;\r
1365                 ops.len       = 0;\r
1366                 ops.retlen    = 0;\r
1367                 ops.ooblen    = mtd->ecclayout->oobavail + 1;\r
1368                 ops.oobretlen = 0;\r
1369                 ops.ooboffs   = 0;\r
1370                 ops.datbuf    = NULL;\r
1371                 ops.oobbuf    = readbuf;\r
1372                 pr_info("attempting to read past end of device\n");\r
1373                 pr_info("an error is expected...\n");\r
1374                 err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);\r
1375                 if (err) {\r
1376                         pr_info("error occurred as expected\n");\r
1377                         err = 0;\r
1378                 } else {\r
1379                         pr_err("error: read past end of device\n");\r
1380                         errcnt += 1;\r
1381                 }\r
1382 \r
1383                 err = mtd_test_erase_eraseblock(ebcnt - 1, 0);\r
1384                 if (err)\r
1385                         goto out;\r
1386 \r
1387                 /* Attempt to write off end of device */\r
1388                 ops.mode      = MTD_OPS_AUTO_OOB;\r
1389                 ops.len       = 0;\r
1390                 ops.retlen    = 0;\r
1391                 ops.ooblen    = mtd->ecclayout->oobavail;\r
1392                 ops.oobretlen = 0;\r
1393                 ops.ooboffs   = 1;\r
1394                 ops.datbuf    = NULL;\r
1395                 ops.oobbuf    = writebuf;\r
1396                 pr_info("attempting to write past end of device\n");\r
1397                 pr_info("an error is expected...\n");\r
1398                 err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);\r
1399                 if (err) {\r
1400                         pr_info("error occurred as expected\n");\r
1401                         err = 0;\r
1402                 } else {\r
1403                         pr_err("error: wrote past end of device\n");\r
1404                         errcnt += 1;\r
1405                 }\r
1406 \r
1407                 /* Attempt to read off end of device */\r
1408                 ops.mode      = MTD_OPS_AUTO_OOB;\r
1409                 ops.len       = 0;\r
1410                 ops.retlen    = 0;\r
1411                 ops.ooblen    = mtd->ecclayout->oobavail;\r
1412                 ops.oobretlen = 0;\r
1413                 ops.ooboffs   = 1;\r
1414                 ops.datbuf    = NULL;\r
1415                 ops.oobbuf    = readbuf;\r
1416                 pr_info("attempting to read past end of device\n");\r
1417                 pr_info("an error is expected...\n");\r
1418                 err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);\r
1419                 if (err) {\r
1420                         pr_info("error occurred as expected\n");\r
1421                         err = 0;\r
1422                 } else {\r
1423                         pr_err("error: read past end of device\n");\r
1424                         errcnt += 1;\r
1425                 }\r
1426         }\r
1427 \r
1428         /* Fifth test: write / read across block boundaries */\r
1429         pr_info("test 5 of 5\n");\r
1430 \r
1431         /* Erase all eraseblocks */\r
1432         err = mtd_test_erase_whole_device();\r
1433         if (err)\r
1434                 goto out;\r
1435 \r
1436         /* Write all eraseblocks */\r
1437         prandom_seed_state(&rnd_state, 11);\r
1438 //      pr_info("writing OOBs of whole device\n");\r
1439         for (i = 0; i < ebcnt - 1; ++i) {\r
1440                 int cnt = 2;\r
1441                 int pg;\r
1442                 size_t sz = mtd->ecclayout->oobavail;\r
1443                 if (bbt[i] || bbt[i + 1])\r
1444                         continue;\r
1445                 addr = (i + 1) * mtd->erasesize - mtd->writesize;\r
1446                 for (pg = 0; pg < cnt; ++pg) {\r
1447                         prandom_bytes_state(&rnd_state, writebuf, sz);\r
1448                         ops.mode      = MTD_OPS_AUTO_OOB;\r
1449                         ops.len       = 0;\r
1450                         ops.retlen    = 0;\r
1451                         ops.ooblen    = sz;\r
1452                         ops.oobretlen = 0;\r
1453                         ops.ooboffs   = 0;\r
1454                         ops.datbuf    = NULL;\r
1455                         ops.oobbuf    = writebuf;\r
1456                         err = mtd_write_oob(mtd, addr, &ops);\r
1457                         if (err)\r
1458                                 goto out;\r
1459                         cond_resched();\r
1460                         addr += mtd->writesize;\r
1461                 }\r
1462         }\r
1463 //      pr_info("written %u eraseblocks\n", i);\r
1464 \r
1465         /* Check all eraseblocks */\r
1466         prandom_seed_state(&rnd_state, 11);\r
1467 //      pr_info("verifying all eraseblocks\n");\r
1468         for (i = 0; i < ebcnt - 1; ++i) {\r
1469                 if (bbt[i] || bbt[i + 1])\r
1470                         continue;\r
1471                 prandom_bytes_state(&rnd_state, writebuf,\r
1472                                         (((mtd->ecclayout->oobavail >> 2) + 1) << 2) * 2);\r
1473                 if(mtd->ecclayout->oobavail%4 != 0)\r
1474                         oobtest_adjust(writebuf, (((mtd->ecclayout->oobavail >> 2) + 1) << 2) * 2, mtd->ecclayout->oobavail);\r
1475                 addr = (i + 1) * mtd->erasesize - mtd->writesize;\r
1476                 ops.mode      = MTD_OPS_AUTO_OOB;\r
1477                 ops.len       = 0;\r
1478                 ops.retlen    = 0;\r
1479                 ops.ooblen    = mtd->ecclayout->oobavail * 2;\r
1480                 ops.oobretlen = 0;\r
1481                 ops.ooboffs   = 0;\r
1482                 ops.datbuf    = NULL;\r
1483                 ops.oobbuf    = readbuf;\r
1484                 err = mtd_read_oob(mtd, addr, &ops);\r
1485                 if (err)\r
1486                         goto out;\r
1487                 if (memcmp(readbuf, writebuf, mtd->ecclayout->oobavail * 2)) {\r
1488                         pr_err("error: verify failed at %#llx\n",\r
1489                                (long long)addr);\r
1490                         errcnt += 1;\r
1491                         if (errcnt > 1000) {\r
1492                                 pr_err("error: too many errors\n");\r
1493                                 goto out;\r
1494                         }\r
1495                 }\r
1496                 cond_resched();\r
1497         }\r
1498 //      pr_info("verified %u eraseblocks\n", i);\r
1499 \r
1500         pr_info("oobtest finished with %d errors!\n", errcnt);\r
1501 out:\r
1502         vfree(writebuf);\r
1503         vfree(readbuf);\r
1504 \r
1505         return err;\r
1506 }\r
1507 \r
1508 static long speedtest_calc_speed(void)\r
1509 {\r
1510         long ms = 0;\r
1511         uint64_t k = 0;\r
1512 \r
1513         ms = (finish.tv_sec - start.tv_sec) * 1000 +\r
1514              (finish.tv_usec - start.tv_usec) / 1000;\r
1515         if (ms == 0)\r
1516                 return 0;\r
1517         k = goodebcnt * (mtd->erasesize / 1024) * 1000;\r
1518         do_div(k, ms);\r
1519         return k;\r
1520 }\r
1521 \r
1522 static int speedtest_write_eraseblock(int ebnum)\r
1523 {\r
1524         int err = 0;\r
1525         size_t written = 0;\r
1526         loff_t addr = ebnum * mtd->erasesize;\r
1527 \r
1528         err = mtd_write(mtd, addr, mtd->erasesize, &written, writebuf);\r
1529         if (err || written != mtd->erasesize) {\r
1530                 pr_err("error: write failed at %#llx\n", addr);\r
1531                 if (!err)\r
1532                         err = -EINVAL;\r
1533         }\r
1534 \r
1535         return err;\r
1536 }\r
1537 \r
1538 static int speedtest_write_eraseblock_by_page(int ebnum)\r
1539 {\r
1540         int err = 0;\r
1541         size_t written = 0;\r
1542         unsigned int i = 0;\r
1543         void *buf = writebuf;\r
1544         loff_t addr = ebnum * mtd->erasesize;\r
1545 \r
1546         for (i = 0; i < pgcnt; i++) {\r
1547                 err = mtd_write(mtd, addr, pgsize, &written, buf);\r
1548                 if (err || written != pgsize) {\r
1549                         pr_err("error: write failed at %#llx\n",\r
1550                                addr);\r
1551                         if (!err)\r
1552                                 err = -EINVAL;\r
1553                         break;\r
1554                 }\r
1555                 addr += pgsize;\r
1556                 buf += pgsize;\r
1557         }\r
1558 \r
1559         return err;\r
1560 }\r
1561 \r
1562 static int speedtest_write_eraseblock_by_2pages(int ebnum)\r
1563 {\r
1564         int err = 0;\r
1565         void *buf = writebuf;\r
1566         unsigned int i = 0, n = pgcnt / 2;\r
1567         size_t written = 0, sz = pgsize * 2;\r
1568         loff_t addr = ebnum * mtd->erasesize;\r
1569 \r
1570         for (i = 0; i < n; i++) {\r
1571                 err = mtd_write(mtd, addr, sz, &written, buf);\r
1572                 if (err || written != sz) {\r
1573                         pr_err("error: write failed at %#llx\n",\r
1574                                addr);\r
1575                         if (!err)\r
1576                                 err = -EINVAL;\r
1577                         return err;\r
1578                 }\r
1579                 addr += sz;\r
1580                 buf += sz;\r
1581         }\r
1582         if (pgcnt % 2) {\r
1583                 err = mtd_write(mtd, addr, pgsize, &written, buf);\r
1584                 if (err || written != pgsize) {\r
1585                         pr_err("error: write failed at %#llx\n",\r
1586                                addr);\r
1587                         if (!err)\r
1588                                 err = -EINVAL;\r
1589                 }\r
1590         }\r
1591 \r
1592         return err;\r
1593 }\r
1594 \r
1595 static int speedtest_read_eraseblock(int ebnum)\r
1596 {\r
1597         int err = 0;\r
1598         size_t read = 0;\r
1599         loff_t addr = ebnum * mtd->erasesize;\r
1600 \r
1601         err = mtd_read(mtd, addr, mtd->erasesize, &read, writebuf);\r
1602         /* Ignore corrected ECC errors */\r
1603         if (mtd_is_bitflip(err))\r
1604                 err = 0;\r
1605         if (err || read != mtd->erasesize) {\r
1606                 pr_err("error: read failed at %#llx\n", addr);\r
1607                 if (!err)\r
1608                         err = -EINVAL;\r
1609         }\r
1610 \r
1611         return err;\r
1612 }\r
1613 \r
1614 static int speedtest_read_eraseblock_by_page(int ebnum)\r
1615 {\r
1616         int err = 0;\r
1617         size_t read = 0;\r
1618         unsigned int i = 0;\r
1619         void *buf = writebuf;\r
1620         loff_t addr = ebnum * mtd->erasesize;\r
1621 \r
1622         for (i = 0; i < pgcnt; i++) {\r
1623                 err = mtd_read(mtd, addr, pgsize, &read, buf);\r
1624                 /* Ignore corrected ECC errors */\r
1625                 if (mtd_is_bitflip(err))\r
1626                         err = 0;\r
1627                 if (err || read != pgsize) {\r
1628                         pr_err("error: read failed at %#llx\n",\r
1629                                addr);\r
1630                         if (!err)\r
1631                                 err = -EINVAL;\r
1632                         break;\r
1633                 }\r
1634                 addr += pgsize;\r
1635                 buf += pgsize;\r
1636         }\r
1637 \r
1638         return err;\r
1639 }\r
1640 \r
1641 static int speedtest_read_eraseblock_by_2pages(int ebnum)\r
1642 {\r
1643         int err = 0;\r
1644         void *buf = writebuf;\r
1645         size_t read = 0, sz = pgsize * 2;\r
1646         unsigned int i = 0, n = pgcnt / 2;\r
1647         loff_t addr = ebnum * mtd->erasesize;\r
1648 \r
1649         for (i = 0; i < n; i++) {\r
1650                 err = mtd_read(mtd, addr, sz, &read, buf);\r
1651                 /* Ignore corrected ECC errors */\r
1652                 if (mtd_is_bitflip(err))\r
1653                         err = 0;\r
1654                 if (err || read != sz) {\r
1655                         pr_err("error: read failed at %#llx\n",\r
1656                                addr);\r
1657                         if (!err)\r
1658                                 err = -EINVAL;\r
1659                         return err;\r
1660                 }\r
1661                 addr += sz;\r
1662                 buf += sz;\r
1663         }\r
1664         if (pgcnt % 2) {\r
1665                 err = mtd_read(mtd, addr, pgsize, &read, buf);\r
1666                 /* Ignore corrected ECC errors */\r
1667                 if (mtd_is_bitflip(err))\r
1668                         err = 0;\r
1669                 if (err || read != pgsize) {\r
1670                         pr_err("error: read failed at %#llx\n",\r
1671                                addr);\r
1672                         if (!err)\r
1673                                 err = -EINVAL;\r
1674                 }\r
1675         }\r
1676 \r
1677         return err;\r
1678 }\r
1679 \r
1680 static int mtd_test_speedtest(void )\r
1681 {\r
1682         int err = 0;\r
1683         long speed = 0;\r
1684         unsigned int i = 0, blocks = 0, j = 0, k = 0;\r
1685 \r
1686         writebuf = vmalloc(mtd->erasesize);\r
1687         if(!writebuf) {\r
1688                 pr_err("%s, can't get enough memory!\n", __func__);\r
1689                 return -ENOMEM;\r
1690         }\r
1691 \r
1692         memset(writebuf, 0, mtd->erasesize);\r
1693         prandom_bytes(writebuf, mtd->erasesize);\r
1694 \r
1695         pr_info("speedtest begin!\n");\r
1696         err = mtd_test_erase_whole_device();\r
1697         if (err)\r
1698                 goto out;\r
1699 \r
1700         /* Write all eraseblocks, 1 eraseblock at a time */\r
1701 //      pr_info("testing eraseblock write speed\n");\r
1702         mtd_test_start_timing();\r
1703         for (i = 0; i < ebcnt; ++i) {\r
1704                 if (bbt[i])\r
1705                         continue;\r
1706                 err = speedtest_write_eraseblock(i);\r
1707                 if (err)\r
1708                         goto out;\r
1709                 cond_resched();\r
1710         }\r
1711         mtd_test_stop_timing();\r
1712         speed = speedtest_calc_speed();\r
1713         pr_info("eraseblock write speed is %ld KiB/s\n", speed);\r
1714 \r
1715         /* Read all eraseblocks, 1 eraseblock at a time */\r
1716 //      pr_info("testing eraseblock read speed\n");\r
1717         mtd_test_start_timing();\r
1718         for (i = 0; i < ebcnt; ++i) {\r
1719                 if (bbt[i])\r
1720                         continue;\r
1721                 err = speedtest_read_eraseblock(i);\r
1722                 if (err)\r
1723                         goto out;\r
1724                 cond_resched();\r
1725         }\r
1726         mtd_test_stop_timing();\r
1727         speed = speedtest_calc_speed();\r
1728         pr_info("eraseblock read speed is %ld KiB/s\n", speed);\r
1729 \r
1730         err = mtd_test_erase_whole_device();\r
1731         if (err)\r
1732                 goto out;\r
1733 \r
1734         /* Write all eraseblocks, 1 page at a time */\r
1735 //      pr_info("testing page write speed\n");\r
1736         mtd_test_start_timing();\r
1737         for (i = 0; i < ebcnt; ++i) {\r
1738                 if (bbt[i])\r
1739                         continue;\r
1740                 err = speedtest_write_eraseblock_by_page(i);\r
1741                 if (err)\r
1742                         goto out;\r
1743                 cond_resched();\r
1744         }\r
1745         mtd_test_stop_timing();\r
1746         speed = speedtest_calc_speed();\r
1747         pr_info("page write speed is %ld KiB/s\n", speed);\r
1748 \r
1749         /* Read all eraseblocks, 1 page at a time */\r
1750 //      pr_info("testing page read speed\n");\r
1751         mtd_test_start_timing();\r
1752         for (i = 0; i < ebcnt; ++i) {\r
1753                 if (bbt[i])\r
1754                         continue;\r
1755                 err = speedtest_read_eraseblock_by_page(i);\r
1756                 if (err)\r
1757                         goto out;\r
1758                 cond_resched();\r
1759         }\r
1760         mtd_test_stop_timing();\r
1761         speed = speedtest_calc_speed();\r
1762         pr_info("page read speed is %ld KiB/s\n", speed);\r
1763 \r
1764         err = mtd_test_erase_whole_device();\r
1765         if (err)\r
1766                 goto out;\r
1767 \r
1768         /* Write all eraseblocks, 2 pages at a time */\r
1769 //      pr_info("testing 2 page write speed\n");\r
1770         mtd_test_start_timing();\r
1771         for (i = 0; i < ebcnt; ++i) {\r
1772                 if (bbt[i])\r
1773                         continue;\r
1774                 err = speedtest_write_eraseblock_by_2pages(i);\r
1775                 if (err)\r
1776                         goto out;\r
1777                 cond_resched();\r
1778         }\r
1779         mtd_test_stop_timing();\r
1780         speed = speedtest_calc_speed();\r
1781         pr_info("2 page write speed is %ld KiB/s\n", speed);\r
1782 \r
1783         /* Read all eraseblocks, 2 pages at a time */\r
1784 //      pr_info("testing 2 page read speed\n");\r
1785         mtd_test_start_timing();\r
1786         for (i = 0; i < ebcnt; ++i) {\r
1787                 if (bbt[i])\r
1788                         continue;\r
1789                 err = speedtest_read_eraseblock_by_2pages(i);\r
1790                 if (err)\r
1791                         goto out;\r
1792                 cond_resched();\r
1793         }\r
1794         mtd_test_stop_timing();\r
1795         speed = speedtest_calc_speed();\r
1796         pr_info("2 page read speed is %ld KiB/s\n", speed);\r
1797 \r
1798         /* Erase all eraseblocks */\r
1799 //      pr_info("Testing erase speed\n");\r
1800         mtd_test_start_timing();\r
1801         for (i = 0; i < ebcnt; ++i) {\r
1802                 if (bbt[i])\r
1803                         continue;\r
1804                 err = mtd_test_erase_eraseblock(i, 0);\r
1805                 if (err)\r
1806                         goto out;\r
1807                 cond_resched();\r
1808         }\r
1809         mtd_test_stop_timing();\r
1810         speed = speedtest_calc_speed();\r
1811         pr_info("erase speed is %ld KiB/s\n", speed);\r
1812 \r
1813         /* Multi-block erase all eraseblocks */\r
1814         for (k = 1; k < 7; k++) {\r
1815                 blocks = 1 << k;\r
1816 //              pr_info("Testing %dx multi-block erase speed\n", blocks);\r
1817                 mtd_test_start_timing();\r
1818                 for (i = 0; i < ebcnt; ) {\r
1819                         for (j = 0; j < blocks && (i + j) < ebcnt; j++)\r
1820                                 if (bbt[i + j])\r
1821                                         break;\r
1822                         if (j < 1) {\r
1823                                 i++;\r
1824                                 continue;\r
1825                         }\r
1826                         err = mtd_test_erase_eraseblock(i, j);\r
1827                         if (err)\r
1828                                 goto out;\r
1829                         cond_resched();\r
1830                         i += j;\r
1831                 }\r
1832                 mtd_test_stop_timing();\r
1833                 speed = speedtest_calc_speed();\r
1834                 pr_info("%dx multi-block erase speed is %ld KiB/s\n",\r
1835                        blocks, speed);\r
1836         }\r
1837         pr_info("speedtest finished successfully!\n");\r
1838 \r
1839 out:\r
1840         vfree(writebuf);\r
1841         return err;\r
1842 }\r
1843 \r
1844 static int stresstest_rand_eb(void)\r
1845 {\r
1846         unsigned int eb = 0;\r
1847 \r
1848 again:\r
1849         eb = prandom_u32();\r
1850         /* Read or write up 2 eraseblocks at a time - hence 'ebcnt - 1' */\r
1851         eb %= (ebcnt - 1);\r
1852         if (bbt[eb])\r
1853                 goto again;\r
1854         return eb;\r
1855 }\r
1856 \r
1857 static int stresstest_rand_offs(void)\r
1858 {\r
1859         unsigned int offs = 0;\r
1860 \r
1861         offs = prandom_u32();\r
1862         offs %= bufsize;\r
1863         return offs;\r
1864 }\r
1865 \r
1866 static int stresstest_rand_len(int offs)\r
1867 {\r
1868         unsigned int len = 0;\r
1869 \r
1870         len = prandom_u32();\r
1871         len %= (bufsize - offs);\r
1872         return len;\r
1873 }\r
1874 \r
1875 static int stresstest_do_read(void)\r
1876 {\r
1877         int err = 0;\r
1878         size_t read = 0;\r
1879         loff_t addr = 0;\r
1880         int eb = stresstest_rand_eb();\r
1881         int offs = stresstest_rand_offs();\r
1882         int len = stresstest_rand_len(offs);\r
1883 \r
1884         if (bbt[eb + 1]) {\r
1885                 if (offs >= mtd->erasesize)\r
1886                         offs -= mtd->erasesize;\r
1887                 if (offs + len > mtd->erasesize)\r
1888                         len = mtd->erasesize - offs;\r
1889         }\r
1890         addr = eb * mtd->erasesize + offs;\r
1891         err = mtd_read(mtd, addr, len, &read, readbuf);\r
1892         if (mtd_is_bitflip(err))\r
1893                 err = 0;\r
1894         if (unlikely(err || read != len)) {\r
1895                 pr_err("error: read failed at 0x%llx, err:%d len: %dread:%d\n",\r
1896                        (long long)addr, err, len, read);\r
1897                 if (!err)\r
1898                         err = -EINVAL;\r
1899                 return err;\r
1900         }\r
1901         return 0;\r
1902 }\r
1903 \r
1904 static int stresstest_do_write(void)\r
1905 {\r
1906         int err = 0;\r
1907         loff_t addr = 0;\r
1908         size_t written = 0;\r
1909         int eb = stresstest_rand_eb();\r
1910         unsigned int offs = 0, len = 0;\r
1911 \r
1912         offs = offsets[eb];\r
1913         if (offs >= mtd->erasesize) {\r
1914                 err = mtd_test_erase_eraseblock(eb, 0);\r
1915                 if (err)\r
1916                         return err;\r
1917                 offs = offsets[eb] = 0;\r
1918         }\r
1919         len = stresstest_rand_len(offs);\r
1920         len = ((len + pgsize - 1) / pgsize) * pgsize;\r
1921         if (offs + len > mtd->erasesize) {\r
1922                 if (bbt[eb + 1])\r
1923                         len = mtd->erasesize - offs;\r
1924                 else {\r
1925                         err = mtd_test_erase_eraseblock(eb + 1, 0);\r
1926                         if (err)\r
1927                                 return err;\r
1928                         offsets[eb + 1] = 0;\r
1929                 }\r
1930         }\r
1931         addr = eb * mtd->erasesize + offs;\r
1932         err = mtd_write(mtd, addr, len, &written, writebuf);\r
1933         if (unlikely(err || written != len)) {\r
1934                 pr_err("error: write failed at 0x%llx\n",\r
1935                        (long long)addr);\r
1936                 if (!err)\r
1937                         err = -EINVAL;\r
1938                 return err;\r
1939         }\r
1940         offs += len;\r
1941         while (offs > mtd->erasesize) {\r
1942                 offsets[eb++] = mtd->erasesize;\r
1943                 offs -= mtd->erasesize;\r
1944         }\r
1945         offsets[eb] = offs;\r
1946         return 0;\r
1947 }\r
1948 \r
1949 static int stresstest_do_operation(void)\r
1950 {\r
1951         if (prandom_u32() & 1) {\r
1952                 return stresstest_do_read();\r
1953         } else {\r
1954                 return stresstest_do_write();\r
1955         }\r
1956 }\r
1957 \r
1958 static int mtd_test_stresstest(void)\r
1959 {\r
1960         int err = 0;\r
1961         unsigned int i = 0, op = 0;\r
1962 \r
1963         bufsize = mtd->erasesize * 2;\r
1964         readbuf = vmalloc(bufsize);\r
1965         if(!readbuf) {\r
1966                 pr_err("%s, alloc readbuf failed!\n", __func__);\r
1967                 return -ENOMEM;\r
1968         }\r
1969         writebuf = vmalloc(bufsize);\r
1970         if(!writebuf) {\r
1971                 pr_err("%s, alloc writebuf failed!\n", __func__);\r
1972                 vfree(readbuf);\r
1973                 return -ENOMEM;\r
1974         }\r
1975         offsets = vmalloc(ebcnt * sizeof(int));\r
1976         if(!offsets) {\r
1977                 pr_err("%s, alloc offsets failed!\n", __func__);\r
1978                 vfree(readbuf);\r
1979                 vfree(writebuf);\r
1980                 return -ENOMEM;\r
1981         }\r
1982         pr_info("stresstest begin!\n");\r
1983 \r
1984         for (i = 0; i < ebcnt; i++)\r
1985                 offsets[i] = mtd->erasesize;\r
1986         prandom_bytes(writebuf, bufsize);\r
1987 \r
1988         err = mtd_test_erase_whole_device();\r
1989         if(err)\r
1990                 goto out;\r
1991 \r
1992         for (op = 0; op < 10000; op++) {\r
1993                 if ((op & 1023) == 0)\r
1994                         pr_info("%d operations done\n", op);\r
1995                 err = stresstest_do_operation();\r
1996                 if (err)\r
1997                         goto out;\r
1998                 cond_resched();\r
1999         }\r
2000 \r
2001 out:\r
2002         vfree(offsets);\r
2003         vfree(readbuf);\r
2004         vfree(writebuf);\r
2005         pr_info("stresstest finished, %d operations done!\n", op);\r
2006         return err;\r
2007 }\r
2008 \r
2009 static int __init nandflash_stdtest_init(void)\r
2010 {\r
2011         int err = 0;\r
2012         uint64_t tmp = 0;\r
2013 \r
2014         pr_info(KERN_INFO "\n");\r
2015         pr_info(KERN_INFO "=================================================\n");\r
2016 \r
2017         if (dev < 0) {\r
2018                 pr_info("Please specify a valid mtd-device via module parameter\n");\r
2019                 return -EINVAL;\r
2020         }\r
2021 \r
2022         pr_info("MTD device: %d\n", dev);\r
2023 \r
2024         mtd = get_mtd_device(NULL, dev);\r
2025         if (IS_ERR(mtd)) {\r
2026                 err = PTR_ERR(mtd);\r
2027                 pr_info("error: cannot get MTD device\n");\r
2028                 return err;\r
2029         }\r
2030 \r
2031         if (mtd->type != MTD_NANDFLASH) {\r
2032                 pr_info("this test requires NAND flash\n");\r
2033                 goto out;\r
2034         }\r
2035 \r
2036         tmp = mtd->size;\r
2037         do_div(tmp, mtd->erasesize);\r
2038         ebcnt = tmp;\r
2039         pgcnt = mtd->erasesize / mtd->writesize;\r
2040         pgsize = mtd->writesize;\r
2041         subsize  = mtd->writesize >> mtd->subpage_sft;\r
2042         subcount = mtd->writesize / subsize;\r
2043         subpgsize = mtd->writesize >> mtd->subpage_sft;\r
2044 \r
2045         pr_info("MTD device size %llu, eraseblock size %u, "\r
2046                "page size %u, count of eraseblocks %u, pages per "\r
2047                "eraseblock %u, OOB size %u\n",\r
2048                (unsigned long long)mtd->size, mtd->erasesize,\r
2049                mtd->writesize, ebcnt, pgcnt, mtd->oobsize);\r
2050 \r
2051         err = mtd_test_scan_bad_block();\r
2052         if (err)\r
2053                 goto out;\r
2054 \r
2055         err = mtd_test_readtest();\r
2056         if(err) {\r
2057                 pr_err("readtest failed!\n");\r
2058                 goto out;\r
2059         }\r
2060         mdelay(100);\r
2061         err = mtd_test_pagetest();\r
2062         if(err) {\r
2063                 pr_err("pagetest failed!\n");\r
2064                 goto out;\r
2065         }\r
2066         mdelay(100);\r
2067         err = mtd_test_subpagetest();\r
2068         if(err) {\r
2069                 pr_err("subpagetest failed!\n");\r
2070                 goto out;\r
2071         }\r
2072         mdelay(100);\r
2073         err = mtd_test_oobtest();\r
2074         if(err) {\r
2075                 pr_err("oobtest failed!\n");\r
2076                 goto out;\r
2077         }\r
2078         mdelay(100);\r
2079         err = mtd_test_speedtest();\r
2080         if(err) {\r
2081                 pr_err("speedtest failed!\n");\r
2082                 goto out;\r
2083         }\r
2084         mdelay(100);\r
2085         err = mtd_test_stresstest();\r
2086         if(err) {\r
2087                 pr_err("stresstest failed!\n");\r
2088                 goto out;\r
2089         }\r
2090 \r
2091 out:\r
2092         pr_info(KERN_INFO "=================================================\n");\r
2093         if(bbt != NULL)\r
2094                 vfree(bbt);\r
2095         put_mtd_device(mtd);\r
2096 \r
2097         return -1;\r
2098 }\r
2099 \r
2100 static void __exit nandflash_stdtest_exit(void)\r
2101 {\r
2102         return;\r
2103 }\r
2104 \r
2105 module_init(nandflash_stdtest_init);\r
2106 module_exit(nandflash_stdtest_exit);\r
2107 \r
2108 MODULE_DESCRIPTION("mtd_stdand_test");\r
2109 MODULE_AUTHOR("ming.tang@spreadtrum.com");\r
2110 MODULE_LICENSE("GPL");\r