2  * Copyright (C) 2006-2007 Nokia Corporation
 
   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.
 
   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
 
  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.
 
  17  * Test sub-page read and write on MTD device.
 
  18  * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
 
  22 #include <linux/init.h>
 
  23 #include <linux/module.h>
 
  24 #include <linux/moduleparam.h>
 
  25 #include <linux/err.h>
 
  26 #include <linux/mtd/mtd.h>
 
  27 #include <linux/sched.h>
 
  29 #define PRINT_PREF KERN_INFO "mtd_subpagetest: "
 
  32 module_param(dev, int, S_IRUGO);
 
  33 MODULE_PARM_DESC(dev, "MTD device number to use");
 
  35 static struct mtd_info *mtd;
 
  36 static unsigned char *writebuf;
 
  37 static unsigned char *readbuf;
 
  38 static unsigned char *bbt;
 
  45 static unsigned long next = 1;
 
  47 static inline unsigned int simple_rand(void)
 
  49         next = next * 1103515245 + 12345;
 
  50         return (unsigned int)((next / 65536) % 32768);
 
  53 static inline void simple_srand(unsigned long seed)
 
  58 static void set_random_data(unsigned char *buf, size_t len)
 
  62         for (i = 0; i < len; ++i)
 
  63                 buf[i] = simple_rand();
 
  66 static inline void clear_data(unsigned char *buf, size_t len)
 
  71 static int erase_eraseblock(int ebnum)
 
  75         loff_t addr = ebnum * mtd->erasesize;
 
  77         memset(&ei, 0, sizeof(struct erase_info));
 
  80         ei.len  = mtd->erasesize;
 
  82         err = mtd->erase(mtd, &ei);
 
  84                 printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
 
  88         if (ei.state == MTD_ERASE_FAILED) {
 
  89                 printk(PRINT_PREF "some erase error occurred at EB %d\n",
 
  97 static int erase_whole_device(void)
 
 102         printk(PRINT_PREF "erasing whole device\n");
 
 103         for (i = 0; i < ebcnt; ++i) {
 
 106                 err = erase_eraseblock(i);
 
 111         printk(PRINT_PREF "erased %u eraseblocks\n", i);
 
 115 static int write_eraseblock(int ebnum)
 
 119         loff_t addr = ebnum * mtd->erasesize;
 
 121         set_random_data(writebuf, subpgsize);
 
 122         err = mtd->write(mtd, addr, subpgsize, &written, writebuf);
 
 123         if (unlikely(err || written != subpgsize)) {
 
 124                 printk(PRINT_PREF "error: write failed at %#llx\n",
 
 126                 if (written != subpgsize) {
 
 127                         printk(PRINT_PREF "  write size: %#x\n", subpgsize);
 
 128                         printk(PRINT_PREF "  written: %#zx\n", written);
 
 130                 return err ? err : -1;
 
 135         set_random_data(writebuf, subpgsize);
 
 136         err = mtd->write(mtd, addr, subpgsize, &written, writebuf);
 
 137         if (unlikely(err || written != subpgsize)) {
 
 138                 printk(PRINT_PREF "error: write failed at %#llx\n",
 
 140                 if (written != subpgsize) {
 
 141                         printk(PRINT_PREF "  write size: %#x\n", subpgsize);
 
 142                         printk(PRINT_PREF "  written: %#zx\n", written);
 
 144                 return err ? err : -1;
 
 150 static int write_eraseblock2(int ebnum)
 
 154         loff_t addr = ebnum * mtd->erasesize;
 
 156         for (k = 1; k < 33; ++k) {
 
 157                 if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
 
 159                 set_random_data(writebuf, subpgsize * k);
 
 160                 err = mtd->write(mtd, addr, subpgsize * k, &written, writebuf);
 
 161                 if (unlikely(err || written != subpgsize * k)) {
 
 162                         printk(PRINT_PREF "error: write failed at %#llx\n",
 
 164                         if (written != subpgsize) {
 
 165                                 printk(PRINT_PREF "  write size: %#x\n",
 
 167                                 printk(PRINT_PREF "  written: %#08zx\n",
 
 170                         return err ? err : -1;
 
 172                 addr += subpgsize * k;
 
 178 static void print_subpage(unsigned char *p)
 
 182         for (i = 0; i < subpgsize; ) {
 
 183                 for (j = 0; i < subpgsize && j < 32; ++i, ++j)
 
 184                         printk("%02x", *p++);
 
 189 static int verify_eraseblock(int ebnum)
 
 193         loff_t addr = ebnum * mtd->erasesize;
 
 195         set_random_data(writebuf, subpgsize);
 
 196         clear_data(readbuf, subpgsize);
 
 198         err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
 
 199         if (unlikely(err || read != subpgsize)) {
 
 200                 if (err == -EUCLEAN && read == subpgsize) {
 
 201                         printk(PRINT_PREF "ECC correction at %#llx\n",
 
 205                         printk(PRINT_PREF "error: read failed at %#llx\n",
 
 207                         return err ? err : -1;
 
 210         if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
 
 211                 printk(PRINT_PREF "error: verify failed at %#llx\n",
 
 213                 printk(PRINT_PREF "------------- written----------------\n");
 
 214                 print_subpage(writebuf);
 
 215                 printk(PRINT_PREF "------------- read ------------------\n");
 
 216                 print_subpage(readbuf);
 
 217                 printk(PRINT_PREF "-------------------------------------\n");
 
 223         set_random_data(writebuf, subpgsize);
 
 224         clear_data(readbuf, subpgsize);
 
 226         err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
 
 227         if (unlikely(err || read != subpgsize)) {
 
 228                 if (err == -EUCLEAN && read == subpgsize) {
 
 229                         printk(PRINT_PREF "ECC correction at %#llx\n",
 
 233                         printk(PRINT_PREF "error: read failed at %#llx\n",
 
 235                         return err ? err : -1;
 
 238         if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
 
 239                 printk(PRINT_PREF "error: verify failed at %#llx\n",
 
 241                 printk(PRINT_PREF "------------- written----------------\n");
 
 242                 print_subpage(writebuf);
 
 243                 printk(PRINT_PREF "------------- read ------------------\n");
 
 244                 print_subpage(readbuf);
 
 245                 printk(PRINT_PREF "-------------------------------------\n");
 
 252 static int verify_eraseblock2(int ebnum)
 
 256         loff_t addr = ebnum * mtd->erasesize;
 
 258         for (k = 1; k < 33; ++k) {
 
 259                 if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
 
 261                 set_random_data(writebuf, subpgsize * k);
 
 262                 clear_data(readbuf, subpgsize * k);
 
 264                 err = mtd->read(mtd, addr, subpgsize * k, &read, readbuf);
 
 265                 if (unlikely(err || read != subpgsize * k)) {
 
 266                         if (err == -EUCLEAN && read == subpgsize * k) {
 
 267                                 printk(PRINT_PREF "ECC correction at %#llx\n",
 
 271                                 printk(PRINT_PREF "error: read failed at "
 
 272                                        "%#llx\n", (long long)addr);
 
 273                                 return err ? err : -1;
 
 276                 if (unlikely(memcmp(readbuf, writebuf, subpgsize * k))) {
 
 277                         printk(PRINT_PREF "error: verify failed at %#llx\n",
 
 281                 addr += subpgsize * k;
 
 287 static int verify_eraseblock_ff(int ebnum)
 
 292         loff_t addr = ebnum * mtd->erasesize;
 
 294         memset(writebuf, 0xff, subpgsize);
 
 295         for (j = 0; j < mtd->erasesize / subpgsize; ++j) {
 
 296                 clear_data(readbuf, subpgsize);
 
 298                 err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
 
 299                 if (unlikely(err || read != subpgsize)) {
 
 300                         if (err == -EUCLEAN && read == subpgsize) {
 
 301                                 printk(PRINT_PREF "ECC correction at %#llx\n",
 
 305                                 printk(PRINT_PREF "error: read failed at "
 
 306                                        "%#llx\n", (long long)addr);
 
 307                                 return err ? err : -1;
 
 310                 if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
 
 311                         printk(PRINT_PREF "error: verify 0xff failed at "
 
 312                                "%#llx\n", (long long)addr);
 
 321 static int verify_all_eraseblocks_ff(void)
 
 326         printk(PRINT_PREF "verifying all eraseblocks for 0xff\n");
 
 327         for (i = 0; i < ebcnt; ++i) {
 
 330                 err = verify_eraseblock_ff(i);
 
 334                         printk(PRINT_PREF "verified up to eraseblock %u\n", i);
 
 337         printk(PRINT_PREF "verified %u eraseblocks\n", i);
 
 341 static int is_block_bad(int ebnum)
 
 343         loff_t addr = ebnum * mtd->erasesize;
 
 346         ret = mtd->block_isbad(mtd, addr);
 
 348                 printk(PRINT_PREF "block %d is bad\n", ebnum);
 
 352 static int scan_for_bad_eraseblocks(void)
 
 356         bbt = kmalloc(ebcnt, GFP_KERNEL);
 
 358                 printk(PRINT_PREF "error: cannot allocate memory\n");
 
 361         memset(bbt, 0 , ebcnt);
 
 363         printk(PRINT_PREF "scanning for bad eraseblocks\n");
 
 364         for (i = 0; i < ebcnt; ++i) {
 
 365                 bbt[i] = is_block_bad(i) ? 1 : 0;
 
 370         printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
 
 374 static int __init mtd_subpagetest_init(void)
 
 380         printk(KERN_INFO "\n");
 
 381         printk(KERN_INFO "=================================================\n");
 
 382         printk(PRINT_PREF "MTD device: %d\n", dev);
 
 384         mtd = get_mtd_device(NULL, dev);
 
 387                 printk(PRINT_PREF "error: cannot get MTD device\n");
 
 391         if (mtd->type != MTD_NANDFLASH) {
 
 392                 printk(PRINT_PREF "this test requires NAND flash\n");
 
 396         subpgsize = mtd->writesize >> mtd->subpage_sft;
 
 397         printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
 
 398                "page size %u, subpage size %u, count of eraseblocks %u, "
 
 399                "pages per eraseblock %u, OOB size %u\n",
 
 400                (unsigned long long)mtd->size, mtd->erasesize,
 
 401                mtd->writesize, subpgsize, ebcnt, pgcnt, mtd->oobsize);
 
 404         bufsize = subpgsize * 32;
 
 405         writebuf = kmalloc(bufsize, GFP_KERNEL);
 
 407                 printk(PRINT_PREF "error: cannot allocate memory\n");
 
 410         readbuf = kmalloc(bufsize, GFP_KERNEL);
 
 412                 printk(PRINT_PREF "error: cannot allocate memory\n");
 
 417         do_div(tmp, mtd->erasesize);
 
 419         pgcnt = mtd->erasesize / mtd->writesize;
 
 421         err = scan_for_bad_eraseblocks();
 
 425         err = erase_whole_device();
 
 429         printk(PRINT_PREF "writing whole device\n");
 
 431         for (i = 0; i < ebcnt; ++i) {
 
 434                 err = write_eraseblock(i);
 
 438                         printk(PRINT_PREF "written up to eraseblock %u\n", i);
 
 441         printk(PRINT_PREF "written %u eraseblocks\n", i);
 
 444         printk(PRINT_PREF "verifying all eraseblocks\n");
 
 445         for (i = 0; i < ebcnt; ++i) {
 
 448                 err = verify_eraseblock(i);
 
 452                         printk(PRINT_PREF "verified up to eraseblock %u\n", i);
 
 455         printk(PRINT_PREF "verified %u eraseblocks\n", i);
 
 457         err = erase_whole_device();
 
 461         err = verify_all_eraseblocks_ff();
 
 465         /* Write all eraseblocks */
 
 467         printk(PRINT_PREF "writing whole device\n");
 
 468         for (i = 0; i < ebcnt; ++i) {
 
 471                 err = write_eraseblock2(i);
 
 475                         printk(PRINT_PREF "written up to eraseblock %u\n", i);
 
 478         printk(PRINT_PREF "written %u eraseblocks\n", i);
 
 480         /* Check all eraseblocks */
 
 482         printk(PRINT_PREF "verifying all eraseblocks\n");
 
 483         for (i = 0; i < ebcnt; ++i) {
 
 486                 err = verify_eraseblock2(i);
 
 490                         printk(PRINT_PREF "verified up to eraseblock %u\n", i);
 
 493         printk(PRINT_PREF "verified %u eraseblocks\n", i);
 
 495         err = erase_whole_device();
 
 499         err = verify_all_eraseblocks_ff();
 
 503         printk(PRINT_PREF "finished with %d errors\n", errcnt);
 
 511                 printk(PRINT_PREF "error %d occurred\n", err);
 
 512         printk(KERN_INFO "=================================================\n");
 
 515 module_init(mtd_subpagetest_init);
 
 517 static void __exit mtd_subpagetest_exit(void)
 
 521 module_exit(mtd_subpagetest_exit);
 
 523 MODULE_DESCRIPTION("Subpage test module");
 
 524 MODULE_AUTHOR("Adrian Hunter");
 
 525 MODULE_LICENSE("GPL");