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