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