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 34 #include "mtd_test.h" 35 36 static int dev = -EINVAL; 37 module_param(dev, int, S_IRUGO); 38 MODULE_PARM_DESC(dev, "MTD device number to use"); 39 40 static struct mtd_info *mtd; 41 static unsigned char *twopages; 42 static unsigned char *writebuf; 43 static unsigned char *boundary; 44 static unsigned char *bbt; 45 46 static int pgsize; 47 static int bufsize; 48 static int ebcnt; 49 static int pgcnt; 50 static int errcnt; 51 static struct rnd_state rnd_state; 52 53 static int write_eraseblock(int ebnum) 54 { 55 int err; 56 loff_t addr = ebnum * mtd->erasesize; 57 58 prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize); 59 cond_resched(); 60 err = mtdtest_write(mtd, addr, mtd->erasesize, writebuf); 61 if (err) 62 pr_err("error: write failed at %#llx\n", 63 (long long)addr); 64 65 return err; 66 } 67 68 static int verify_eraseblock(int ebnum) 69 { 70 uint32_t j; 71 int err = 0, i; 72 loff_t addr0, addrn; 73 loff_t addr = ebnum * mtd->erasesize; 74 75 addr0 = 0; 76 for (i = 0; i < ebcnt && bbt[i]; ++i) 77 addr0 += mtd->erasesize; 78 79 addrn = mtd->size; 80 for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i) 81 addrn -= mtd->erasesize; 82 83 prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize); 84 for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) { 85 /* Do a read to set the internal dataRAMs to different data */ 86 err = mtdtest_read(mtd, addr0, bufsize, twopages); 87 if (err) { 88 pr_err("error: read failed at %#llx\n", 89 (long long)addr0); 90 return err; 91 } 92 err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages); 93 if (err) { 94 pr_err("error: read failed at %#llx\n", 95 (long long)(addrn - bufsize)); 96 return err; 97 } 98 memset(twopages, 0, bufsize); 99 err = mtdtest_read(mtd, addr, bufsize, twopages); 100 if (err) { 101 pr_err("error: read failed at %#llx\n", 102 (long long)addr); 103 break; 104 } 105 if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) { 106 pr_err("error: verify failed at %#llx\n", 107 (long long)addr); 108 errcnt += 1; 109 } 110 } 111 /* Check boundary between eraseblocks */ 112 if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) { 113 struct rnd_state old_state = rnd_state; 114 115 /* Do a read to set the internal dataRAMs to different data */ 116 err = mtdtest_read(mtd, addr0, bufsize, twopages); 117 if (err) { 118 pr_err("error: read failed at %#llx\n", 119 (long long)addr0); 120 return err; 121 } 122 err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages); 123 if (err) { 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 = mtdtest_read(mtd, addr, bufsize, twopages); 130 if (err) { 131 pr_err("error: read failed at %#llx\n", 132 (long long)addr); 133 return err; 134 } 135 memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize); 136 prandom_bytes_state(&rnd_state, boundary + pgsize, pgsize); 137 if (memcmp(twopages, boundary, bufsize)) { 138 pr_err("error: verify failed at %#llx\n", 139 (long long)addr); 140 errcnt += 1; 141 } 142 rnd_state = old_state; 143 } 144 return err; 145 } 146 147 static int crosstest(void) 148 { 149 int err = 0, i; 150 loff_t addr, addr0, addrn; 151 unsigned char *pp1, *pp2, *pp3, *pp4; 152 153 pr_info("crosstest\n"); 154 pp1 = kmalloc(pgsize * 4, GFP_KERNEL); 155 if (!pp1) 156 return -ENOMEM; 157 pp2 = pp1 + pgsize; 158 pp3 = pp2 + pgsize; 159 pp4 = pp3 + pgsize; 160 memset(pp1, 0, pgsize * 4); 161 162 addr0 = 0; 163 for (i = 0; i < ebcnt && bbt[i]; ++i) 164 addr0 += mtd->erasesize; 165 166 addrn = mtd->size; 167 for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i) 168 addrn -= mtd->erasesize; 169 170 /* Read 2nd-to-last page to pp1 */ 171 addr = addrn - pgsize - pgsize; 172 err = mtdtest_read(mtd, addr, pgsize, pp1); 173 if (err) { 174 pr_err("error: read failed at %#llx\n", 175 (long long)addr); 176 kfree(pp1); 177 return err; 178 } 179 180 /* Read 3rd-to-last page to pp1 */ 181 addr = addrn - pgsize - pgsize - pgsize; 182 err = mtdtest_read(mtd, addr, pgsize, pp1); 183 if (err) { 184 pr_err("error: read failed at %#llx\n", 185 (long long)addr); 186 kfree(pp1); 187 return err; 188 } 189 190 /* Read first page to pp2 */ 191 addr = addr0; 192 pr_info("reading page at %#llx\n", (long long)addr); 193 err = mtdtest_read(mtd, addr, pgsize, pp2); 194 if (err) { 195 pr_err("error: read failed at %#llx\n", 196 (long long)addr); 197 kfree(pp1); 198 return err; 199 } 200 201 /* Read last page to pp3 */ 202 addr = addrn - pgsize; 203 pr_info("reading page at %#llx\n", (long long)addr); 204 err = mtdtest_read(mtd, addr, pgsize, pp3); 205 if (err) { 206 pr_err("error: read failed at %#llx\n", 207 (long long)addr); 208 kfree(pp1); 209 return err; 210 } 211 212 /* Read first page again to pp4 */ 213 addr = addr0; 214 pr_info("reading page at %#llx\n", (long long)addr); 215 err = mtdtest_read(mtd, addr, pgsize, pp4); 216 if (err) { 217 pr_err("error: read failed at %#llx\n", 218 (long long)addr); 219 kfree(pp1); 220 return err; 221 } 222 223 /* pp2 and pp4 should be the same */ 224 pr_info("verifying pages read at %#llx match\n", 225 (long long)addr0); 226 if (memcmp(pp2, pp4, pgsize)) { 227 pr_err("verify failed!\n"); 228 errcnt += 1; 229 } else if (!err) 230 pr_info("crosstest ok\n"); 231 kfree(pp1); 232 return err; 233 } 234 235 static int erasecrosstest(void) 236 { 237 int err = 0, i, ebnum, ebnum2; 238 loff_t addr0; 239 char *readbuf = twopages; 240 241 pr_info("erasecrosstest\n"); 242 243 ebnum = 0; 244 addr0 = 0; 245 for (i = 0; i < ebcnt && bbt[i]; ++i) { 246 addr0 += mtd->erasesize; 247 ebnum += 1; 248 } 249 250 ebnum2 = ebcnt - 1; 251 while (ebnum2 && bbt[ebnum2]) 252 ebnum2 -= 1; 253 254 pr_info("erasing block %d\n", ebnum); 255 err = mtdtest_erase_eraseblock(mtd, ebnum); 256 if (err) 257 return err; 258 259 pr_info("writing 1st page of block %d\n", ebnum); 260 prandom_bytes_state(&rnd_state, writebuf, pgsize); 261 strcpy(writebuf, "There is no data like this!"); 262 err = mtdtest_write(mtd, addr0, pgsize, writebuf); 263 if (err) { 264 pr_info("error: write failed at %#llx\n", 265 (long long)addr0); 266 return err; 267 } 268 269 pr_info("reading 1st page of block %d\n", ebnum); 270 memset(readbuf, 0, pgsize); 271 err = mtdtest_read(mtd, addr0, pgsize, readbuf); 272 if (err) { 273 pr_err("error: read failed at %#llx\n", 274 (long long)addr0); 275 return err; 276 } 277 278 pr_info("verifying 1st page of block %d\n", ebnum); 279 if (memcmp(writebuf, readbuf, pgsize)) { 280 pr_err("verify failed!\n"); 281 errcnt += 1; 282 return -1; 283 } 284 285 pr_info("erasing block %d\n", ebnum); 286 err = mtdtest_erase_eraseblock(mtd, ebnum); 287 if (err) 288 return err; 289 290 pr_info("writing 1st page of block %d\n", ebnum); 291 prandom_bytes_state(&rnd_state, writebuf, pgsize); 292 strcpy(writebuf, "There is no data like this!"); 293 err = mtdtest_write(mtd, addr0, pgsize, writebuf); 294 if (err) { 295 pr_err("error: write failed at %#llx\n", 296 (long long)addr0); 297 return err; 298 } 299 300 pr_info("erasing block %d\n", ebnum2); 301 err = mtdtest_erase_eraseblock(mtd, ebnum2); 302 if (err) 303 return err; 304 305 pr_info("reading 1st page of block %d\n", ebnum); 306 memset(readbuf, 0, pgsize); 307 err = mtdtest_read(mtd, addr0, pgsize, readbuf); 308 if (err) { 309 pr_err("error: read failed at %#llx\n", 310 (long long)addr0); 311 return err; 312 } 313 314 pr_info("verifying 1st page of block %d\n", ebnum); 315 if (memcmp(writebuf, readbuf, pgsize)) { 316 pr_err("verify failed!\n"); 317 errcnt += 1; 318 return -1; 319 } 320 321 if (!err) 322 pr_info("erasecrosstest ok\n"); 323 return err; 324 } 325 326 static int erasetest(void) 327 { 328 int err = 0, i, ebnum, ok = 1; 329 loff_t addr0; 330 331 pr_info("erasetest\n"); 332 333 ebnum = 0; 334 addr0 = 0; 335 for (i = 0; i < ebcnt && bbt[i]; ++i) { 336 addr0 += mtd->erasesize; 337 ebnum += 1; 338 } 339 340 pr_info("erasing block %d\n", ebnum); 341 err = mtdtest_erase_eraseblock(mtd, ebnum); 342 if (err) 343 return err; 344 345 pr_info("writing 1st page of block %d\n", ebnum); 346 prandom_bytes_state(&rnd_state, writebuf, pgsize); 347 err = mtdtest_write(mtd, addr0, pgsize, writebuf); 348 if (err) { 349 pr_err("error: write failed at %#llx\n", 350 (long long)addr0); 351 return err; 352 } 353 354 pr_info("erasing block %d\n", ebnum); 355 err = mtdtest_erase_eraseblock(mtd, ebnum); 356 if (err) 357 return err; 358 359 pr_info("reading 1st page of block %d\n", ebnum); 360 err = mtdtest_read(mtd, addr0, pgsize, twopages); 361 if (err) { 362 pr_err("error: read failed at %#llx\n", 363 (long long)addr0); 364 return err; 365 } 366 367 pr_info("verifying 1st page of block %d is all 0xff\n", 368 ebnum); 369 for (i = 0; i < pgsize; ++i) 370 if (twopages[i] != 0xff) { 371 pr_err("verifying all 0xff failed at %d\n", 372 i); 373 errcnt += 1; 374 ok = 0; 375 break; 376 } 377 378 if (ok && !err) 379 pr_info("erasetest ok\n"); 380 381 return err; 382 } 383 384 static int __init mtd_pagetest_init(void) 385 { 386 int err = 0; 387 uint64_t tmp; 388 uint32_t i; 389 390 printk(KERN_INFO "\n"); 391 printk(KERN_INFO "=================================================\n"); 392 393 if (dev < 0) { 394 pr_info("Please specify a valid mtd-device via module parameter\n"); 395 pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); 396 return -EINVAL; 397 } 398 399 pr_info("MTD device: %d\n", dev); 400 401 mtd = get_mtd_device(NULL, dev); 402 if (IS_ERR(mtd)) { 403 err = PTR_ERR(mtd); 404 pr_err("error: cannot get MTD device\n"); 405 return err; 406 } 407 408 if (mtd->type != MTD_NANDFLASH) { 409 pr_info("this test requires NAND flash\n"); 410 goto out; 411 } 412 413 tmp = mtd->size; 414 do_div(tmp, mtd->erasesize); 415 ebcnt = tmp; 416 pgcnt = mtd->erasesize / mtd->writesize; 417 pgsize = mtd->writesize; 418 419 pr_info("MTD device size %llu, eraseblock size %u, " 420 "page size %u, count of eraseblocks %u, pages per " 421 "eraseblock %u, OOB size %u\n", 422 (unsigned long long)mtd->size, mtd->erasesize, 423 pgsize, ebcnt, pgcnt, mtd->oobsize); 424 425 err = -ENOMEM; 426 bufsize = pgsize * 2; 427 writebuf = kmalloc(mtd->erasesize, GFP_KERNEL); 428 if (!writebuf) 429 goto out; 430 twopages = kmalloc(bufsize, GFP_KERNEL); 431 if (!twopages) 432 goto out; 433 boundary = kmalloc(bufsize, GFP_KERNEL); 434 if (!boundary) 435 goto out; 436 437 bbt = kzalloc(ebcnt, GFP_KERNEL); 438 if (!bbt) 439 goto out; 440 err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt); 441 if (err) 442 goto out; 443 444 /* Erase all eraseblocks */ 445 pr_info("erasing whole device\n"); 446 err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); 447 if (err) 448 goto out; 449 pr_info("erased %u eraseblocks\n", ebcnt); 450 451 /* Write all eraseblocks */ 452 prandom_seed_state(&rnd_state, 1); 453 pr_info("writing whole device\n"); 454 for (i = 0; i < ebcnt; ++i) { 455 if (bbt[i]) 456 continue; 457 err = write_eraseblock(i); 458 if (err) 459 goto out; 460 if (i % 256 == 0) 461 pr_info("written up to eraseblock %u\n", i); 462 cond_resched(); 463 } 464 pr_info("written %u eraseblocks\n", i); 465 466 /* Check all eraseblocks */ 467 prandom_seed_state(&rnd_state, 1); 468 pr_info("verifying all eraseblocks\n"); 469 for (i = 0; i < ebcnt; ++i) { 470 if (bbt[i]) 471 continue; 472 err = verify_eraseblock(i); 473 if (err) 474 goto out; 475 if (i % 256 == 0) 476 pr_info("verified up to eraseblock %u\n", i); 477 cond_resched(); 478 } 479 pr_info("verified %u eraseblocks\n", i); 480 481 err = crosstest(); 482 if (err) 483 goto out; 484 485 err = erasecrosstest(); 486 if (err) 487 goto out; 488 489 err = erasetest(); 490 if (err) 491 goto out; 492 493 pr_info("finished with %d errors\n", errcnt); 494 out: 495 496 kfree(bbt); 497 kfree(boundary); 498 kfree(twopages); 499 kfree(writebuf); 500 put_mtd_device(mtd); 501 if (err) 502 pr_info("error %d occurred\n", err); 503 printk(KERN_INFO "=================================================\n"); 504 return err; 505 } 506 module_init(mtd_pagetest_init); 507 508 static void __exit mtd_pagetest_exit(void) 509 { 510 return; 511 } 512 module_exit(mtd_pagetest_exit); 513 514 MODULE_DESCRIPTION("NAND page test"); 515 MODULE_AUTHOR("Adrian Hunter"); 516 MODULE_LICENSE("GPL"); 517