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