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