1/* 2 * Copyright (C) 2006-2008 Artem Bityutskiy 3 * Copyright (C) 2006-2008 Jarkko Lavinen 4 * Copyright (C) 2006-2008 Adrian Hunter 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 as published by 8 * the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License along with 16 * this program; see the file COPYING. If not, write to the Free Software 17 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 * 19 * Authors: Artem Bityutskiy, Jarkko Lavinen, Adria Hunter 20 * 21 * WARNING: this test program may kill your flash and your device. Do not 22 * use it unless you know what you do. Authors are not responsible for any 23 * damage caused by this program. 24 */ 25 26#include <linux/init.h> 27#include <linux/module.h> 28#include <linux/moduleparam.h> 29#include <linux/err.h> 30#include <linux/mtd/mtd.h> 31#include <linux/slab.h> 32#include <linux/sched.h> 33 34#define PRINT_PREF KERN_INFO "mtd_torturetest: " 35#define RETRIES 3 36 37static int eb = 8; 38module_param(eb, int, S_IRUGO); 39MODULE_PARM_DESC(eb, "eraseblock number within the selected MTD device"); 40 41static int ebcnt = 32; 42module_param(ebcnt, int, S_IRUGO); 43MODULE_PARM_DESC(ebcnt, "number of consecutive eraseblocks to torture"); 44 45static int pgcnt; 46module_param(pgcnt, int, S_IRUGO); 47MODULE_PARM_DESC(pgcnt, "number of pages per eraseblock to torture (0 => all)"); 48 49static int dev; 50module_param(dev, int, S_IRUGO); 51MODULE_PARM_DESC(dev, "MTD device number to use"); 52 53static int gran = 512; 54module_param(gran, int, S_IRUGO); 55MODULE_PARM_DESC(gran, "how often the status information should be printed"); 56 57static int check = 1; 58module_param(check, int, S_IRUGO); 59MODULE_PARM_DESC(check, "if the written data should be checked"); 60 61static unsigned int cycles_count; 62module_param(cycles_count, uint, S_IRUGO); 63MODULE_PARM_DESC(cycles_count, "how many erase cycles to do " 64 "(infinite by default)"); 65 66static struct mtd_info *mtd; 67 68/* This buffer contains 0x555555...0xAAAAAA... pattern */ 69static unsigned char *patt_5A5; 70/* This buffer contains 0xAAAAAA...0x555555... pattern */ 71static unsigned char *patt_A5A; 72/* This buffer contains all 0xFF bytes */ 73static unsigned char *patt_FF; 74/* This a temporary buffer is use when checking data */ 75static unsigned char *check_buf; 76/* How many erase cycles were done */ 77static unsigned int erase_cycles; 78 79static int pgsize; 80static struct timeval start, finish; 81 82static void report_corrupt(unsigned char *read, unsigned char *written); 83 84static inline void start_timing(void) 85{ 86 do_gettimeofday(&start); 87} 88 89static inline void stop_timing(void) 90{ 91 do_gettimeofday(&finish); 92} 93 94/* 95 * Erase eraseblock number @ebnum. 96 */ 97static inline int erase_eraseblock(int ebnum) 98{ 99 int err; 100 struct erase_info ei; 101 loff_t addr = ebnum * mtd->erasesize; 102 103 memset(&ei, 0, sizeof(struct erase_info)); 104 ei.mtd = mtd; 105 ei.addr = addr; 106 ei.len = mtd->erasesize; 107 108 err = mtd->erase(mtd, &ei); 109 if (err) { 110 printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); 111 return err; 112 } 113 114 if (ei.state == MTD_ERASE_FAILED) { 115 printk(PRINT_PREF "some erase error occurred at EB %d\n", 116 ebnum); 117 return -EIO; 118 } 119 120 return 0; 121} 122 123/* 124 * Check that the contents of eraseblock number @enbum is equivalent to the 125 * @buf buffer. 126 */ 127static inline int check_eraseblock(int ebnum, unsigned char *buf) 128{ 129 int err, retries = 0; 130 size_t read = 0; 131 loff_t addr = ebnum * mtd->erasesize; 132 size_t len = mtd->erasesize; 133 134 if (pgcnt) { 135 addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize; 136 len = pgcnt * pgsize; 137 } 138 139retry: 140 err = mtd->read(mtd, addr, len, &read, check_buf); 141 if (err == -EUCLEAN) 142 printk(PRINT_PREF "single bit flip occurred at EB %d " 143 "MTD reported that it was fixed.\n", ebnum); 144 else if (err) { 145 printk(PRINT_PREF "error %d while reading EB %d, " 146 "read %zd\n", err, ebnum, read); 147 return err; 148 } 149 150 if (read != len) { 151 printk(PRINT_PREF "failed to read %zd bytes from EB %d, " 152 "read only %zd, but no error reported\n", 153 len, ebnum, read); 154 return -EIO; 155 } 156 157 if (memcmp(buf, check_buf, len)) { 158 printk(PRINT_PREF "read wrong data from EB %d\n", ebnum); 159 report_corrupt(check_buf, buf); 160 161 if (retries++ < RETRIES) { 162 /* Try read again */ 163 yield(); 164 printk(PRINT_PREF "re-try reading data from EB %d\n", 165 ebnum); 166 goto retry; 167 } else { 168 printk(PRINT_PREF "retried %d times, still errors, " 169 "give-up\n", RETRIES); 170 return -EINVAL; 171 } 172 } 173 174 if (retries != 0) 175 printk(PRINT_PREF "only attempt number %d was OK (!!!)\n", 176 retries); 177 178 return 0; 179} 180 181static inline int write_pattern(int ebnum, void *buf) 182{ 183 int err; 184 size_t written = 0; 185 loff_t addr = ebnum * mtd->erasesize; 186 size_t len = mtd->erasesize; 187 188 if (pgcnt) { 189 addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize; 190 len = pgcnt * pgsize; 191 } 192 err = mtd->write(mtd, addr, len, &written, buf); 193 if (err) { 194 printk(PRINT_PREF "error %d while writing EB %d, written %zd" 195 " bytes\n", err, ebnum, written); 196 return err; 197 } 198 if (written != len) { 199 printk(PRINT_PREF "written only %zd bytes of %zd, but no error" 200 " reported\n", written, len); 201 return -EIO; 202 } 203 204 return 0; 205} 206 207static int __init tort_init(void) 208{ 209 int err = 0, i, infinite = !cycles_count; 210 int bad_ebs[ebcnt]; 211 212 printk(KERN_INFO "\n"); 213 printk(KERN_INFO "=================================================\n"); 214 printk(PRINT_PREF "Warning: this program is trying to wear out your " 215 "flash, stop it if this is not wanted.\n"); 216 printk(PRINT_PREF "MTD device: %d\n", dev); 217 printk(PRINT_PREF "torture %d eraseblocks (%d-%d) of mtd%d\n", 218 ebcnt, eb, eb + ebcnt - 1, dev); 219 if (pgcnt) 220 printk(PRINT_PREF "torturing just %d pages per eraseblock\n", 221 pgcnt); 222 printk(PRINT_PREF "write verify %s\n", check ? "enabled" : "disabled"); 223 224 mtd = get_mtd_device(NULL, dev); 225 if (IS_ERR(mtd)) { 226 err = PTR_ERR(mtd); 227 printk(PRINT_PREF "error: cannot get MTD device\n"); 228 return err; 229 } 230 231 if (mtd->writesize == 1) { 232 printk(PRINT_PREF "not NAND flash, assume page size is 512 " 233 "bytes.\n"); 234 pgsize = 512; 235 } else 236 pgsize = mtd->writesize; 237 238 if (pgcnt && (pgcnt > mtd->erasesize / pgsize || pgcnt < 0)) { 239 printk(PRINT_PREF "error: invalid pgcnt value %d\n", pgcnt); 240 goto out_mtd; 241 } 242 243 err = -ENOMEM; 244 patt_5A5 = kmalloc(mtd->erasesize, GFP_KERNEL); 245 if (!patt_5A5) { 246 printk(PRINT_PREF "error: cannot allocate memory\n"); 247 goto out_mtd; 248 } 249 250 patt_A5A = kmalloc(mtd->erasesize, GFP_KERNEL); 251 if (!patt_A5A) { 252 printk(PRINT_PREF "error: cannot allocate memory\n"); 253 goto out_patt_5A5; 254 } 255 256 patt_FF = kmalloc(mtd->erasesize, GFP_KERNEL); 257 if (!patt_FF) { 258 printk(PRINT_PREF "error: cannot allocate memory\n"); 259 goto out_patt_A5A; 260 } 261 262 check_buf = kmalloc(mtd->erasesize, GFP_KERNEL); 263 if (!check_buf) { 264 printk(PRINT_PREF "error: cannot allocate memory\n"); 265 goto out_patt_FF; 266 } 267 268 err = 0; 269 270 /* Initialize patterns */ 271 memset(patt_FF, 0xFF, mtd->erasesize); 272 for (i = 0; i < mtd->erasesize / pgsize; i++) { 273 if (!(i & 1)) { 274 memset(patt_5A5 + i * pgsize, 0x55, pgsize); 275 memset(patt_A5A + i * pgsize, 0xAA, pgsize); 276 } else { 277 memset(patt_5A5 + i * pgsize, 0xAA, pgsize); 278 memset(patt_A5A + i * pgsize, 0x55, pgsize); 279 } 280 } 281 282 /* 283 * Check if there is a bad eraseblock among those we are going to test. 284 */ 285 memset(&bad_ebs[0], 0, sizeof(int) * ebcnt); 286 if (mtd->block_isbad) { 287 for (i = eb; i < eb + ebcnt; i++) { 288 err = mtd->block_isbad(mtd, 289 (loff_t)i * mtd->erasesize); 290 291 if (err < 0) { 292 printk(PRINT_PREF "block_isbad() returned %d " 293 "for EB %d\n", err, i); 294 goto out; 295 } 296 297 if (err) { 298 printk("EB %d is bad. Skip it.\n", i); 299 bad_ebs[i - eb] = 1; 300 } 301 } 302 } 303 304 start_timing(); 305 while (1) { 306 int i; 307 void *patt; 308 309 /* Erase all eraseblocks */ 310 for (i = eb; i < eb + ebcnt; i++) { 311 if (bad_ebs[i - eb]) 312 continue; 313 err = erase_eraseblock(i); 314 if (err) 315 goto out; 316 cond_resched(); 317 } 318 319 /* Check if the eraseblocks contain only 0xFF bytes */ 320 if (check) { 321 for (i = eb; i < eb + ebcnt; i++) { 322 if (bad_ebs[i - eb]) 323 continue; 324 err = check_eraseblock(i, patt_FF); 325 if (err) { 326 printk(PRINT_PREF "verify failed" 327 " for 0xFF... pattern\n"); 328 goto out; 329 } 330 cond_resched(); 331 } 332 } 333 334 /* Write the pattern */ 335 for (i = eb; i < eb + ebcnt; i++) { 336 if (bad_ebs[i - eb]) 337 continue; 338 if ((eb + erase_cycles) & 1) 339 patt = patt_5A5; 340 else 341 patt = patt_A5A; 342 err = write_pattern(i, patt); 343 if (err) 344 goto out; 345 cond_resched(); 346 } 347 348 /* Verify what we wrote */ 349 if (check) { 350 for (i = eb; i < eb + ebcnt; i++) { 351 if (bad_ebs[i - eb]) 352 continue; 353 if ((eb + erase_cycles) & 1) 354 patt = patt_5A5; 355 else 356 patt = patt_A5A; 357 err = check_eraseblock(i, patt); 358 if (err) { 359 printk(PRINT_PREF "verify failed for %s" 360 " pattern\n", 361 ((eb + erase_cycles) & 1) ? 362 "0x55AA55..." : "0xAA55AA..."); 363 goto out; 364 } 365 cond_resched(); 366 } 367 } 368 369 erase_cycles += 1; 370 371 if (erase_cycles % gran == 0) { 372 long ms; 373 374 stop_timing(); 375 ms = (finish.tv_sec - start.tv_sec) * 1000 + 376 (finish.tv_usec - start.tv_usec) / 1000; 377 printk(PRINT_PREF "%08u erase cycles done, took %lu " 378 "milliseconds (%lu seconds)\n", 379 erase_cycles, ms, ms / 1000); 380 start_timing(); 381 } 382 383 if (!infinite && --cycles_count == 0) 384 break; 385 } 386out: 387 388 printk(PRINT_PREF "finished after %u erase cycles\n", 389 erase_cycles); 390 kfree(check_buf); 391out_patt_FF: 392 kfree(patt_FF); 393out_patt_A5A: 394 kfree(patt_A5A); 395out_patt_5A5: 396 kfree(patt_5A5); 397out_mtd: 398 put_mtd_device(mtd); 399 if (err) 400 printk(PRINT_PREF "error %d occurred during torturing\n", err); 401 printk(KERN_INFO "=================================================\n"); 402 return err; 403} 404module_init(tort_init); 405 406static void __exit tort_exit(void) 407{ 408 return; 409} 410module_exit(tort_exit); 411 412static int countdiffs(unsigned char *buf, unsigned char *check_buf, 413 unsigned offset, unsigned len, unsigned *bytesp, 414 unsigned *bitsp); 415static void print_bufs(unsigned char *read, unsigned char *written, int start, 416 int len); 417 418/* 419 * Report the detailed information about how the read EB differs from what was 420 * written. 421 */ 422static void report_corrupt(unsigned char *read, unsigned char *written) 423{ 424 int i; 425 int bytes, bits, pages, first; 426 int offset, len; 427 size_t check_len = mtd->erasesize; 428 429 if (pgcnt) 430 check_len = pgcnt * pgsize; 431 432 bytes = bits = pages = 0; 433 for (i = 0; i < check_len; i += pgsize) 434 if (countdiffs(written, read, i, pgsize, &bytes, 435 &bits) >= 0) 436 pages++; 437 438 printk(PRINT_PREF "verify fails on %d pages, %d bytes/%d bits\n", 439 pages, bytes, bits); 440 printk(PRINT_PREF "The following is a list of all differences between" 441 " what was read from flash and what was expected\n"); 442 443 for (i = 0; i < check_len; i += pgsize) { 444 cond_resched(); 445 bytes = bits = 0; 446 first = countdiffs(written, read, i, pgsize, &bytes, 447 &bits); 448 if (first < 0) 449 continue; 450 451 printk("-------------------------------------------------------" 452 "----------------------------------\n"); 453 454 printk(PRINT_PREF "Page %zd has %d bytes/%d bits failing verify," 455 " starting at offset 0x%x\n", 456 (mtd->erasesize - check_len + i) / pgsize, 457 bytes, bits, first); 458 459 offset = first & ~0x7; 460 len = ((first + bytes) | 0x7) + 1 - offset; 461 462 print_bufs(read, written, offset, len); 463 } 464} 465 466static void print_bufs(unsigned char *read, unsigned char *written, int start, 467 int len) 468{ 469 int i = 0, j1, j2; 470 char *diff; 471 472 printk("Offset Read Written\n"); 473 while (i < len) { 474 printk("0x%08x: ", start + i); 475 diff = " "; 476 for (j1 = 0; j1 < 8 && i + j1 < len; j1++) { 477 printk(" %02x", read[start + i + j1]); 478 if (read[start + i + j1] != written[start + i + j1]) 479 diff = "***"; 480 } 481 482 while (j1 < 8) { 483 printk(" "); 484 j1 += 1; 485 } 486 487 printk(" %s ", diff); 488 489 for (j2 = 0; j2 < 8 && i + j2 < len; j2++) 490 printk(" %02x", written[start + i + j2]); 491 printk("\n"); 492 i += 8; 493 } 494} 495 496/* 497 * Count the number of differing bytes and bits and return the first differing 498 * offset. 499 */ 500static int countdiffs(unsigned char *buf, unsigned char *check_buf, 501 unsigned offset, unsigned len, unsigned *bytesp, 502 unsigned *bitsp) 503{ 504 unsigned i, bit; 505 int first = -1; 506 507 for (i = offset; i < offset + len; i++) 508 if (buf[i] != check_buf[i]) { 509 first = i; 510 break; 511 } 512 513 while (i < offset + len) { 514 if (buf[i] != check_buf[i]) { 515 (*bytesp)++; 516 bit = 1; 517 while (bit < 256) { 518 if ((buf[i] & bit) != (check_buf[i] & bit)) 519 (*bitsp)++; 520 bit <<= 1; 521 } 522 } 523 i++; 524 } 525 526 return first; 527} 528 529MODULE_DESCRIPTION("Eraseblock torturing module"); 530MODULE_AUTHOR("Artem Bityutskiy, Jarkko Lavinen, Adrian Hunter"); 531MODULE_LICENSE("GPL"); 532