linux/drivers/mtd/tests/mtd_pagetest.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 page read and write on MTD device.
  18 *
  19 * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
  20 */
  21
  22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  23
  24#include <asm/div64.h>
  25#include <linux/init.h>
  26#include <linux/module.h>
  27#include <linux/moduleparam.h>
  28#include <linux/err.h>
  29#include <linux/mtd/mtd.h>
  30#include <linux/slab.h>
  31#include <linux/sched.h>
  32#include <linux/random.h>
  33
  34static int dev = -EINVAL;
  35module_param(dev, int, S_IRUGO);
  36MODULE_PARM_DESC(dev, "MTD device number to use");
  37
  38static struct mtd_info *mtd;
  39static unsigned char *twopages;
  40static unsigned char *writebuf;
  41static unsigned char *boundary;
  42static unsigned char *bbt;
  43
  44static int pgsize;
  45static int bufsize;
  46static int ebcnt;
  47static int pgcnt;
  48static int errcnt;
  49static struct rnd_state rnd_state;
  50
  51static int erase_eraseblock(int ebnum)
  52{
  53        int err;
  54        struct erase_info ei;
  55        loff_t addr = ebnum * mtd->erasesize;
  56
  57        memset(&ei, 0, sizeof(struct erase_info));
  58        ei.mtd  = mtd;
  59        ei.addr = addr;
  60        ei.len  = mtd->erasesize;
  61
  62        err = mtd_erase(mtd, &ei);
  63        if (err) {
  64                pr_err("error %d while erasing EB %d\n", err, ebnum);
  65                return err;
  66        }
  67
  68        if (ei.state == MTD_ERASE_FAILED) {
  69                pr_err("some erase error occurred at EB %d\n",
  70                       ebnum);
  71                return -EIO;
  72        }
  73
  74        return 0;
  75}
  76
  77static int write_eraseblock(int ebnum)
  78{
  79        int err = 0;
  80        size_t written;
  81        loff_t addr = ebnum * mtd->erasesize;
  82
  83        prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
  84        cond_resched();
  85        err = mtd_write(mtd, addr, mtd->erasesize, &written, writebuf);
  86        if (err || written != mtd->erasesize)
  87                pr_err("error: write failed at %#llx\n",
  88                       (long long)addr);
  89
  90        return err;
  91}
  92
  93static int verify_eraseblock(int ebnum)
  94{
  95        uint32_t j;
  96        size_t read;
  97        int err = 0, i;
  98        loff_t addr0, addrn;
  99        loff_t addr = ebnum * mtd->erasesize;
 100
 101        addr0 = 0;
 102        for (i = 0; i < ebcnt && bbt[i]; ++i)
 103                addr0 += mtd->erasesize;
 104
 105        addrn = mtd->size;
 106        for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
 107                addrn -= mtd->erasesize;
 108
 109        prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
 110        for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) {
 111                /* Do a read to set the internal dataRAMs to different data */
 112                err = mtd_read(mtd, addr0, bufsize, &read, twopages);
 113                if (mtd_is_bitflip(err))
 114                        err = 0;
 115                if (err || read != bufsize) {
 116                        pr_err("error: read failed at %#llx\n",
 117                               (long long)addr0);
 118                        return err;
 119                }
 120                err = mtd_read(mtd, addrn - bufsize, bufsize, &read, twopages);
 121                if (mtd_is_bitflip(err))
 122                        err = 0;
 123                if (err || read != bufsize) {
 124                        pr_err("error: read failed at %#llx\n",
 125                               (long long)(addrn - bufsize));
 126                        return err;
 127                }
 128                memset(twopages, 0, bufsize);
 129                err = mtd_read(mtd, addr, bufsize, &read, twopages);
 130                if (mtd_is_bitflip(err))
 131                        err = 0;
 132                if (err || read != bufsize) {
 133                        pr_err("error: read failed at %#llx\n",
 134                               (long long)addr);
 135                        break;
 136                }
 137                if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) {
 138                        pr_err("error: verify failed at %#llx\n",
 139                               (long long)addr);
 140                        errcnt += 1;
 141                }
 142        }
 143        /* Check boundary between eraseblocks */
 144        if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) {
 145                struct rnd_state old_state = rnd_state;
 146
 147                /* Do a read to set the internal dataRAMs to different data */
 148                err = mtd_read(mtd, addr0, bufsize, &read, twopages);
 149                if (mtd_is_bitflip(err))
 150                        err = 0;
 151                if (err || read != bufsize) {
 152                        pr_err("error: read failed at %#llx\n",
 153                               (long long)addr0);
 154                        return err;
 155                }
 156                err = mtd_read(mtd, addrn - bufsize, bufsize, &read, twopages);
 157                if (mtd_is_bitflip(err))
 158                        err = 0;
 159                if (err || read != bufsize) {
 160                        pr_err("error: read failed at %#llx\n",
 161                               (long long)(addrn - bufsize));
 162                        return err;
 163                }
 164                memset(twopages, 0, bufsize);
 165                err = mtd_read(mtd, addr, bufsize, &read, twopages);
 166                if (mtd_is_bitflip(err))
 167                        err = 0;
 168                if (err || read != bufsize) {
 169                        pr_err("error: read failed at %#llx\n",
 170                               (long long)addr);
 171                        return err;
 172                }
 173                memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize);
 174                prandom_bytes_state(&rnd_state, boundary + pgsize, pgsize);
 175                if (memcmp(twopages, boundary, bufsize)) {
 176                        pr_err("error: verify failed at %#llx\n",
 177                               (long long)addr);
 178                        errcnt += 1;
 179                }
 180                rnd_state = old_state;
 181        }
 182        return err;
 183}
 184
 185static int crosstest(void)
 186{
 187        size_t read;
 188        int err = 0, i;
 189        loff_t addr, addr0, addrn;
 190        unsigned char *pp1, *pp2, *pp3, *pp4;
 191
 192        pr_info("crosstest\n");
 193        pp1 = kmalloc(pgsize * 4, GFP_KERNEL);
 194        if (!pp1) {
 195                pr_err("error: cannot allocate memory\n");
 196                return -ENOMEM;
 197        }
 198        pp2 = pp1 + pgsize;
 199        pp3 = pp2 + pgsize;
 200        pp4 = pp3 + pgsize;
 201        memset(pp1, 0, pgsize * 4);
 202
 203        addr0 = 0;
 204        for (i = 0; i < ebcnt && bbt[i]; ++i)
 205                addr0 += mtd->erasesize;
 206
 207        addrn = mtd->size;
 208        for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
 209                addrn -= mtd->erasesize;
 210
 211        /* Read 2nd-to-last page to pp1 */
 212        addr = addrn - pgsize - pgsize;
 213        err = mtd_read(mtd, addr, pgsize, &read, pp1);
 214        if (mtd_is_bitflip(err))
 215                err = 0;
 216        if (err || read != pgsize) {
 217                pr_err("error: read failed at %#llx\n",
 218                       (long long)addr);
 219                kfree(pp1);
 220                return err;
 221        }
 222
 223        /* Read 3rd-to-last page to pp1 */
 224        addr = addrn - pgsize - pgsize - pgsize;
 225        err = mtd_read(mtd, addr, pgsize, &read, pp1);
 226        if (mtd_is_bitflip(err))
 227                err = 0;
 228        if (err || read != pgsize) {
 229                pr_err("error: read failed at %#llx\n",
 230                       (long long)addr);
 231                kfree(pp1);
 232                return err;
 233        }
 234
 235        /* Read first page to pp2 */
 236        addr = addr0;
 237        pr_info("reading page at %#llx\n", (long long)addr);
 238        err = mtd_read(mtd, addr, pgsize, &read, pp2);
 239        if (mtd_is_bitflip(err))
 240                err = 0;
 241        if (err || read != pgsize) {
 242                pr_err("error: read failed at %#llx\n",
 243                       (long long)addr);
 244                kfree(pp1);
 245                return err;
 246        }
 247
 248        /* Read last page to pp3 */
 249        addr = addrn - pgsize;
 250        pr_info("reading page at %#llx\n", (long long)addr);
 251        err = mtd_read(mtd, addr, pgsize, &read, pp3);
 252        if (mtd_is_bitflip(err))
 253                err = 0;
 254        if (err || read != pgsize) {
 255                pr_err("error: read failed at %#llx\n",
 256                       (long long)addr);
 257                kfree(pp1);
 258                return err;
 259        }
 260
 261        /* Read first page again to pp4 */
 262        addr = addr0;
 263        pr_info("reading page at %#llx\n", (long long)addr);
 264        err = mtd_read(mtd, addr, pgsize, &read, pp4);
 265        if (mtd_is_bitflip(err))
 266                err = 0;
 267        if (err || read != pgsize) {
 268                pr_err("error: read failed at %#llx\n",
 269                       (long long)addr);
 270                kfree(pp1);
 271                return err;
 272        }
 273
 274        /* pp2 and pp4 should be the same */
 275        pr_info("verifying pages read at %#llx match\n",
 276               (long long)addr0);
 277        if (memcmp(pp2, pp4, pgsize)) {
 278                pr_err("verify failed!\n");
 279                errcnt += 1;
 280        } else if (!err)
 281                pr_info("crosstest ok\n");
 282        kfree(pp1);
 283        return err;
 284}
 285
 286static int erasecrosstest(void)
 287{
 288        size_t read, written;
 289        int err = 0, i, ebnum, ebnum2;
 290        loff_t addr0;
 291        char *readbuf = twopages;
 292
 293        pr_info("erasecrosstest\n");
 294
 295        ebnum = 0;
 296        addr0 = 0;
 297        for (i = 0; i < ebcnt && bbt[i]; ++i) {
 298                addr0 += mtd->erasesize;
 299                ebnum += 1;
 300        }
 301
 302        ebnum2 = ebcnt - 1;
 303        while (ebnum2 && bbt[ebnum2])
 304                ebnum2 -= 1;
 305
 306        pr_info("erasing block %d\n", ebnum);
 307        err = erase_eraseblock(ebnum);
 308        if (err)
 309                return err;
 310
 311        pr_info("writing 1st page of block %d\n", ebnum);
 312        prandom_bytes_state(&rnd_state, writebuf, pgsize);
 313        strcpy(writebuf, "There is no data like this!");
 314        err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
 315        if (err || written != pgsize) {
 316                pr_info("error: write failed at %#llx\n",
 317                       (long long)addr0);
 318                return err ? err : -1;
 319        }
 320
 321        pr_info("reading 1st page of block %d\n", ebnum);
 322        memset(readbuf, 0, pgsize);
 323        err = mtd_read(mtd, addr0, pgsize, &read, readbuf);
 324        if (mtd_is_bitflip(err))
 325                err = 0;
 326        if (err || read != pgsize) {
 327                pr_err("error: read failed at %#llx\n",
 328                       (long long)addr0);
 329                return err ? err : -1;
 330        }
 331
 332        pr_info("verifying 1st page of block %d\n", ebnum);
 333        if (memcmp(writebuf, readbuf, pgsize)) {
 334                pr_err("verify failed!\n");
 335                errcnt += 1;
 336                return -1;
 337        }
 338
 339        pr_info("erasing block %d\n", ebnum);
 340        err = erase_eraseblock(ebnum);
 341        if (err)
 342                return err;
 343
 344        pr_info("writing 1st page of block %d\n", ebnum);
 345        prandom_bytes_state(&rnd_state, writebuf, pgsize);
 346        strcpy(writebuf, "There is no data like this!");
 347        err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
 348        if (err || written != pgsize) {
 349                pr_err("error: write failed at %#llx\n",
 350                       (long long)addr0);
 351                return err ? err : -1;
 352        }
 353
 354        pr_info("erasing block %d\n", ebnum2);
 355        err = erase_eraseblock(ebnum2);
 356        if (err)
 357                return err;
 358
 359        pr_info("reading 1st page of block %d\n", ebnum);
 360        memset(readbuf, 0, pgsize);
 361        err = mtd_read(mtd, addr0, pgsize, &read, readbuf);
 362        if (mtd_is_bitflip(err))
 363                err = 0;
 364        if (err || read != pgsize) {
 365                pr_err("error: read failed at %#llx\n",
 366                       (long long)addr0);
 367                return err ? err : -1;
 368        }
 369
 370        pr_info("verifying 1st page of block %d\n", ebnum);
 371        if (memcmp(writebuf, readbuf, pgsize)) {
 372                pr_err("verify failed!\n");
 373                errcnt += 1;
 374                return -1;
 375        }
 376
 377        if (!err)
 378                pr_info("erasecrosstest ok\n");
 379        return err;
 380}
 381
 382static int erasetest(void)
 383{
 384        size_t read, written;
 385        int err = 0, i, ebnum, ok = 1;
 386        loff_t addr0;
 387
 388        pr_info("erasetest\n");
 389
 390        ebnum = 0;
 391        addr0 = 0;
 392        for (i = 0; i < ebcnt && bbt[i]; ++i) {
 393                addr0 += mtd->erasesize;
 394                ebnum += 1;
 395        }
 396
 397        pr_info("erasing block %d\n", ebnum);
 398        err = erase_eraseblock(ebnum);
 399        if (err)
 400                return err;
 401
 402        pr_info("writing 1st page of block %d\n", ebnum);
 403        prandom_bytes_state(&rnd_state, writebuf, pgsize);
 404        err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
 405        if (err || written != pgsize) {
 406                pr_err("error: write failed at %#llx\n",
 407                       (long long)addr0);
 408                return err ? err : -1;
 409        }
 410
 411        pr_info("erasing block %d\n", ebnum);
 412        err = erase_eraseblock(ebnum);
 413        if (err)
 414                return err;
 415
 416        pr_info("reading 1st page of block %d\n", ebnum);
 417        err = mtd_read(mtd, addr0, pgsize, &read, twopages);
 418        if (mtd_is_bitflip(err))
 419                err = 0;
 420        if (err || read != pgsize) {
 421                pr_err("error: read failed at %#llx\n",
 422                       (long long)addr0);
 423                return err ? err : -1;
 424        }
 425
 426        pr_info("verifying 1st page of block %d is all 0xff\n",
 427               ebnum);
 428        for (i = 0; i < pgsize; ++i)
 429                if (twopages[i] != 0xff) {
 430                        pr_err("verifying all 0xff failed at %d\n",
 431                               i);
 432                        errcnt += 1;
 433                        ok = 0;
 434                        break;
 435                }
 436
 437        if (ok && !err)
 438                pr_info("erasetest ok\n");
 439
 440        return err;
 441}
 442
 443static int is_block_bad(int ebnum)
 444{
 445        loff_t addr = ebnum * mtd->erasesize;
 446        int ret;
 447
 448        ret = mtd_block_isbad(mtd, addr);
 449        if (ret)
 450                pr_info("block %d is bad\n", ebnum);
 451        return ret;
 452}
 453
 454static int scan_for_bad_eraseblocks(void)
 455{
 456        int i, bad = 0;
 457
 458        bbt = kzalloc(ebcnt, GFP_KERNEL);
 459        if (!bbt) {
 460                pr_err("error: cannot allocate memory\n");
 461                return -ENOMEM;
 462        }
 463
 464        pr_info("scanning for bad eraseblocks\n");
 465        for (i = 0; i < ebcnt; ++i) {
 466                bbt[i] = is_block_bad(i) ? 1 : 0;
 467                if (bbt[i])
 468                        bad += 1;
 469                cond_resched();
 470        }
 471        pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
 472        return 0;
 473}
 474
 475static int __init mtd_pagetest_init(void)
 476{
 477        int err = 0;
 478        uint64_t tmp;
 479        uint32_t i;
 480
 481        printk(KERN_INFO "\n");
 482        printk(KERN_INFO "=================================================\n");
 483
 484        if (dev < 0) {
 485                pr_info("Please specify a valid mtd-device via module parameter\n");
 486                pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
 487                return -EINVAL;
 488        }
 489
 490        pr_info("MTD device: %d\n", dev);
 491
 492        mtd = get_mtd_device(NULL, dev);
 493        if (IS_ERR(mtd)) {
 494                err = PTR_ERR(mtd);
 495                pr_err("error: cannot get MTD device\n");
 496                return err;
 497        }
 498
 499        if (mtd->type != MTD_NANDFLASH) {
 500                pr_info("this test requires NAND flash\n");
 501                goto out;
 502        }
 503
 504        tmp = mtd->size;
 505        do_div(tmp, mtd->erasesize);
 506        ebcnt = tmp;
 507        pgcnt = mtd->erasesize / mtd->writesize;
 508        pgsize = mtd->writesize;
 509
 510        pr_info("MTD device size %llu, eraseblock size %u, "
 511               "page size %u, count of eraseblocks %u, pages per "
 512               "eraseblock %u, OOB size %u\n",
 513               (unsigned long long)mtd->size, mtd->erasesize,
 514               pgsize, ebcnt, pgcnt, mtd->oobsize);
 515
 516        err = -ENOMEM;
 517        bufsize = pgsize * 2;
 518        writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
 519        if (!writebuf) {
 520                pr_err("error: cannot allocate memory\n");
 521                goto out;
 522        }
 523        twopages = kmalloc(bufsize, GFP_KERNEL);
 524        if (!twopages) {
 525                pr_err("error: cannot allocate memory\n");
 526                goto out;
 527        }
 528        boundary = kmalloc(bufsize, GFP_KERNEL);
 529        if (!boundary) {
 530                pr_err("error: cannot allocate memory\n");
 531                goto out;
 532        }
 533
 534        err = scan_for_bad_eraseblocks();
 535        if (err)
 536                goto out;
 537
 538        /* Erase all eraseblocks */
 539        pr_info("erasing whole device\n");
 540        for (i = 0; i < ebcnt; ++i) {
 541                if (bbt[i])
 542                        continue;
 543                err = erase_eraseblock(i);
 544                if (err)
 545                        goto out;
 546                cond_resched();
 547        }
 548        pr_info("erased %u eraseblocks\n", i);
 549
 550        /* Write all eraseblocks */
 551        prandom_seed_state(&rnd_state, 1);
 552        pr_info("writing whole device\n");
 553        for (i = 0; i < ebcnt; ++i) {
 554                if (bbt[i])
 555                        continue;
 556                err = write_eraseblock(i);
 557                if (err)
 558                        goto out;
 559                if (i % 256 == 0)
 560                        pr_info("written up to eraseblock %u\n", i);
 561                cond_resched();
 562        }
 563        pr_info("written %u eraseblocks\n", i);
 564
 565        /* Check all eraseblocks */
 566        prandom_seed_state(&rnd_state, 1);
 567        pr_info("verifying all eraseblocks\n");
 568        for (i = 0; i < ebcnt; ++i) {
 569                if (bbt[i])
 570                        continue;
 571                err = verify_eraseblock(i);
 572                if (err)
 573                        goto out;
 574                if (i % 256 == 0)
 575                        pr_info("verified up to eraseblock %u\n", i);
 576                cond_resched();
 577        }
 578        pr_info("verified %u eraseblocks\n", i);
 579
 580        err = crosstest();
 581        if (err)
 582                goto out;
 583
 584        err = erasecrosstest();
 585        if (err)
 586                goto out;
 587
 588        err = erasetest();
 589        if (err)
 590                goto out;
 591
 592        pr_info("finished with %d errors\n", errcnt);
 593out:
 594
 595        kfree(bbt);
 596        kfree(boundary);
 597        kfree(twopages);
 598        kfree(writebuf);
 599        put_mtd_device(mtd);
 600        if (err)
 601                pr_info("error %d occurred\n", err);
 602        printk(KERN_INFO "=================================================\n");
 603        return err;
 604}
 605module_init(mtd_pagetest_init);
 606
 607static void __exit mtd_pagetest_exit(void)
 608{
 609        return;
 610}
 611module_exit(mtd_pagetest_exit);
 612
 613MODULE_DESCRIPTION("NAND page test");
 614MODULE_AUTHOR("Adrian Hunter");
 615MODULE_LICENSE("GPL");
 616