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