Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2006-2007 Nokia Corporation
0004  *
0005  * Test sub-page read and write on MTD device.
0006  * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
0007  */
0008 
0009 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0010 
0011 #include <linux/init.h>
0012 #include <linux/module.h>
0013 #include <linux/moduleparam.h>
0014 #include <linux/err.h>
0015 #include <linux/mtd/mtd.h>
0016 #include <linux/slab.h>
0017 #include <linux/sched.h>
0018 #include <linux/random.h>
0019 
0020 #include "mtd_test.h"
0021 
0022 static int dev = -EINVAL;
0023 module_param(dev, int, S_IRUGO);
0024 MODULE_PARM_DESC(dev, "MTD device number to use");
0025 
0026 static struct mtd_info *mtd;
0027 static unsigned char *writebuf;
0028 static unsigned char *readbuf;
0029 static unsigned char *bbt;
0030 
0031 static int subpgsize;
0032 static int bufsize;
0033 static int ebcnt;
0034 static int pgcnt;
0035 static int errcnt;
0036 static struct rnd_state rnd_state;
0037 
0038 static inline void clear_data(unsigned char *buf, size_t len)
0039 {
0040     memset(buf, 0, len);
0041 }
0042 
0043 static int write_eraseblock(int ebnum)
0044 {
0045     size_t written;
0046     int err = 0;
0047     loff_t addr = (loff_t)ebnum * mtd->erasesize;
0048 
0049     prandom_bytes_state(&rnd_state, writebuf, subpgsize);
0050     err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
0051     if (unlikely(err || written != subpgsize)) {
0052         pr_err("error: write failed at %#llx\n",
0053                (long long)addr);
0054         if (written != subpgsize) {
0055             pr_err("  write size: %#x\n", subpgsize);
0056             pr_err("  written: %#zx\n", written);
0057         }
0058         return err ? err : -1;
0059     }
0060 
0061     addr += subpgsize;
0062 
0063     prandom_bytes_state(&rnd_state, writebuf, subpgsize);
0064     err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
0065     if (unlikely(err || written != subpgsize)) {
0066         pr_err("error: write failed at %#llx\n",
0067                (long long)addr);
0068         if (written != subpgsize) {
0069             pr_err("  write size: %#x\n", subpgsize);
0070             pr_err("  written: %#zx\n", written);
0071         }
0072         return err ? err : -1;
0073     }
0074 
0075     return err;
0076 }
0077 
0078 static int write_eraseblock2(int ebnum)
0079 {
0080     size_t written;
0081     int err = 0, k;
0082     loff_t addr = (loff_t)ebnum * mtd->erasesize;
0083 
0084     for (k = 1; k < 33; ++k) {
0085         if (addr + (subpgsize * k) > (loff_t)(ebnum + 1) * mtd->erasesize)
0086             break;
0087         prandom_bytes_state(&rnd_state, writebuf, subpgsize * k);
0088         err = mtd_write(mtd, addr, subpgsize * k, &written, writebuf);
0089         if (unlikely(err || written != subpgsize * k)) {
0090             pr_err("error: write failed at %#llx\n",
0091                    (long long)addr);
0092             if (written != subpgsize * k) {
0093                 pr_err("  write size: %#x\n",
0094                        subpgsize * k);
0095                 pr_err("  written: %#08zx\n",
0096                        written);
0097             }
0098             return err ? err : -1;
0099         }
0100         addr += subpgsize * k;
0101     }
0102 
0103     return err;
0104 }
0105 
0106 static void print_subpage(unsigned char *p)
0107 {
0108     int i, j;
0109 
0110     for (i = 0; i < subpgsize; ) {
0111         for (j = 0; i < subpgsize && j < 32; ++i, ++j)
0112             printk("%02x", *p++);
0113         printk("\n");
0114     }
0115 }
0116 
0117 static int verify_eraseblock(int ebnum)
0118 {
0119     size_t read;
0120     int err = 0;
0121     loff_t addr = (loff_t)ebnum * mtd->erasesize;
0122 
0123     prandom_bytes_state(&rnd_state, writebuf, subpgsize);
0124     clear_data(readbuf, subpgsize);
0125     err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
0126     if (unlikely(err || read != subpgsize)) {
0127         if (mtd_is_bitflip(err) && read == subpgsize) {
0128             pr_info("ECC correction at %#llx\n",
0129                    (long long)addr);
0130             err = 0;
0131         } else {
0132             pr_err("error: read failed at %#llx\n",
0133                    (long long)addr);
0134             return err ? err : -1;
0135         }
0136     }
0137     if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
0138         pr_err("error: verify failed at %#llx\n",
0139                (long long)addr);
0140         pr_info("------------- written----------------\n");
0141         print_subpage(writebuf);
0142         pr_info("------------- read ------------------\n");
0143         print_subpage(readbuf);
0144         pr_info("-------------------------------------\n");
0145         errcnt += 1;
0146     }
0147 
0148     addr += subpgsize;
0149 
0150     prandom_bytes_state(&rnd_state, writebuf, subpgsize);
0151     clear_data(readbuf, subpgsize);
0152     err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
0153     if (unlikely(err || read != subpgsize)) {
0154         if (mtd_is_bitflip(err) && read == subpgsize) {
0155             pr_info("ECC correction at %#llx\n",
0156                    (long long)addr);
0157             err = 0;
0158         } else {
0159             pr_err("error: read failed at %#llx\n",
0160                    (long long)addr);
0161             return err ? err : -1;
0162         }
0163     }
0164     if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
0165         pr_info("error: verify failed at %#llx\n",
0166                (long long)addr);
0167         pr_info("------------- written----------------\n");
0168         print_subpage(writebuf);
0169         pr_info("------------- read ------------------\n");
0170         print_subpage(readbuf);
0171         pr_info("-------------------------------------\n");
0172         errcnt += 1;
0173     }
0174 
0175     return err;
0176 }
0177 
0178 static int verify_eraseblock2(int ebnum)
0179 {
0180     size_t read;
0181     int err = 0, k;
0182     loff_t addr = (loff_t)ebnum * mtd->erasesize;
0183 
0184     for (k = 1; k < 33; ++k) {
0185         if (addr + (subpgsize * k) > (loff_t)(ebnum + 1) * mtd->erasesize)
0186             break;
0187         prandom_bytes_state(&rnd_state, writebuf, subpgsize * k);
0188         clear_data(readbuf, subpgsize * k);
0189         err = mtd_read(mtd, addr, subpgsize * k, &read, readbuf);
0190         if (unlikely(err || read != subpgsize * k)) {
0191             if (mtd_is_bitflip(err) && read == subpgsize * k) {
0192                 pr_info("ECC correction at %#llx\n",
0193                        (long long)addr);
0194                 err = 0;
0195             } else {
0196                 pr_err("error: read failed at "
0197                        "%#llx\n", (long long)addr);
0198                 return err ? err : -1;
0199             }
0200         }
0201         if (unlikely(memcmp(readbuf, writebuf, subpgsize * k))) {
0202             pr_err("error: verify failed at %#llx\n",
0203                    (long long)addr);
0204             errcnt += 1;
0205         }
0206         addr += subpgsize * k;
0207     }
0208 
0209     return err;
0210 }
0211 
0212 static int verify_eraseblock_ff(int ebnum)
0213 {
0214     uint32_t j;
0215     size_t read;
0216     int err = 0;
0217     loff_t addr = (loff_t)ebnum * mtd->erasesize;
0218 
0219     memset(writebuf, 0xff, subpgsize);
0220     for (j = 0; j < mtd->erasesize / subpgsize; ++j) {
0221         clear_data(readbuf, subpgsize);
0222         err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
0223         if (unlikely(err || read != subpgsize)) {
0224             if (mtd_is_bitflip(err) && read == subpgsize) {
0225                 pr_info("ECC correction at %#llx\n",
0226                        (long long)addr);
0227                 err = 0;
0228             } else {
0229                 pr_err("error: read failed at "
0230                        "%#llx\n", (long long)addr);
0231                 return err ? err : -1;
0232             }
0233         }
0234         if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
0235             pr_err("error: verify 0xff failed at "
0236                    "%#llx\n", (long long)addr);
0237             errcnt += 1;
0238         }
0239         addr += subpgsize;
0240     }
0241 
0242     return err;
0243 }
0244 
0245 static int verify_all_eraseblocks_ff(void)
0246 {
0247     int err;
0248     unsigned int i;
0249 
0250     pr_info("verifying all eraseblocks for 0xff\n");
0251     for (i = 0; i < ebcnt; ++i) {
0252         if (bbt[i])
0253             continue;
0254         err = verify_eraseblock_ff(i);
0255         if (err)
0256             return err;
0257         if (i % 256 == 0)
0258             pr_info("verified up to eraseblock %u\n", i);
0259 
0260         err = mtdtest_relax();
0261         if (err)
0262             return err;
0263     }
0264     pr_info("verified %u eraseblocks\n", i);
0265     return 0;
0266 }
0267 
0268 static int __init mtd_subpagetest_init(void)
0269 {
0270     int err = 0;
0271     uint32_t i;
0272     uint64_t tmp;
0273 
0274     printk(KERN_INFO "\n");
0275     printk(KERN_INFO "=================================================\n");
0276 
0277     if (dev < 0) {
0278         pr_info("Please specify a valid mtd-device via module parameter\n");
0279         pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
0280         return -EINVAL;
0281     }
0282 
0283     pr_info("MTD device: %d\n", dev);
0284 
0285     mtd = get_mtd_device(NULL, dev);
0286     if (IS_ERR(mtd)) {
0287         err = PTR_ERR(mtd);
0288         pr_err("error: cannot get MTD device\n");
0289         return err;
0290     }
0291 
0292     if (!mtd_type_is_nand(mtd)) {
0293         pr_info("this test requires NAND flash\n");
0294         goto out;
0295     }
0296 
0297     subpgsize = mtd->writesize >> mtd->subpage_sft;
0298     tmp = mtd->size;
0299     do_div(tmp, mtd->erasesize);
0300     ebcnt = tmp;
0301     pgcnt = mtd->erasesize / mtd->writesize;
0302 
0303     pr_info("MTD device size %llu, eraseblock size %u, "
0304            "page size %u, subpage size %u, count of eraseblocks %u, "
0305            "pages per eraseblock %u, OOB size %u\n",
0306            (unsigned long long)mtd->size, mtd->erasesize,
0307            mtd->writesize, subpgsize, ebcnt, pgcnt, mtd->oobsize);
0308 
0309     err = -ENOMEM;
0310     bufsize = subpgsize * 32;
0311     writebuf = kmalloc(bufsize, GFP_KERNEL);
0312     if (!writebuf)
0313         goto out;
0314     readbuf = kmalloc(bufsize, GFP_KERNEL);
0315     if (!readbuf)
0316         goto out;
0317     bbt = kzalloc(ebcnt, GFP_KERNEL);
0318     if (!bbt)
0319         goto out;
0320 
0321     err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
0322     if (err)
0323         goto out;
0324 
0325     err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
0326     if (err)
0327         goto out;
0328 
0329     pr_info("writing whole device\n");
0330     prandom_seed_state(&rnd_state, 1);
0331     for (i = 0; i < ebcnt; ++i) {
0332         if (bbt[i])
0333             continue;
0334         err = write_eraseblock(i);
0335         if (unlikely(err))
0336             goto out;
0337         if (i % 256 == 0)
0338             pr_info("written up to eraseblock %u\n", i);
0339 
0340         err = mtdtest_relax();
0341         if (err)
0342             goto out;
0343     }
0344     pr_info("written %u eraseblocks\n", i);
0345 
0346     prandom_seed_state(&rnd_state, 1);
0347     pr_info("verifying all eraseblocks\n");
0348     for (i = 0; i < ebcnt; ++i) {
0349         if (bbt[i])
0350             continue;
0351         err = verify_eraseblock(i);
0352         if (unlikely(err))
0353             goto out;
0354         if (i % 256 == 0)
0355             pr_info("verified up to eraseblock %u\n", i);
0356 
0357         err = mtdtest_relax();
0358         if (err)
0359             goto out;
0360     }
0361     pr_info("verified %u eraseblocks\n", i);
0362 
0363     err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
0364     if (err)
0365         goto out;
0366 
0367     err = verify_all_eraseblocks_ff();
0368     if (err)
0369         goto out;
0370 
0371     /* Write all eraseblocks */
0372     prandom_seed_state(&rnd_state, 3);
0373     pr_info("writing whole device\n");
0374     for (i = 0; i < ebcnt; ++i) {
0375         if (bbt[i])
0376             continue;
0377         err = write_eraseblock2(i);
0378         if (unlikely(err))
0379             goto out;
0380         if (i % 256 == 0)
0381             pr_info("written up to eraseblock %u\n", i);
0382 
0383         err = mtdtest_relax();
0384         if (err)
0385             goto out;
0386     }
0387     pr_info("written %u eraseblocks\n", i);
0388 
0389     /* Check all eraseblocks */
0390     prandom_seed_state(&rnd_state, 3);
0391     pr_info("verifying all eraseblocks\n");
0392     for (i = 0; i < ebcnt; ++i) {
0393         if (bbt[i])
0394             continue;
0395         err = verify_eraseblock2(i);
0396         if (unlikely(err))
0397             goto out;
0398         if (i % 256 == 0)
0399             pr_info("verified up to eraseblock %u\n", i);
0400 
0401         err = mtdtest_relax();
0402         if (err)
0403             goto out;
0404     }
0405     pr_info("verified %u eraseblocks\n", i);
0406 
0407     err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
0408     if (err)
0409         goto out;
0410 
0411     err = verify_all_eraseblocks_ff();
0412     if (err)
0413         goto out;
0414 
0415     pr_info("finished with %d errors\n", errcnt);
0416 
0417 out:
0418     kfree(bbt);
0419     kfree(readbuf);
0420     kfree(writebuf);
0421     put_mtd_device(mtd);
0422     if (err)
0423         pr_info("error %d occurred\n", err);
0424     printk(KERN_INFO "=================================================\n");
0425     return err;
0426 }
0427 module_init(mtd_subpagetest_init);
0428 
0429 static void __exit mtd_subpagetest_exit(void)
0430 {
0431     return;
0432 }
0433 module_exit(mtd_subpagetest_exit);
0434 
0435 MODULE_DESCRIPTION("Subpage test module");
0436 MODULE_AUTHOR("Adrian Hunter");
0437 MODULE_LICENSE("GPL");