Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2006-2008 Nokia Corporation
0004  *
0005  * Test OOB read and write on MTD device.
0006  *
0007  * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
0008  */
0009 
0010 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0011 
0012 #include <asm/div64.h>
0013 #include <linux/init.h>
0014 #include <linux/module.h>
0015 #include <linux/moduleparam.h>
0016 #include <linux/err.h>
0017 #include <linux/mtd/mtd.h>
0018 #include <linux/slab.h>
0019 #include <linux/sched.h>
0020 #include <linux/random.h>
0021 
0022 #include "mtd_test.h"
0023 
0024 static int dev = -EINVAL;
0025 static int bitflip_limit;
0026 module_param(dev, int, S_IRUGO);
0027 MODULE_PARM_DESC(dev, "MTD device number to use");
0028 module_param(bitflip_limit, int, S_IRUGO);
0029 MODULE_PARM_DESC(bitflip_limit, "Max. allowed bitflips per page");
0030 
0031 static struct mtd_info *mtd;
0032 static unsigned char *readbuf;
0033 static unsigned char *writebuf;
0034 static unsigned char *bbt;
0035 
0036 static int ebcnt;
0037 static int pgcnt;
0038 static int errcnt;
0039 static int use_offset;
0040 static int use_len;
0041 static int use_len_max;
0042 static int vary_offset;
0043 static struct rnd_state rnd_state;
0044 
0045 static void do_vary_offset(void)
0046 {
0047     use_len -= 1;
0048     if (use_len < 1) {
0049         use_offset += 1;
0050         if (use_offset >= use_len_max)
0051             use_offset = 0;
0052         use_len = use_len_max - use_offset;
0053     }
0054 }
0055 
0056 static int write_eraseblock(int ebnum)
0057 {
0058     int i;
0059     struct mtd_oob_ops ops;
0060     int err = 0;
0061     loff_t addr = (loff_t)ebnum * mtd->erasesize;
0062 
0063     prandom_bytes_state(&rnd_state, writebuf, use_len_max * pgcnt);
0064     for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
0065         ops.mode      = MTD_OPS_AUTO_OOB;
0066         ops.len       = 0;
0067         ops.retlen    = 0;
0068         ops.ooblen    = use_len;
0069         ops.oobretlen = 0;
0070         ops.ooboffs   = use_offset;
0071         ops.datbuf    = NULL;
0072         ops.oobbuf    = writebuf + (use_len_max * i) + use_offset;
0073         err = mtd_write_oob(mtd, addr, &ops);
0074         if (err || ops.oobretlen != use_len) {
0075             pr_err("error: writeoob failed at %#llx\n",
0076                    (long long)addr);
0077             pr_err("error: use_len %d, use_offset %d\n",
0078                    use_len, use_offset);
0079             errcnt += 1;
0080             return err ? err : -1;
0081         }
0082         if (vary_offset)
0083             do_vary_offset();
0084     }
0085 
0086     return err;
0087 }
0088 
0089 static int write_whole_device(void)
0090 {
0091     int err;
0092     unsigned int i;
0093 
0094     pr_info("writing OOBs of whole device\n");
0095     for (i = 0; i < ebcnt; ++i) {
0096         if (bbt[i])
0097             continue;
0098         err = write_eraseblock(i);
0099         if (err)
0100             return err;
0101         if (i % 256 == 0)
0102             pr_info("written up to eraseblock %u\n", i);
0103 
0104         err = mtdtest_relax();
0105         if (err)
0106             return err;
0107     }
0108     pr_info("written %u eraseblocks\n", i);
0109     return 0;
0110 }
0111 
0112 /*
0113  * Display the address, offset and data bytes at comparison failure.
0114  * Return number of bitflips encountered.
0115  */
0116 static size_t memcmpshowoffset(loff_t addr, loff_t offset, const void *cs,
0117                    const void *ct, size_t count)
0118 {
0119     const unsigned char *su1, *su2;
0120     int res;
0121     size_t i = 0;
0122     size_t bitflips = 0;
0123 
0124     for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--, i++) {
0125         res = *su1 ^ *su2;
0126         if (res) {
0127             pr_info("error @addr[0x%lx:0x%lx] 0x%x -> 0x%x diff 0x%x\n",
0128                 (unsigned long)addr, (unsigned long)offset + i,
0129                 *su1, *su2, res);
0130             bitflips += hweight8(res);
0131         }
0132     }
0133 
0134     return bitflips;
0135 }
0136 
0137 #define memcmpshow(addr, cs, ct, count) memcmpshowoffset((addr), 0, (cs), (ct),\
0138                              (count))
0139 
0140 /*
0141  * Compare with 0xff and show the address, offset and data bytes at
0142  * comparison failure. Return number of bitflips encountered.
0143  */
0144 static size_t memffshow(loff_t addr, loff_t offset, const void *cs,
0145             size_t count)
0146 {
0147     const unsigned char *su1;
0148     int res;
0149     size_t i = 0;
0150     size_t bitflips = 0;
0151 
0152     for (su1 = cs; 0 < count; ++su1, count--, i++) {
0153         res = *su1 ^ 0xff;
0154         if (res) {
0155             pr_info("error @addr[0x%lx:0x%lx] 0x%x -> 0xff diff 0x%x\n",
0156                 (unsigned long)addr, (unsigned long)offset + i,
0157                 *su1, res);
0158             bitflips += hweight8(res);
0159         }
0160     }
0161 
0162     return bitflips;
0163 }
0164 
0165 static int verify_eraseblock(int ebnum)
0166 {
0167     int i;
0168     struct mtd_oob_ops ops;
0169     int err = 0;
0170     loff_t addr = (loff_t)ebnum * mtd->erasesize;
0171     size_t bitflips;
0172 
0173     prandom_bytes_state(&rnd_state, writebuf, use_len_max * pgcnt);
0174     for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
0175         ops.mode      = MTD_OPS_AUTO_OOB;
0176         ops.len       = 0;
0177         ops.retlen    = 0;
0178         ops.ooblen    = use_len;
0179         ops.oobretlen = 0;
0180         ops.ooboffs   = use_offset;
0181         ops.datbuf    = NULL;
0182         ops.oobbuf    = readbuf;
0183         err = mtd_read_oob(mtd, addr, &ops);
0184         if (mtd_is_bitflip(err))
0185             err = 0;
0186 
0187         if (err || ops.oobretlen != use_len) {
0188             pr_err("error: readoob failed at %#llx\n",
0189                    (long long)addr);
0190             errcnt += 1;
0191             return err ? err : -1;
0192         }
0193 
0194         bitflips = memcmpshow(addr, readbuf,
0195                       writebuf + (use_len_max * i) + use_offset,
0196                       use_len);
0197         if (bitflips > bitflip_limit) {
0198             pr_err("error: verify failed at %#llx\n",
0199                    (long long)addr);
0200             errcnt += 1;
0201             if (errcnt > 1000) {
0202                 pr_err("error: too many errors\n");
0203                 return -1;
0204             }
0205         } else if (bitflips) {
0206             pr_info("ignoring error as within bitflip_limit\n");
0207         }
0208 
0209         if (use_offset != 0 || use_len < mtd->oobavail) {
0210             int k;
0211 
0212             ops.mode      = MTD_OPS_AUTO_OOB;
0213             ops.len       = 0;
0214             ops.retlen    = 0;
0215             ops.ooblen    = mtd->oobavail;
0216             ops.oobretlen = 0;
0217             ops.ooboffs   = 0;
0218             ops.datbuf    = NULL;
0219             ops.oobbuf    = readbuf;
0220             err = mtd_read_oob(mtd, addr, &ops);
0221             if (mtd_is_bitflip(err))
0222                 err = 0;
0223 
0224             if (err || ops.oobretlen != mtd->oobavail) {
0225                 pr_err("error: readoob failed at %#llx\n",
0226                         (long long)addr);
0227                 errcnt += 1;
0228                 return err ? err : -1;
0229             }
0230             bitflips = memcmpshowoffset(addr, use_offset,
0231                             readbuf + use_offset,
0232                             writebuf + (use_len_max * i) + use_offset,
0233                             use_len);
0234 
0235             /* verify pre-offset area for 0xff */
0236             bitflips += memffshow(addr, 0, readbuf, use_offset);
0237 
0238             /* verify post-(use_offset + use_len) area for 0xff */
0239             k = use_offset + use_len;
0240             bitflips += memffshow(addr, k, readbuf + k,
0241                           mtd->oobavail - k);
0242 
0243             if (bitflips > bitflip_limit) {
0244                 pr_err("error: verify failed at %#llx\n",
0245                         (long long)addr);
0246                 errcnt += 1;
0247                 if (errcnt > 1000) {
0248                     pr_err("error: too many errors\n");
0249                     return -1;
0250                 }
0251             } else if (bitflips) {
0252                 pr_info("ignoring errors as within bitflip limit\n");
0253             }
0254         }
0255         if (vary_offset)
0256             do_vary_offset();
0257     }
0258     return err;
0259 }
0260 
0261 static int verify_eraseblock_in_one_go(int ebnum)
0262 {
0263     struct mtd_oob_ops ops;
0264     int err = 0;
0265     loff_t addr = (loff_t)ebnum * mtd->erasesize;
0266     size_t len = mtd->oobavail * pgcnt;
0267     size_t oobavail = mtd->oobavail;
0268     size_t bitflips;
0269     int i;
0270 
0271     prandom_bytes_state(&rnd_state, writebuf, len);
0272     ops.mode      = MTD_OPS_AUTO_OOB;
0273     ops.len       = 0;
0274     ops.retlen    = 0;
0275     ops.ooblen    = len;
0276     ops.oobretlen = 0;
0277     ops.ooboffs   = 0;
0278     ops.datbuf    = NULL;
0279     ops.oobbuf    = readbuf;
0280 
0281     /* read entire block's OOB at one go */
0282     err = mtd_read_oob(mtd, addr, &ops);
0283     if (mtd_is_bitflip(err))
0284         err = 0;
0285 
0286     if (err || ops.oobretlen != len) {
0287         pr_err("error: readoob failed at %#llx\n",
0288                (long long)addr);
0289         errcnt += 1;
0290         return err ? err : -1;
0291     }
0292 
0293     /* verify one page OOB at a time for bitflip per page limit check */
0294     for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
0295         bitflips = memcmpshow(addr, readbuf + (i * oobavail),
0296                       writebuf + (i * oobavail), oobavail);
0297         if (bitflips > bitflip_limit) {
0298             pr_err("error: verify failed at %#llx\n",
0299                    (long long)addr);
0300             errcnt += 1;
0301             if (errcnt > 1000) {
0302                 pr_err("error: too many errors\n");
0303                 return -1;
0304             }
0305         } else if (bitflips) {
0306             pr_info("ignoring error as within bitflip_limit\n");
0307         }
0308     }
0309 
0310     return err;
0311 }
0312 
0313 static int verify_all_eraseblocks(void)
0314 {
0315     int err;
0316     unsigned int i;
0317 
0318     pr_info("verifying all eraseblocks\n");
0319     for (i = 0; i < ebcnt; ++i) {
0320         if (bbt[i])
0321             continue;
0322         err = verify_eraseblock(i);
0323         if (err)
0324             return err;
0325         if (i % 256 == 0)
0326             pr_info("verified up to eraseblock %u\n", i);
0327 
0328         err = mtdtest_relax();
0329         if (err)
0330             return err;
0331     }
0332     pr_info("verified %u eraseblocks\n", i);
0333     return 0;
0334 }
0335 
0336 static int __init mtd_oobtest_init(void)
0337 {
0338     int err = 0;
0339     unsigned int i;
0340     uint64_t tmp;
0341     struct mtd_oob_ops ops;
0342     loff_t addr = 0, addr0;
0343 
0344     printk(KERN_INFO "\n");
0345     printk(KERN_INFO "=================================================\n");
0346 
0347     if (dev < 0) {
0348         pr_info("Please specify a valid mtd-device via module parameter\n");
0349         pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
0350         return -EINVAL;
0351     }
0352 
0353     pr_info("MTD device: %d\n", dev);
0354 
0355     mtd = get_mtd_device(NULL, dev);
0356     if (IS_ERR(mtd)) {
0357         err = PTR_ERR(mtd);
0358         pr_err("error: cannot get MTD device\n");
0359         return err;
0360     }
0361 
0362     if (!mtd_type_is_nand(mtd)) {
0363         pr_info("this test requires NAND flash\n");
0364         goto out;
0365     }
0366 
0367     tmp = mtd->size;
0368     do_div(tmp, mtd->erasesize);
0369     ebcnt = tmp;
0370     pgcnt = mtd->erasesize / mtd->writesize;
0371 
0372     pr_info("MTD device size %llu, eraseblock size %u, "
0373            "page size %u, count of eraseblocks %u, pages per "
0374            "eraseblock %u, OOB size %u\n",
0375            (unsigned long long)mtd->size, mtd->erasesize,
0376            mtd->writesize, ebcnt, pgcnt, mtd->oobsize);
0377 
0378     err = -ENOMEM;
0379     readbuf = kmalloc(mtd->erasesize, GFP_KERNEL);
0380     if (!readbuf)
0381         goto out;
0382     writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
0383     if (!writebuf)
0384         goto out;
0385     bbt = kzalloc(ebcnt, GFP_KERNEL);
0386     if (!bbt)
0387         goto out;
0388 
0389     err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
0390     if (err)
0391         goto out;
0392 
0393     use_offset = 0;
0394     use_len = mtd->oobavail;
0395     use_len_max = mtd->oobavail;
0396     vary_offset = 0;
0397 
0398     /* First test: write all OOB, read it back and verify */
0399     pr_info("test 1 of 5\n");
0400 
0401     err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
0402     if (err)
0403         goto out;
0404 
0405     prandom_seed_state(&rnd_state, 1);
0406     err = write_whole_device();
0407     if (err)
0408         goto out;
0409 
0410     prandom_seed_state(&rnd_state, 1);
0411     err = verify_all_eraseblocks();
0412     if (err)
0413         goto out;
0414 
0415     /*
0416      * Second test: write all OOB, a block at a time, read it back and
0417      * verify.
0418      */
0419     pr_info("test 2 of 5\n");
0420 
0421     err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
0422     if (err)
0423         goto out;
0424 
0425     prandom_seed_state(&rnd_state, 3);
0426     err = write_whole_device();
0427     if (err)
0428         goto out;
0429 
0430     /* Check all eraseblocks */
0431     prandom_seed_state(&rnd_state, 3);
0432     pr_info("verifying all eraseblocks\n");
0433     for (i = 0; i < ebcnt; ++i) {
0434         if (bbt[i])
0435             continue;
0436         err = verify_eraseblock_in_one_go(i);
0437         if (err)
0438             goto out;
0439         if (i % 256 == 0)
0440             pr_info("verified up to eraseblock %u\n", i);
0441 
0442         err = mtdtest_relax();
0443         if (err)
0444             goto out;
0445     }
0446     pr_info("verified %u eraseblocks\n", i);
0447 
0448     /*
0449      * Third test: write OOB at varying offsets and lengths, read it back
0450      * and verify.
0451      */
0452     pr_info("test 3 of 5\n");
0453 
0454     err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
0455     if (err)
0456         goto out;
0457 
0458     /* Write all eraseblocks */
0459     use_offset = 0;
0460     use_len = mtd->oobavail;
0461     use_len_max = mtd->oobavail;
0462     vary_offset = 1;
0463     prandom_seed_state(&rnd_state, 5);
0464 
0465     err = write_whole_device();
0466     if (err)
0467         goto out;
0468 
0469     /* Check all eraseblocks */
0470     use_offset = 0;
0471     use_len = mtd->oobavail;
0472     use_len_max = mtd->oobavail;
0473     vary_offset = 1;
0474     prandom_seed_state(&rnd_state, 5);
0475     err = verify_all_eraseblocks();
0476     if (err)
0477         goto out;
0478 
0479     use_offset = 0;
0480     use_len = mtd->oobavail;
0481     use_len_max = mtd->oobavail;
0482     vary_offset = 0;
0483 
0484     /* Fourth test: try to write off end of device */
0485     pr_info("test 4 of 5\n");
0486 
0487     err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
0488     if (err)
0489         goto out;
0490 
0491     addr0 = 0;
0492     for (i = 0; i < ebcnt && bbt[i]; ++i)
0493         addr0 += mtd->erasesize;
0494 
0495     /* Attempt to write off end of OOB */
0496     ops.mode      = MTD_OPS_AUTO_OOB;
0497     ops.len       = 0;
0498     ops.retlen    = 0;
0499     ops.ooblen    = 1;
0500     ops.oobretlen = 0;
0501     ops.ooboffs   = mtd->oobavail;
0502     ops.datbuf    = NULL;
0503     ops.oobbuf    = writebuf;
0504     pr_info("attempting to start write past end of OOB\n");
0505     pr_info("an error is expected...\n");
0506     err = mtd_write_oob(mtd, addr0, &ops);
0507     if (err) {
0508         pr_info("error occurred as expected\n");
0509     } else {
0510         pr_err("error: can write past end of OOB\n");
0511         errcnt += 1;
0512     }
0513 
0514     /* Attempt to read off end of OOB */
0515     ops.mode      = MTD_OPS_AUTO_OOB;
0516     ops.len       = 0;
0517     ops.retlen    = 0;
0518     ops.ooblen    = 1;
0519     ops.oobretlen = 0;
0520     ops.ooboffs   = mtd->oobavail;
0521     ops.datbuf    = NULL;
0522     ops.oobbuf    = readbuf;
0523     pr_info("attempting to start read past end of OOB\n");
0524     pr_info("an error is expected...\n");
0525     err = mtd_read_oob(mtd, addr0, &ops);
0526     if (mtd_is_bitflip(err))
0527         err = 0;
0528 
0529     if (err) {
0530         pr_info("error occurred as expected\n");
0531     } else {
0532         pr_err("error: can read past end of OOB\n");
0533         errcnt += 1;
0534     }
0535 
0536     if (bbt[ebcnt - 1])
0537         pr_info("skipping end of device tests because last "
0538                "block is bad\n");
0539     else {
0540         /* Attempt to write off end of device */
0541         ops.mode      = MTD_OPS_AUTO_OOB;
0542         ops.len       = 0;
0543         ops.retlen    = 0;
0544         ops.ooblen    = mtd->oobavail + 1;
0545         ops.oobretlen = 0;
0546         ops.ooboffs   = 0;
0547         ops.datbuf    = NULL;
0548         ops.oobbuf    = writebuf;
0549         pr_info("attempting to write past end of device\n");
0550         pr_info("an error is expected...\n");
0551         err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
0552         if (err) {
0553             pr_info("error occurred as expected\n");
0554         } else {
0555             pr_err("error: wrote past end of device\n");
0556             errcnt += 1;
0557         }
0558 
0559         /* Attempt to read off end of device */
0560         ops.mode      = MTD_OPS_AUTO_OOB;
0561         ops.len       = 0;
0562         ops.retlen    = 0;
0563         ops.ooblen    = mtd->oobavail + 1;
0564         ops.oobretlen = 0;
0565         ops.ooboffs   = 0;
0566         ops.datbuf    = NULL;
0567         ops.oobbuf    = readbuf;
0568         pr_info("attempting to read past end of device\n");
0569         pr_info("an error is expected...\n");
0570         err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
0571         if (mtd_is_bitflip(err))
0572             err = 0;
0573 
0574         if (err) {
0575             pr_info("error occurred as expected\n");
0576         } else {
0577             pr_err("error: read past end of device\n");
0578             errcnt += 1;
0579         }
0580 
0581         err = mtdtest_erase_eraseblock(mtd, ebcnt - 1);
0582         if (err)
0583             goto out;
0584 
0585         /* Attempt to write off end of device */
0586         ops.mode      = MTD_OPS_AUTO_OOB;
0587         ops.len       = 0;
0588         ops.retlen    = 0;
0589         ops.ooblen    = mtd->oobavail;
0590         ops.oobretlen = 0;
0591         ops.ooboffs   = 1;
0592         ops.datbuf    = NULL;
0593         ops.oobbuf    = writebuf;
0594         pr_info("attempting to write past end of device\n");
0595         pr_info("an error is expected...\n");
0596         err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
0597         if (err) {
0598             pr_info("error occurred as expected\n");
0599         } else {
0600             pr_err("error: wrote past end of device\n");
0601             errcnt += 1;
0602         }
0603 
0604         /* Attempt to read off end of device */
0605         ops.mode      = MTD_OPS_AUTO_OOB;
0606         ops.len       = 0;
0607         ops.retlen    = 0;
0608         ops.ooblen    = mtd->oobavail;
0609         ops.oobretlen = 0;
0610         ops.ooboffs   = 1;
0611         ops.datbuf    = NULL;
0612         ops.oobbuf    = readbuf;
0613         pr_info("attempting to read past end of device\n");
0614         pr_info("an error is expected...\n");
0615         err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
0616         if (mtd_is_bitflip(err))
0617             err = 0;
0618 
0619         if (err) {
0620             pr_info("error occurred as expected\n");
0621         } else {
0622             pr_err("error: read past end of device\n");
0623             errcnt += 1;
0624         }
0625     }
0626 
0627     /* Fifth test: write / read across block boundaries */
0628     pr_info("test 5 of 5\n");
0629 
0630     /* Erase all eraseblocks */
0631     err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
0632     if (err)
0633         goto out;
0634 
0635     /* Write all eraseblocks */
0636     prandom_seed_state(&rnd_state, 11);
0637     pr_info("writing OOBs of whole device\n");
0638     for (i = 0; i < ebcnt - 1; ++i) {
0639         int cnt = 2;
0640         int pg;
0641         size_t sz = mtd->oobavail;
0642         if (bbt[i] || bbt[i + 1])
0643             continue;
0644         addr = (loff_t)(i + 1) * mtd->erasesize - mtd->writesize;
0645         prandom_bytes_state(&rnd_state, writebuf, sz * cnt);
0646         for (pg = 0; pg < cnt; ++pg) {
0647             ops.mode      = MTD_OPS_AUTO_OOB;
0648             ops.len       = 0;
0649             ops.retlen    = 0;
0650             ops.ooblen    = sz;
0651             ops.oobretlen = 0;
0652             ops.ooboffs   = 0;
0653             ops.datbuf    = NULL;
0654             ops.oobbuf    = writebuf + pg * sz;
0655             err = mtd_write_oob(mtd, addr, &ops);
0656             if (err)
0657                 goto out;
0658             if (i % 256 == 0)
0659                 pr_info("written up to eraseblock %u\n", i);
0660 
0661             err = mtdtest_relax();
0662             if (err)
0663                 goto out;
0664 
0665             addr += mtd->writesize;
0666         }
0667     }
0668     pr_info("written %u eraseblocks\n", i);
0669 
0670     /* Check all eraseblocks */
0671     prandom_seed_state(&rnd_state, 11);
0672     pr_info("verifying all eraseblocks\n");
0673     for (i = 0; i < ebcnt - 1; ++i) {
0674         if (bbt[i] || bbt[i + 1])
0675             continue;
0676         prandom_bytes_state(&rnd_state, writebuf, mtd->oobavail * 2);
0677         addr = (loff_t)(i + 1) * mtd->erasesize - mtd->writesize;
0678         ops.mode      = MTD_OPS_AUTO_OOB;
0679         ops.len       = 0;
0680         ops.retlen    = 0;
0681         ops.ooblen    = mtd->oobavail * 2;
0682         ops.oobretlen = 0;
0683         ops.ooboffs   = 0;
0684         ops.datbuf    = NULL;
0685         ops.oobbuf    = readbuf;
0686         err = mtd_read_oob(mtd, addr, &ops);
0687         if (mtd_is_bitflip(err))
0688             err = 0;
0689 
0690         if (err)
0691             goto out;
0692         if (memcmpshow(addr, readbuf, writebuf,
0693                    mtd->oobavail * 2)) {
0694             pr_err("error: verify failed at %#llx\n",
0695                    (long long)addr);
0696             errcnt += 1;
0697             if (errcnt > 1000) {
0698                 err = -EINVAL;
0699                 pr_err("error: too many errors\n");
0700                 goto out;
0701             }
0702         }
0703         if (i % 256 == 0)
0704             pr_info("verified up to eraseblock %u\n", i);
0705 
0706         err = mtdtest_relax();
0707         if (err)
0708             goto out;
0709     }
0710     pr_info("verified %u eraseblocks\n", i);
0711 
0712     pr_info("finished with %d errors\n", errcnt);
0713 out:
0714     kfree(bbt);
0715     kfree(writebuf);
0716     kfree(readbuf);
0717     put_mtd_device(mtd);
0718     if (err)
0719         pr_info("error %d occurred\n", err);
0720     printk(KERN_INFO "=================================================\n");
0721     return err;
0722 }
0723 module_init(mtd_oobtest_init);
0724 
0725 static void __exit mtd_oobtest_exit(void)
0726 {
0727     return;
0728 }
0729 module_exit(mtd_oobtest_exit);
0730 
0731 MODULE_DESCRIPTION("Out-of-band test module");
0732 MODULE_AUTHOR("Adrian Hunter");
0733 MODULE_LICENSE("GPL");