root/drivers/mtd/tests/oobtest.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. do_vary_offset
  2. write_eraseblock
  3. write_whole_device
  4. memcmpshowoffset
  5. memffshow
  6. verify_eraseblock
  7. verify_eraseblock_in_one_go
  8. verify_all_eraseblocks
  9. mtd_oobtest_init
  10. mtd_oobtest_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2006-2008 Nokia Corporation
   4  *
   5  * Test OOB read and write on MTD device.
   6  *
   7  * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
   8  */
   9 
  10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  11 
  12 #include <asm/div64.h>
  13 #include <linux/init.h>
  14 #include <linux/module.h>
  15 #include <linux/moduleparam.h>
  16 #include <linux/err.h>
  17 #include <linux/mtd/mtd.h>
  18 #include <linux/slab.h>
  19 #include <linux/sched.h>
  20 #include <linux/random.h>
  21 
  22 #include "mtd_test.h"
  23 
  24 static int dev = -EINVAL;
  25 static int bitflip_limit;
  26 module_param(dev, int, S_IRUGO);
  27 MODULE_PARM_DESC(dev, "MTD device number to use");
  28 module_param(bitflip_limit, int, S_IRUGO);
  29 MODULE_PARM_DESC(bitflip_limit, "Max. allowed bitflips per page");
  30 
  31 static struct mtd_info *mtd;
  32 static unsigned char *readbuf;
  33 static unsigned char *writebuf;
  34 static unsigned char *bbt;
  35 
  36 static int ebcnt;
  37 static int pgcnt;
  38 static int errcnt;
  39 static int use_offset;
  40 static int use_len;
  41 static int use_len_max;
  42 static int vary_offset;
  43 static struct rnd_state rnd_state;
  44 
  45 static void do_vary_offset(void)
  46 {
  47         use_len -= 1;
  48         if (use_len < 1) {
  49                 use_offset += 1;
  50                 if (use_offset >= use_len_max)
  51                         use_offset = 0;
  52                 use_len = use_len_max - use_offset;
  53         }
  54 }
  55 
  56 static int write_eraseblock(int ebnum)
  57 {
  58         int i;
  59         struct mtd_oob_ops ops;
  60         int err = 0;
  61         loff_t addr = (loff_t)ebnum * mtd->erasesize;
  62 
  63         prandom_bytes_state(&rnd_state, writebuf, use_len_max * pgcnt);
  64         for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
  65                 ops.mode      = MTD_OPS_AUTO_OOB;
  66                 ops.len       = 0;
  67                 ops.retlen    = 0;
  68                 ops.ooblen    = use_len;
  69                 ops.oobretlen = 0;
  70                 ops.ooboffs   = use_offset;
  71                 ops.datbuf    = NULL;
  72                 ops.oobbuf    = writebuf + (use_len_max * i) + use_offset;
  73                 err = mtd_write_oob(mtd, addr, &ops);
  74                 if (err || ops.oobretlen != use_len) {
  75                         pr_err("error: writeoob failed at %#llx\n",
  76                                (long long)addr);
  77                         pr_err("error: use_len %d, use_offset %d\n",
  78                                use_len, use_offset);
  79                         errcnt += 1;
  80                         return err ? err : -1;
  81                 }
  82                 if (vary_offset)
  83                         do_vary_offset();
  84         }
  85 
  86         return err;
  87 }
  88 
  89 static int write_whole_device(void)
  90 {
  91         int err;
  92         unsigned int i;
  93 
  94         pr_info("writing OOBs of whole device\n");
  95         for (i = 0; i < ebcnt; ++i) {
  96                 if (bbt[i])
  97                         continue;
  98                 err = write_eraseblock(i);
  99                 if (err)
 100                         return err;
 101                 if (i % 256 == 0)
 102                         pr_info("written up to eraseblock %u\n", i);
 103 
 104                 err = mtdtest_relax();
 105                 if (err)
 106                         return err;
 107         }
 108         pr_info("written %u eraseblocks\n", i);
 109         return 0;
 110 }
 111 
 112 /*
 113  * Display the address, offset and data bytes at comparison failure.
 114  * Return number of bitflips encountered.
 115  */
 116 static size_t memcmpshowoffset(loff_t addr, loff_t offset, const void *cs,
 117                                const void *ct, size_t count)
 118 {
 119         const unsigned char *su1, *su2;
 120         int res;
 121         size_t i = 0;
 122         size_t bitflips = 0;
 123 
 124         for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--, i++) {
 125                 res = *su1 ^ *su2;
 126                 if (res) {
 127                         pr_info("error @addr[0x%lx:0x%lx] 0x%x -> 0x%x diff 0x%x\n",
 128                                 (unsigned long)addr, (unsigned long)offset + i,
 129                                 *su1, *su2, res);
 130                         bitflips += hweight8(res);
 131                 }
 132         }
 133 
 134         return bitflips;
 135 }
 136 
 137 #define memcmpshow(addr, cs, ct, count) memcmpshowoffset((addr), 0, (cs), (ct),\
 138                                                          (count))
 139 
 140 /*
 141  * Compare with 0xff and show the address, offset and data bytes at
 142  * comparison failure. Return number of bitflips encountered.
 143  */
 144 static size_t memffshow(loff_t addr, loff_t offset, const void *cs,
 145                         size_t count)
 146 {
 147         const unsigned char *su1;
 148         int res;
 149         size_t i = 0;
 150         size_t bitflips = 0;
 151 
 152         for (su1 = cs; 0 < count; ++su1, count--, i++) {
 153                 res = *su1 ^ 0xff;
 154                 if (res) {
 155                         pr_info("error @addr[0x%lx:0x%lx] 0x%x -> 0xff diff 0x%x\n",
 156                                 (unsigned long)addr, (unsigned long)offset + i,
 157                                 *su1, res);
 158                         bitflips += hweight8(res);
 159                 }
 160         }
 161 
 162         return bitflips;
 163 }
 164 
 165 static int verify_eraseblock(int ebnum)
 166 {
 167         int i;
 168         struct mtd_oob_ops ops;
 169         int err = 0;
 170         loff_t addr = (loff_t)ebnum * mtd->erasesize;
 171         size_t bitflips;
 172 
 173         prandom_bytes_state(&rnd_state, writebuf, use_len_max * pgcnt);
 174         for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
 175                 ops.mode      = MTD_OPS_AUTO_OOB;
 176                 ops.len       = 0;
 177                 ops.retlen    = 0;
 178                 ops.ooblen    = use_len;
 179                 ops.oobretlen = 0;
 180                 ops.ooboffs   = use_offset;
 181                 ops.datbuf    = NULL;
 182                 ops.oobbuf    = readbuf;
 183                 err = mtd_read_oob(mtd, addr, &ops);
 184                 if (mtd_is_bitflip(err))
 185                         err = 0;
 186 
 187                 if (err || ops.oobretlen != use_len) {
 188                         pr_err("error: readoob failed at %#llx\n",
 189                                (long long)addr);
 190                         errcnt += 1;
 191                         return err ? err : -1;
 192                 }
 193 
 194                 bitflips = memcmpshow(addr, readbuf,
 195                                       writebuf + (use_len_max * i) + use_offset,
 196                                       use_len);
 197                 if (bitflips > bitflip_limit) {
 198                         pr_err("error: verify failed at %#llx\n",
 199                                (long long)addr);
 200                         errcnt += 1;
 201                         if (errcnt > 1000) {
 202                                 pr_err("error: too many errors\n");
 203                                 return -1;
 204                         }
 205                 } else if (bitflips) {
 206                         pr_info("ignoring error as within bitflip_limit\n");
 207                 }
 208 
 209                 if (use_offset != 0 || use_len < mtd->oobavail) {
 210                         int k;
 211 
 212                         ops.mode      = MTD_OPS_AUTO_OOB;
 213                         ops.len       = 0;
 214                         ops.retlen    = 0;
 215                         ops.ooblen    = mtd->oobavail;
 216                         ops.oobretlen = 0;
 217                         ops.ooboffs   = 0;
 218                         ops.datbuf    = NULL;
 219                         ops.oobbuf    = readbuf;
 220                         err = mtd_read_oob(mtd, addr, &ops);
 221                         if (mtd_is_bitflip(err))
 222                                 err = 0;
 223 
 224                         if (err || ops.oobretlen != mtd->oobavail) {
 225                                 pr_err("error: readoob failed at %#llx\n",
 226                                                 (long long)addr);
 227                                 errcnt += 1;
 228                                 return err ? err : -1;
 229                         }
 230                         bitflips = memcmpshowoffset(addr, use_offset,
 231                                                     readbuf + use_offset,
 232                                                     writebuf + (use_len_max * i) + use_offset,
 233                                                     use_len);
 234 
 235                         /* verify pre-offset area for 0xff */
 236                         bitflips += memffshow(addr, 0, readbuf, use_offset);
 237 
 238                         /* verify post-(use_offset + use_len) area for 0xff */
 239                         k = use_offset + use_len;
 240                         bitflips += memffshow(addr, k, readbuf + k,
 241                                               mtd->oobavail - k);
 242 
 243                         if (bitflips > bitflip_limit) {
 244                                 pr_err("error: verify failed at %#llx\n",
 245                                                 (long long)addr);
 246                                 errcnt += 1;
 247                                 if (errcnt > 1000) {
 248                                         pr_err("error: too many errors\n");
 249                                         return -1;
 250                                 }
 251                         } else if (bitflips) {
 252                                 pr_info("ignoring errors as within bitflip limit\n");
 253                         }
 254                 }
 255                 if (vary_offset)
 256                         do_vary_offset();
 257         }
 258         return err;
 259 }
 260 
 261 static int verify_eraseblock_in_one_go(int ebnum)
 262 {
 263         struct mtd_oob_ops ops;
 264         int err = 0;
 265         loff_t addr = (loff_t)ebnum * mtd->erasesize;
 266         size_t len = mtd->oobavail * pgcnt;
 267         size_t oobavail = mtd->oobavail;
 268         size_t bitflips;
 269         int i;
 270 
 271         prandom_bytes_state(&rnd_state, writebuf, len);
 272         ops.mode      = MTD_OPS_AUTO_OOB;
 273         ops.len       = 0;
 274         ops.retlen    = 0;
 275         ops.ooblen    = len;
 276         ops.oobretlen = 0;
 277         ops.ooboffs   = 0;
 278         ops.datbuf    = NULL;
 279         ops.oobbuf    = readbuf;
 280 
 281         /* read entire block's OOB at one go */
 282         err = mtd_read_oob(mtd, addr, &ops);
 283         if (mtd_is_bitflip(err))
 284                 err = 0;
 285 
 286         if (err || ops.oobretlen != len) {
 287                 pr_err("error: readoob failed at %#llx\n",
 288                        (long long)addr);
 289                 errcnt += 1;
 290                 return err ? err : -1;
 291         }
 292 
 293         /* verify one page OOB at a time for bitflip per page limit check */
 294         for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
 295                 bitflips = memcmpshow(addr, readbuf + (i * oobavail),
 296                                       writebuf + (i * oobavail), oobavail);
 297                 if (bitflips > bitflip_limit) {
 298                         pr_err("error: verify failed at %#llx\n",
 299                                (long long)addr);
 300                         errcnt += 1;
 301                         if (errcnt > 1000) {
 302                                 pr_err("error: too many errors\n");
 303                                 return -1;
 304                         }
 305                 } else if (bitflips) {
 306                         pr_info("ignoring error as within bitflip_limit\n");
 307                 }
 308         }
 309 
 310         return err;
 311 }
 312 
 313 static int verify_all_eraseblocks(void)
 314 {
 315         int err;
 316         unsigned int i;
 317 
 318         pr_info("verifying all eraseblocks\n");
 319         for (i = 0; i < ebcnt; ++i) {
 320                 if (bbt[i])
 321                         continue;
 322                 err = verify_eraseblock(i);
 323                 if (err)
 324                         return err;
 325                 if (i % 256 == 0)
 326                         pr_info("verified up to eraseblock %u\n", i);
 327 
 328                 err = mtdtest_relax();
 329                 if (err)
 330                         return err;
 331         }
 332         pr_info("verified %u eraseblocks\n", i);
 333         return 0;
 334 }
 335 
 336 static int __init mtd_oobtest_init(void)
 337 {
 338         int err = 0;
 339         unsigned int i;
 340         uint64_t tmp;
 341         struct mtd_oob_ops ops;
 342         loff_t addr = 0, addr0;
 343 
 344         printk(KERN_INFO "\n");
 345         printk(KERN_INFO "=================================================\n");
 346 
 347         if (dev < 0) {
 348                 pr_info("Please specify a valid mtd-device via module parameter\n");
 349                 pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
 350                 return -EINVAL;
 351         }
 352 
 353         pr_info("MTD device: %d\n", dev);
 354 
 355         mtd = get_mtd_device(NULL, dev);
 356         if (IS_ERR(mtd)) {
 357                 err = PTR_ERR(mtd);
 358                 pr_err("error: cannot get MTD device\n");
 359                 return err;
 360         }
 361 
 362         if (!mtd_type_is_nand(mtd)) {
 363                 pr_info("this test requires NAND flash\n");
 364                 goto out;
 365         }
 366 
 367         tmp = mtd->size;
 368         do_div(tmp, mtd->erasesize);
 369         ebcnt = tmp;
 370         pgcnt = mtd->erasesize / mtd->writesize;
 371 
 372         pr_info("MTD device size %llu, eraseblock size %u, "
 373                "page size %u, count of eraseblocks %u, pages per "
 374                "eraseblock %u, OOB size %u\n",
 375                (unsigned long long)mtd->size, mtd->erasesize,
 376                mtd->writesize, ebcnt, pgcnt, mtd->oobsize);
 377 
 378         err = -ENOMEM;
 379         readbuf = kmalloc(mtd->erasesize, GFP_KERNEL);
 380         if (!readbuf)
 381                 goto out;
 382         writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
 383         if (!writebuf)
 384                 goto out;
 385         bbt = kzalloc(ebcnt, GFP_KERNEL);
 386         if (!bbt)
 387                 goto out;
 388 
 389         err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
 390         if (err)
 391                 goto out;
 392 
 393         use_offset = 0;
 394         use_len = mtd->oobavail;
 395         use_len_max = mtd->oobavail;
 396         vary_offset = 0;
 397 
 398         /* First test: write all OOB, read it back and verify */
 399         pr_info("test 1 of 5\n");
 400 
 401         err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
 402         if (err)
 403                 goto out;
 404 
 405         prandom_seed_state(&rnd_state, 1);
 406         err = write_whole_device();
 407         if (err)
 408                 goto out;
 409 
 410         prandom_seed_state(&rnd_state, 1);
 411         err = verify_all_eraseblocks();
 412         if (err)
 413                 goto out;
 414 
 415         /*
 416          * Second test: write all OOB, a block at a time, read it back and
 417          * verify.
 418          */
 419         pr_info("test 2 of 5\n");
 420 
 421         err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
 422         if (err)
 423                 goto out;
 424 
 425         prandom_seed_state(&rnd_state, 3);
 426         err = write_whole_device();
 427         if (err)
 428                 goto out;
 429 
 430         /* Check all eraseblocks */
 431         prandom_seed_state(&rnd_state, 3);
 432         pr_info("verifying all eraseblocks\n");
 433         for (i = 0; i < ebcnt; ++i) {
 434                 if (bbt[i])
 435                         continue;
 436                 err = verify_eraseblock_in_one_go(i);
 437                 if (err)
 438                         goto out;
 439                 if (i % 256 == 0)
 440                         pr_info("verified up to eraseblock %u\n", i);
 441 
 442                 err = mtdtest_relax();
 443                 if (err)
 444                         goto out;
 445         }
 446         pr_info("verified %u eraseblocks\n", i);
 447 
 448         /*
 449          * Third test: write OOB at varying offsets and lengths, read it back
 450          * and verify.
 451          */
 452         pr_info("test 3 of 5\n");
 453 
 454         err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
 455         if (err)
 456                 goto out;
 457 
 458         /* Write all eraseblocks */
 459         use_offset = 0;
 460         use_len = mtd->oobavail;
 461         use_len_max = mtd->oobavail;
 462         vary_offset = 1;
 463         prandom_seed_state(&rnd_state, 5);
 464 
 465         err = write_whole_device();
 466         if (err)
 467                 goto out;
 468 
 469         /* Check all eraseblocks */
 470         use_offset = 0;
 471         use_len = mtd->oobavail;
 472         use_len_max = mtd->oobavail;
 473         vary_offset = 1;
 474         prandom_seed_state(&rnd_state, 5);
 475         err = verify_all_eraseblocks();
 476         if (err)
 477                 goto out;
 478 
 479         use_offset = 0;
 480         use_len = mtd->oobavail;
 481         use_len_max = mtd->oobavail;
 482         vary_offset = 0;
 483 
 484         /* Fourth test: try to write off end of device */
 485         pr_info("test 4 of 5\n");
 486 
 487         err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
 488         if (err)
 489                 goto out;
 490 
 491         addr0 = 0;
 492         for (i = 0; i < ebcnt && bbt[i]; ++i)
 493                 addr0 += mtd->erasesize;
 494 
 495         /* Attempt to write off end of OOB */
 496         ops.mode      = MTD_OPS_AUTO_OOB;
 497         ops.len       = 0;
 498         ops.retlen    = 0;
 499         ops.ooblen    = 1;
 500         ops.oobretlen = 0;
 501         ops.ooboffs   = mtd->oobavail;
 502         ops.datbuf    = NULL;
 503         ops.oobbuf    = writebuf;
 504         pr_info("attempting to start write past end of OOB\n");
 505         pr_info("an error is expected...\n");
 506         err = mtd_write_oob(mtd, addr0, &ops);
 507         if (err) {
 508                 pr_info("error occurred as expected\n");
 509                 err = 0;
 510         } else {
 511                 pr_err("error: can write past end of OOB\n");
 512                 errcnt += 1;
 513         }
 514 
 515         /* Attempt to read off end of OOB */
 516         ops.mode      = MTD_OPS_AUTO_OOB;
 517         ops.len       = 0;
 518         ops.retlen    = 0;
 519         ops.ooblen    = 1;
 520         ops.oobretlen = 0;
 521         ops.ooboffs   = mtd->oobavail;
 522         ops.datbuf    = NULL;
 523         ops.oobbuf    = readbuf;
 524         pr_info("attempting to start read past end of OOB\n");
 525         pr_info("an error is expected...\n");
 526         err = mtd_read_oob(mtd, addr0, &ops);
 527         if (mtd_is_bitflip(err))
 528                 err = 0;
 529 
 530         if (err) {
 531                 pr_info("error occurred as expected\n");
 532                 err = 0;
 533         } else {
 534                 pr_err("error: can read past end of OOB\n");
 535                 errcnt += 1;
 536         }
 537 
 538         if (bbt[ebcnt - 1])
 539                 pr_info("skipping end of device tests because last "
 540                        "block is bad\n");
 541         else {
 542                 /* Attempt to write off end of device */
 543                 ops.mode      = MTD_OPS_AUTO_OOB;
 544                 ops.len       = 0;
 545                 ops.retlen    = 0;
 546                 ops.ooblen    = mtd->oobavail + 1;
 547                 ops.oobretlen = 0;
 548                 ops.ooboffs   = 0;
 549                 ops.datbuf    = NULL;
 550                 ops.oobbuf    = writebuf;
 551                 pr_info("attempting to write past end of device\n");
 552                 pr_info("an error is expected...\n");
 553                 err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
 554                 if (err) {
 555                         pr_info("error occurred as expected\n");
 556                         err = 0;
 557                 } else {
 558                         pr_err("error: wrote past end of device\n");
 559                         errcnt += 1;
 560                 }
 561 
 562                 /* Attempt to read off end of device */
 563                 ops.mode      = MTD_OPS_AUTO_OOB;
 564                 ops.len       = 0;
 565                 ops.retlen    = 0;
 566                 ops.ooblen    = mtd->oobavail + 1;
 567                 ops.oobretlen = 0;
 568                 ops.ooboffs   = 0;
 569                 ops.datbuf    = NULL;
 570                 ops.oobbuf    = readbuf;
 571                 pr_info("attempting to read past end of device\n");
 572                 pr_info("an error is expected...\n");
 573                 err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
 574                 if (mtd_is_bitflip(err))
 575                         err = 0;
 576 
 577                 if (err) {
 578                         pr_info("error occurred as expected\n");
 579                         err = 0;
 580                 } else {
 581                         pr_err("error: read past end of device\n");
 582                         errcnt += 1;
 583                 }
 584 
 585                 err = mtdtest_erase_eraseblock(mtd, ebcnt - 1);
 586                 if (err)
 587                         goto out;
 588 
 589                 /* Attempt to write off end of device */
 590                 ops.mode      = MTD_OPS_AUTO_OOB;
 591                 ops.len       = 0;
 592                 ops.retlen    = 0;
 593                 ops.ooblen    = mtd->oobavail;
 594                 ops.oobretlen = 0;
 595                 ops.ooboffs   = 1;
 596                 ops.datbuf    = NULL;
 597                 ops.oobbuf    = writebuf;
 598                 pr_info("attempting to write past end of device\n");
 599                 pr_info("an error is expected...\n");
 600                 err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
 601                 if (err) {
 602                         pr_info("error occurred as expected\n");
 603                         err = 0;
 604                 } else {
 605                         pr_err("error: wrote past end of device\n");
 606                         errcnt += 1;
 607                 }
 608 
 609                 /* Attempt to read off end of device */
 610                 ops.mode      = MTD_OPS_AUTO_OOB;
 611                 ops.len       = 0;
 612                 ops.retlen    = 0;
 613                 ops.ooblen    = mtd->oobavail;
 614                 ops.oobretlen = 0;
 615                 ops.ooboffs   = 1;
 616                 ops.datbuf    = NULL;
 617                 ops.oobbuf    = readbuf;
 618                 pr_info("attempting to read past end of device\n");
 619                 pr_info("an error is expected...\n");
 620                 err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
 621                 if (mtd_is_bitflip(err))
 622                         err = 0;
 623 
 624                 if (err) {
 625                         pr_info("error occurred as expected\n");
 626                         err = 0;
 627                 } else {
 628                         pr_err("error: read past end of device\n");
 629                         errcnt += 1;
 630                 }
 631         }
 632 
 633         /* Fifth test: write / read across block boundaries */
 634         pr_info("test 5 of 5\n");
 635 
 636         /* Erase all eraseblocks */
 637         err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
 638         if (err)
 639                 goto out;
 640 
 641         /* Write all eraseblocks */
 642         prandom_seed_state(&rnd_state, 11);
 643         pr_info("writing OOBs of whole device\n");
 644         for (i = 0; i < ebcnt - 1; ++i) {
 645                 int cnt = 2;
 646                 int pg;
 647                 size_t sz = mtd->oobavail;
 648                 if (bbt[i] || bbt[i + 1])
 649                         continue;
 650                 addr = (loff_t)(i + 1) * mtd->erasesize - mtd->writesize;
 651                 prandom_bytes_state(&rnd_state, writebuf, sz * cnt);
 652                 for (pg = 0; pg < cnt; ++pg) {
 653                         ops.mode      = MTD_OPS_AUTO_OOB;
 654                         ops.len       = 0;
 655                         ops.retlen    = 0;
 656                         ops.ooblen    = sz;
 657                         ops.oobretlen = 0;
 658                         ops.ooboffs   = 0;
 659                         ops.datbuf    = NULL;
 660                         ops.oobbuf    = writebuf + pg * sz;
 661                         err = mtd_write_oob(mtd, addr, &ops);
 662                         if (err)
 663                                 goto out;
 664                         if (i % 256 == 0)
 665                                 pr_info("written up to eraseblock %u\n", i);
 666 
 667                         err = mtdtest_relax();
 668                         if (err)
 669                                 goto out;
 670 
 671                         addr += mtd->writesize;
 672                 }
 673         }
 674         pr_info("written %u eraseblocks\n", i);
 675 
 676         /* Check all eraseblocks */
 677         prandom_seed_state(&rnd_state, 11);
 678         pr_info("verifying all eraseblocks\n");
 679         for (i = 0; i < ebcnt - 1; ++i) {
 680                 if (bbt[i] || bbt[i + 1])
 681                         continue;
 682                 prandom_bytes_state(&rnd_state, writebuf, mtd->oobavail * 2);
 683                 addr = (loff_t)(i + 1) * mtd->erasesize - mtd->writesize;
 684                 ops.mode      = MTD_OPS_AUTO_OOB;
 685                 ops.len       = 0;
 686                 ops.retlen    = 0;
 687                 ops.ooblen    = mtd->oobavail * 2;
 688                 ops.oobretlen = 0;
 689                 ops.ooboffs   = 0;
 690                 ops.datbuf    = NULL;
 691                 ops.oobbuf    = readbuf;
 692                 err = mtd_read_oob(mtd, addr, &ops);
 693                 if (mtd_is_bitflip(err))
 694                         err = 0;
 695 
 696                 if (err)
 697                         goto out;
 698                 if (memcmpshow(addr, readbuf, writebuf,
 699                                mtd->oobavail * 2)) {
 700                         pr_err("error: verify failed at %#llx\n",
 701                                (long long)addr);
 702                         errcnt += 1;
 703                         if (errcnt > 1000) {
 704                                 pr_err("error: too many errors\n");
 705                                 goto out;
 706                         }
 707                 }
 708                 if (i % 256 == 0)
 709                         pr_info("verified up to eraseblock %u\n", i);
 710 
 711                 err = mtdtest_relax();
 712                 if (err)
 713                         goto out;
 714         }
 715         pr_info("verified %u eraseblocks\n", i);
 716 
 717         pr_info("finished with %d errors\n", errcnt);
 718 out:
 719         kfree(bbt);
 720         kfree(writebuf);
 721         kfree(readbuf);
 722         put_mtd_device(mtd);
 723         if (err)
 724                 pr_info("error %d occurred\n", err);
 725         printk(KERN_INFO "=================================================\n");
 726         return err;
 727 }
 728 module_init(mtd_oobtest_init);
 729 
 730 static void __exit mtd_oobtest_exit(void)
 731 {
 732         return;
 733 }
 734 module_exit(mtd_oobtest_exit);
 735 
 736 MODULE_DESCRIPTION("Out-of-band test module");
 737 MODULE_AUTHOR("Adrian Hunter");
 738 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */