1*4cd10358SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2bf60862aSArtem Bityutskiy /* 3bf60862aSArtem Bityutskiy * Copyright (C) 2006-2007 Nokia Corporation 4bf60862aSArtem Bityutskiy * 5bf60862aSArtem Bityutskiy * Test sub-page read and write on MTD device. 6bf60862aSArtem Bityutskiy * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> 7bf60862aSArtem Bityutskiy */ 8bf60862aSArtem Bityutskiy 9cd66a2dfSVikram Narayanan #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10cd66a2dfSVikram Narayanan 11bf60862aSArtem Bityutskiy #include <linux/init.h> 12bf60862aSArtem Bityutskiy #include <linux/module.h> 13bf60862aSArtem Bityutskiy #include <linux/moduleparam.h> 14bf60862aSArtem Bityutskiy #include <linux/err.h> 15bf60862aSArtem Bityutskiy #include <linux/mtd/mtd.h> 165a0e3ad6STejun Heo #include <linux/slab.h> 17bf60862aSArtem Bityutskiy #include <linux/sched.h> 18a312b78bSAkinobu Mita #include <linux/random.h> 19bf60862aSArtem Bityutskiy 20725cd71cSAkinobu Mita #include "mtd_test.h" 21725cd71cSAkinobu Mita 227406060eSWolfram Sang static int dev = -EINVAL; 23bf60862aSArtem Bityutskiy module_param(dev, int, S_IRUGO); 24bf60862aSArtem Bityutskiy MODULE_PARM_DESC(dev, "MTD device number to use"); 25bf60862aSArtem Bityutskiy 26bf60862aSArtem Bityutskiy static struct mtd_info *mtd; 27bf60862aSArtem Bityutskiy static unsigned char *writebuf; 28bf60862aSArtem Bityutskiy static unsigned char *readbuf; 29bf60862aSArtem Bityutskiy static unsigned char *bbt; 30bf60862aSArtem Bityutskiy 31bf60862aSArtem Bityutskiy static int subpgsize; 32bf60862aSArtem Bityutskiy static int bufsize; 33bf60862aSArtem Bityutskiy static int ebcnt; 34bf60862aSArtem Bityutskiy static int pgcnt; 35bf60862aSArtem Bityutskiy static int errcnt; 36a312b78bSAkinobu Mita static struct rnd_state rnd_state; 37bf60862aSArtem Bityutskiy 38bf60862aSArtem Bityutskiy static inline void clear_data(unsigned char *buf, size_t len) 39bf60862aSArtem Bityutskiy { 40bf60862aSArtem Bityutskiy memset(buf, 0, len); 41bf60862aSArtem Bityutskiy } 42bf60862aSArtem Bityutskiy 43bf60862aSArtem Bityutskiy static int write_eraseblock(int ebnum) 44bf60862aSArtem Bityutskiy { 4530fa9848SArtem Bityutskiy size_t written; 46bf60862aSArtem Bityutskiy int err = 0; 471001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 48bf60862aSArtem Bityutskiy 49a312b78bSAkinobu Mita prandom_bytes_state(&rnd_state, writebuf, subpgsize); 50eda95cbfSArtem Bityutskiy err = mtd_write(mtd, addr, subpgsize, &written, writebuf); 51bf60862aSArtem Bityutskiy if (unlikely(err || written != subpgsize)) { 52cd66a2dfSVikram Narayanan pr_err("error: write failed at %#llx\n", 53bf60862aSArtem Bityutskiy (long long)addr); 54bf60862aSArtem Bityutskiy if (written != subpgsize) { 55cd66a2dfSVikram Narayanan pr_err(" write size: %#x\n", subpgsize); 56cd66a2dfSVikram Narayanan pr_err(" written: %#zx\n", written); 57bf60862aSArtem Bityutskiy } 58bf60862aSArtem Bityutskiy return err ? err : -1; 59bf60862aSArtem Bityutskiy } 60bf60862aSArtem Bityutskiy 61bf60862aSArtem Bityutskiy addr += subpgsize; 62bf60862aSArtem Bityutskiy 63a312b78bSAkinobu Mita prandom_bytes_state(&rnd_state, writebuf, subpgsize); 64eda95cbfSArtem Bityutskiy err = mtd_write(mtd, addr, subpgsize, &written, writebuf); 65bf60862aSArtem Bityutskiy if (unlikely(err || written != subpgsize)) { 66cd66a2dfSVikram Narayanan pr_err("error: write failed at %#llx\n", 67bf60862aSArtem Bityutskiy (long long)addr); 68bf60862aSArtem Bityutskiy if (written != subpgsize) { 69cd66a2dfSVikram Narayanan pr_err(" write size: %#x\n", subpgsize); 70cd66a2dfSVikram Narayanan pr_err(" written: %#zx\n", written); 71bf60862aSArtem Bityutskiy } 72bf60862aSArtem Bityutskiy return err ? err : -1; 73bf60862aSArtem Bityutskiy } 74bf60862aSArtem Bityutskiy 75bf60862aSArtem Bityutskiy return err; 76bf60862aSArtem Bityutskiy } 77bf60862aSArtem Bityutskiy 78bf60862aSArtem Bityutskiy static int write_eraseblock2(int ebnum) 79bf60862aSArtem Bityutskiy { 8030fa9848SArtem Bityutskiy size_t written; 81bf60862aSArtem Bityutskiy int err = 0, k; 821001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 83bf60862aSArtem Bityutskiy 84bf60862aSArtem Bityutskiy for (k = 1; k < 33; ++k) { 85b9da8baeSBrian Norris if (addr + (subpgsize * k) > (loff_t)(ebnum + 1) * mtd->erasesize) 86bf60862aSArtem Bityutskiy break; 87a312b78bSAkinobu Mita prandom_bytes_state(&rnd_state, writebuf, subpgsize * k); 88eda95cbfSArtem Bityutskiy err = mtd_write(mtd, addr, subpgsize * k, &written, writebuf); 89bf60862aSArtem Bityutskiy if (unlikely(err || written != subpgsize * k)) { 90cd66a2dfSVikram Narayanan pr_err("error: write failed at %#llx\n", 91bf60862aSArtem Bityutskiy (long long)addr); 92c46adf09SXiaolei Li if (written != subpgsize * k) { 93cd66a2dfSVikram Narayanan pr_err(" write size: %#x\n", 94bf60862aSArtem Bityutskiy subpgsize * k); 95cd66a2dfSVikram Narayanan pr_err(" written: %#08zx\n", 96bf60862aSArtem Bityutskiy written); 97bf60862aSArtem Bityutskiy } 98bf60862aSArtem Bityutskiy return err ? err : -1; 99bf60862aSArtem Bityutskiy } 100bf60862aSArtem Bityutskiy addr += subpgsize * k; 101bf60862aSArtem Bityutskiy } 102bf60862aSArtem Bityutskiy 103bf60862aSArtem Bityutskiy return err; 104bf60862aSArtem Bityutskiy } 105bf60862aSArtem Bityutskiy 106bf60862aSArtem Bityutskiy static void print_subpage(unsigned char *p) 107bf60862aSArtem Bityutskiy { 108bf60862aSArtem Bityutskiy int i, j; 109bf60862aSArtem Bityutskiy 110bf60862aSArtem Bityutskiy for (i = 0; i < subpgsize; ) { 111bf60862aSArtem Bityutskiy for (j = 0; i < subpgsize && j < 32; ++i, ++j) 112bf60862aSArtem Bityutskiy printk("%02x", *p++); 113bf60862aSArtem Bityutskiy printk("\n"); 114bf60862aSArtem Bityutskiy } 115bf60862aSArtem Bityutskiy } 116bf60862aSArtem Bityutskiy 117bf60862aSArtem Bityutskiy static int verify_eraseblock(int ebnum) 118bf60862aSArtem Bityutskiy { 11930fa9848SArtem Bityutskiy size_t read; 120bf60862aSArtem Bityutskiy int err = 0; 1211001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 122bf60862aSArtem Bityutskiy 123a312b78bSAkinobu Mita prandom_bytes_state(&rnd_state, writebuf, subpgsize); 124bf60862aSArtem Bityutskiy clear_data(readbuf, subpgsize); 125329ad399SArtem Bityutskiy err = mtd_read(mtd, addr, subpgsize, &read, readbuf); 126bf60862aSArtem Bityutskiy if (unlikely(err || read != subpgsize)) { 127d57f4054SBrian Norris if (mtd_is_bitflip(err) && read == subpgsize) { 128cd66a2dfSVikram Narayanan pr_info("ECC correction at %#llx\n", 129bf60862aSArtem Bityutskiy (long long)addr); 130bf60862aSArtem Bityutskiy err = 0; 131bf60862aSArtem Bityutskiy } else { 132cd66a2dfSVikram Narayanan pr_err("error: read failed at %#llx\n", 133bf60862aSArtem Bityutskiy (long long)addr); 134bf60862aSArtem Bityutskiy return err ? err : -1; 135bf60862aSArtem Bityutskiy } 136bf60862aSArtem Bityutskiy } 137bf60862aSArtem Bityutskiy if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { 138cd66a2dfSVikram Narayanan pr_err("error: verify failed at %#llx\n", 139bf60862aSArtem Bityutskiy (long long)addr); 140cd66a2dfSVikram Narayanan pr_info("------------- written----------------\n"); 141bf60862aSArtem Bityutskiy print_subpage(writebuf); 142cd66a2dfSVikram Narayanan pr_info("------------- read ------------------\n"); 143bf60862aSArtem Bityutskiy print_subpage(readbuf); 144cd66a2dfSVikram Narayanan pr_info("-------------------------------------\n"); 145bf60862aSArtem Bityutskiy errcnt += 1; 146bf60862aSArtem Bityutskiy } 147bf60862aSArtem Bityutskiy 148bf60862aSArtem Bityutskiy addr += subpgsize; 149bf60862aSArtem Bityutskiy 150a312b78bSAkinobu Mita prandom_bytes_state(&rnd_state, writebuf, subpgsize); 151bf60862aSArtem Bityutskiy clear_data(readbuf, subpgsize); 152329ad399SArtem Bityutskiy err = mtd_read(mtd, addr, subpgsize, &read, readbuf); 153bf60862aSArtem Bityutskiy if (unlikely(err || read != subpgsize)) { 154d57f4054SBrian Norris if (mtd_is_bitflip(err) && read == subpgsize) { 155cd66a2dfSVikram Narayanan pr_info("ECC correction at %#llx\n", 156bf60862aSArtem Bityutskiy (long long)addr); 157bf60862aSArtem Bityutskiy err = 0; 158bf60862aSArtem Bityutskiy } else { 159cd66a2dfSVikram Narayanan pr_err("error: read failed at %#llx\n", 160bf60862aSArtem Bityutskiy (long long)addr); 161bf60862aSArtem Bityutskiy return err ? err : -1; 162bf60862aSArtem Bityutskiy } 163bf60862aSArtem Bityutskiy } 164bf60862aSArtem Bityutskiy if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { 165cd66a2dfSVikram Narayanan pr_info("error: verify failed at %#llx\n", 166bf60862aSArtem Bityutskiy (long long)addr); 167cd66a2dfSVikram Narayanan pr_info("------------- written----------------\n"); 168bf60862aSArtem Bityutskiy print_subpage(writebuf); 169cd66a2dfSVikram Narayanan pr_info("------------- read ------------------\n"); 170bf60862aSArtem Bityutskiy print_subpage(readbuf); 171cd66a2dfSVikram Narayanan pr_info("-------------------------------------\n"); 172bf60862aSArtem Bityutskiy errcnt += 1; 173bf60862aSArtem Bityutskiy } 174bf60862aSArtem Bityutskiy 175bf60862aSArtem Bityutskiy return err; 176bf60862aSArtem Bityutskiy } 177bf60862aSArtem Bityutskiy 178bf60862aSArtem Bityutskiy static int verify_eraseblock2(int ebnum) 179bf60862aSArtem Bityutskiy { 18030fa9848SArtem Bityutskiy size_t read; 181bf60862aSArtem Bityutskiy int err = 0, k; 1821001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 183bf60862aSArtem Bityutskiy 184bf60862aSArtem Bityutskiy for (k = 1; k < 33; ++k) { 185b9da8baeSBrian Norris if (addr + (subpgsize * k) > (loff_t)(ebnum + 1) * mtd->erasesize) 186bf60862aSArtem Bityutskiy break; 187a312b78bSAkinobu Mita prandom_bytes_state(&rnd_state, writebuf, subpgsize * k); 188bf60862aSArtem Bityutskiy clear_data(readbuf, subpgsize * k); 189329ad399SArtem Bityutskiy err = mtd_read(mtd, addr, subpgsize * k, &read, readbuf); 190bf60862aSArtem Bityutskiy if (unlikely(err || read != subpgsize * k)) { 191d57f4054SBrian Norris if (mtd_is_bitflip(err) && read == subpgsize * k) { 192cd66a2dfSVikram Narayanan pr_info("ECC correction at %#llx\n", 193bf60862aSArtem Bityutskiy (long long)addr); 194bf60862aSArtem Bityutskiy err = 0; 195bf60862aSArtem Bityutskiy } else { 196cd66a2dfSVikram Narayanan pr_err("error: read failed at " 197bf60862aSArtem Bityutskiy "%#llx\n", (long long)addr); 198bf60862aSArtem Bityutskiy return err ? err : -1; 199bf60862aSArtem Bityutskiy } 200bf60862aSArtem Bityutskiy } 201bf60862aSArtem Bityutskiy if (unlikely(memcmp(readbuf, writebuf, subpgsize * k))) { 202cd66a2dfSVikram Narayanan pr_err("error: verify failed at %#llx\n", 203bf60862aSArtem Bityutskiy (long long)addr); 204bf60862aSArtem Bityutskiy errcnt += 1; 205bf60862aSArtem Bityutskiy } 206bf60862aSArtem Bityutskiy addr += subpgsize * k; 207bf60862aSArtem Bityutskiy } 208bf60862aSArtem Bityutskiy 209bf60862aSArtem Bityutskiy return err; 210bf60862aSArtem Bityutskiy } 211bf60862aSArtem Bityutskiy 212bf60862aSArtem Bityutskiy static int verify_eraseblock_ff(int ebnum) 213bf60862aSArtem Bityutskiy { 214bf60862aSArtem Bityutskiy uint32_t j; 21530fa9848SArtem Bityutskiy size_t read; 216bf60862aSArtem Bityutskiy int err = 0; 2171001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 218bf60862aSArtem Bityutskiy 219bf60862aSArtem Bityutskiy memset(writebuf, 0xff, subpgsize); 220bf60862aSArtem Bityutskiy for (j = 0; j < mtd->erasesize / subpgsize; ++j) { 221bf60862aSArtem Bityutskiy clear_data(readbuf, subpgsize); 222329ad399SArtem Bityutskiy err = mtd_read(mtd, addr, subpgsize, &read, readbuf); 223bf60862aSArtem Bityutskiy if (unlikely(err || read != subpgsize)) { 224d57f4054SBrian Norris if (mtd_is_bitflip(err) && read == subpgsize) { 225cd66a2dfSVikram Narayanan pr_info("ECC correction at %#llx\n", 226bf60862aSArtem Bityutskiy (long long)addr); 227bf60862aSArtem Bityutskiy err = 0; 228bf60862aSArtem Bityutskiy } else { 229cd66a2dfSVikram Narayanan pr_err("error: read failed at " 230bf60862aSArtem Bityutskiy "%#llx\n", (long long)addr); 231bf60862aSArtem Bityutskiy return err ? err : -1; 232bf60862aSArtem Bityutskiy } 233bf60862aSArtem Bityutskiy } 234bf60862aSArtem Bityutskiy if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { 235cd66a2dfSVikram Narayanan pr_err("error: verify 0xff failed at " 236bf60862aSArtem Bityutskiy "%#llx\n", (long long)addr); 237bf60862aSArtem Bityutskiy errcnt += 1; 238bf60862aSArtem Bityutskiy } 239bf60862aSArtem Bityutskiy addr += subpgsize; 240bf60862aSArtem Bityutskiy } 241bf60862aSArtem Bityutskiy 242bf60862aSArtem Bityutskiy return err; 243bf60862aSArtem Bityutskiy } 244bf60862aSArtem Bityutskiy 245bf60862aSArtem Bityutskiy static int verify_all_eraseblocks_ff(void) 246bf60862aSArtem Bityutskiy { 247bf60862aSArtem Bityutskiy int err; 248bf60862aSArtem Bityutskiy unsigned int i; 249bf60862aSArtem Bityutskiy 250cd66a2dfSVikram Narayanan pr_info("verifying all eraseblocks for 0xff\n"); 251bf60862aSArtem Bityutskiy for (i = 0; i < ebcnt; ++i) { 252bf60862aSArtem Bityutskiy if (bbt[i]) 253bf60862aSArtem Bityutskiy continue; 254bf60862aSArtem Bityutskiy err = verify_eraseblock_ff(i); 255bf60862aSArtem Bityutskiy if (err) 256bf60862aSArtem Bityutskiy return err; 257bf60862aSArtem Bityutskiy if (i % 256 == 0) 258cd66a2dfSVikram Narayanan pr_info("verified up to eraseblock %u\n", i); 2592a6a28e7SRichard Weinberger 2602a6a28e7SRichard Weinberger err = mtdtest_relax(); 2612a6a28e7SRichard Weinberger if (err) 2622a6a28e7SRichard Weinberger return err; 263bf60862aSArtem Bityutskiy } 264cd66a2dfSVikram Narayanan pr_info("verified %u eraseblocks\n", i); 265bf60862aSArtem Bityutskiy return 0; 266bf60862aSArtem Bityutskiy } 267bf60862aSArtem Bityutskiy 268bf60862aSArtem Bityutskiy static int __init mtd_subpagetest_init(void) 269bf60862aSArtem Bityutskiy { 270bf60862aSArtem Bityutskiy int err = 0; 271bf60862aSArtem Bityutskiy uint32_t i; 272bf60862aSArtem Bityutskiy uint64_t tmp; 273bf60862aSArtem Bityutskiy 274bf60862aSArtem Bityutskiy printk(KERN_INFO "\n"); 275bf60862aSArtem Bityutskiy printk(KERN_INFO "=================================================\n"); 2767406060eSWolfram Sang 2777406060eSWolfram Sang if (dev < 0) { 278064a7694SMasanari Iida pr_info("Please specify a valid mtd-device via module parameter\n"); 279cd66a2dfSVikram Narayanan pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); 2807406060eSWolfram Sang return -EINVAL; 2817406060eSWolfram Sang } 2827406060eSWolfram Sang 283cd66a2dfSVikram Narayanan pr_info("MTD device: %d\n", dev); 284bf60862aSArtem Bityutskiy 285bf60862aSArtem Bityutskiy mtd = get_mtd_device(NULL, dev); 286bf60862aSArtem Bityutskiy if (IS_ERR(mtd)) { 287bf60862aSArtem Bityutskiy err = PTR_ERR(mtd); 288cd66a2dfSVikram Narayanan pr_err("error: cannot get MTD device\n"); 289bf60862aSArtem Bityutskiy return err; 290bf60862aSArtem Bityutskiy } 291bf60862aSArtem Bityutskiy 292818b9739SHuang Shijie if (!mtd_type_is_nand(mtd)) { 293cd66a2dfSVikram Narayanan pr_info("this test requires NAND flash\n"); 294bf60862aSArtem Bityutskiy goto out; 295bf60862aSArtem Bityutskiy } 296bf60862aSArtem Bityutskiy 297bf60862aSArtem Bityutskiy subpgsize = mtd->writesize >> mtd->subpage_sft; 2987b7e905eSRoman Tereshonkov tmp = mtd->size; 2997b7e905eSRoman Tereshonkov do_div(tmp, mtd->erasesize); 3007b7e905eSRoman Tereshonkov ebcnt = tmp; 3017b7e905eSRoman Tereshonkov pgcnt = mtd->erasesize / mtd->writesize; 3027b7e905eSRoman Tereshonkov 303cd66a2dfSVikram Narayanan pr_info("MTD device size %llu, eraseblock size %u, " 304bf60862aSArtem Bityutskiy "page size %u, subpage size %u, count of eraseblocks %u, " 305bf60862aSArtem Bityutskiy "pages per eraseblock %u, OOB size %u\n", 306bf60862aSArtem Bityutskiy (unsigned long long)mtd->size, mtd->erasesize, 307bf60862aSArtem Bityutskiy mtd->writesize, subpgsize, ebcnt, pgcnt, mtd->oobsize); 308bf60862aSArtem Bityutskiy 309bf60862aSArtem Bityutskiy err = -ENOMEM; 310bf60862aSArtem Bityutskiy bufsize = subpgsize * 32; 311bf60862aSArtem Bityutskiy writebuf = kmalloc(bufsize, GFP_KERNEL); 31233777e66SBrian Norris if (!writebuf) 313bf60862aSArtem Bityutskiy goto out; 314bf60862aSArtem Bityutskiy readbuf = kmalloc(bufsize, GFP_KERNEL); 31533777e66SBrian Norris if (!readbuf) 316bf60862aSArtem Bityutskiy goto out; 317725cd71cSAkinobu Mita bbt = kzalloc(ebcnt, GFP_KERNEL); 318725cd71cSAkinobu Mita if (!bbt) 319725cd71cSAkinobu Mita goto out; 320bf60862aSArtem Bityutskiy 321725cd71cSAkinobu Mita err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt); 322bf60862aSArtem Bityutskiy if (err) 323bf60862aSArtem Bityutskiy goto out; 324bf60862aSArtem Bityutskiy 325725cd71cSAkinobu Mita err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); 326bf60862aSArtem Bityutskiy if (err) 327bf60862aSArtem Bityutskiy goto out; 328bf60862aSArtem Bityutskiy 329cd66a2dfSVikram Narayanan pr_info("writing whole device\n"); 330a312b78bSAkinobu Mita prandom_seed_state(&rnd_state, 1); 331bf60862aSArtem Bityutskiy for (i = 0; i < ebcnt; ++i) { 332bf60862aSArtem Bityutskiy if (bbt[i]) 333bf60862aSArtem Bityutskiy continue; 334bf60862aSArtem Bityutskiy err = write_eraseblock(i); 335bf60862aSArtem Bityutskiy if (unlikely(err)) 336bf60862aSArtem Bityutskiy goto out; 337bf60862aSArtem Bityutskiy if (i % 256 == 0) 338cd66a2dfSVikram Narayanan pr_info("written up to eraseblock %u\n", i); 3392a6a28e7SRichard Weinberger 3402a6a28e7SRichard Weinberger err = mtdtest_relax(); 3412a6a28e7SRichard Weinberger if (err) 3422a6a28e7SRichard Weinberger goto out; 343bf60862aSArtem Bityutskiy } 344cd66a2dfSVikram Narayanan pr_info("written %u eraseblocks\n", i); 345bf60862aSArtem Bityutskiy 346a312b78bSAkinobu Mita prandom_seed_state(&rnd_state, 1); 347cd66a2dfSVikram Narayanan pr_info("verifying all eraseblocks\n"); 348bf60862aSArtem Bityutskiy for (i = 0; i < ebcnt; ++i) { 349bf60862aSArtem Bityutskiy if (bbt[i]) 350bf60862aSArtem Bityutskiy continue; 351bf60862aSArtem Bityutskiy err = verify_eraseblock(i); 352bf60862aSArtem Bityutskiy if (unlikely(err)) 353bf60862aSArtem Bityutskiy goto out; 354bf60862aSArtem Bityutskiy if (i % 256 == 0) 355cd66a2dfSVikram Narayanan pr_info("verified up to eraseblock %u\n", i); 3562a6a28e7SRichard Weinberger 3572a6a28e7SRichard Weinberger err = mtdtest_relax(); 3582a6a28e7SRichard Weinberger if (err) 3592a6a28e7SRichard Weinberger goto out; 360bf60862aSArtem Bityutskiy } 361cd66a2dfSVikram Narayanan pr_info("verified %u eraseblocks\n", i); 362bf60862aSArtem Bityutskiy 363725cd71cSAkinobu Mita err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); 364bf60862aSArtem Bityutskiy if (err) 365bf60862aSArtem Bityutskiy goto out; 366bf60862aSArtem Bityutskiy 367bf60862aSArtem Bityutskiy err = verify_all_eraseblocks_ff(); 368bf60862aSArtem Bityutskiy if (err) 369bf60862aSArtem Bityutskiy goto out; 370bf60862aSArtem Bityutskiy 371bf60862aSArtem Bityutskiy /* Write all eraseblocks */ 372a312b78bSAkinobu Mita prandom_seed_state(&rnd_state, 3); 373cd66a2dfSVikram Narayanan pr_info("writing whole device\n"); 374bf60862aSArtem Bityutskiy for (i = 0; i < ebcnt; ++i) { 375bf60862aSArtem Bityutskiy if (bbt[i]) 376bf60862aSArtem Bityutskiy continue; 377bf60862aSArtem Bityutskiy err = write_eraseblock2(i); 378bf60862aSArtem Bityutskiy if (unlikely(err)) 379bf60862aSArtem Bityutskiy goto out; 380bf60862aSArtem Bityutskiy if (i % 256 == 0) 381cd66a2dfSVikram Narayanan pr_info("written up to eraseblock %u\n", i); 3822a6a28e7SRichard Weinberger 3832a6a28e7SRichard Weinberger err = mtdtest_relax(); 3842a6a28e7SRichard Weinberger if (err) 3852a6a28e7SRichard Weinberger goto out; 386bf60862aSArtem Bityutskiy } 387cd66a2dfSVikram Narayanan pr_info("written %u eraseblocks\n", i); 388bf60862aSArtem Bityutskiy 389bf60862aSArtem Bityutskiy /* Check all eraseblocks */ 390a312b78bSAkinobu Mita prandom_seed_state(&rnd_state, 3); 391cd66a2dfSVikram Narayanan pr_info("verifying all eraseblocks\n"); 392bf60862aSArtem Bityutskiy for (i = 0; i < ebcnt; ++i) { 393bf60862aSArtem Bityutskiy if (bbt[i]) 394bf60862aSArtem Bityutskiy continue; 395bf60862aSArtem Bityutskiy err = verify_eraseblock2(i); 396bf60862aSArtem Bityutskiy if (unlikely(err)) 397bf60862aSArtem Bityutskiy goto out; 398bf60862aSArtem Bityutskiy if (i % 256 == 0) 399cd66a2dfSVikram Narayanan pr_info("verified up to eraseblock %u\n", i); 4002a6a28e7SRichard Weinberger 4012a6a28e7SRichard Weinberger err = mtdtest_relax(); 4022a6a28e7SRichard Weinberger if (err) 4032a6a28e7SRichard Weinberger goto out; 404bf60862aSArtem Bityutskiy } 405cd66a2dfSVikram Narayanan pr_info("verified %u eraseblocks\n", i); 406bf60862aSArtem Bityutskiy 407725cd71cSAkinobu Mita err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); 408bf60862aSArtem Bityutskiy if (err) 409bf60862aSArtem Bityutskiy goto out; 410bf60862aSArtem Bityutskiy 411bf60862aSArtem Bityutskiy err = verify_all_eraseblocks_ff(); 412bf60862aSArtem Bityutskiy if (err) 413bf60862aSArtem Bityutskiy goto out; 414bf60862aSArtem Bityutskiy 415cd66a2dfSVikram Narayanan pr_info("finished with %d errors\n", errcnt); 416bf60862aSArtem Bityutskiy 417bf60862aSArtem Bityutskiy out: 418bf60862aSArtem Bityutskiy kfree(bbt); 419bf60862aSArtem Bityutskiy kfree(readbuf); 420bf60862aSArtem Bityutskiy kfree(writebuf); 421bf60862aSArtem Bityutskiy put_mtd_device(mtd); 422bf60862aSArtem Bityutskiy if (err) 423cd66a2dfSVikram Narayanan pr_info("error %d occurred\n", err); 424bf60862aSArtem Bityutskiy printk(KERN_INFO "=================================================\n"); 425bf60862aSArtem Bityutskiy return err; 426bf60862aSArtem Bityutskiy } 427bf60862aSArtem Bityutskiy module_init(mtd_subpagetest_init); 428bf60862aSArtem Bityutskiy 429bf60862aSArtem Bityutskiy static void __exit mtd_subpagetest_exit(void) 430bf60862aSArtem Bityutskiy { 431bf60862aSArtem Bityutskiy return; 432bf60862aSArtem Bityutskiy } 433bf60862aSArtem Bityutskiy module_exit(mtd_subpagetest_exit); 434bf60862aSArtem Bityutskiy 435bf60862aSArtem Bityutskiy MODULE_DESCRIPTION("Subpage test module"); 436bf60862aSArtem Bityutskiy MODULE_AUTHOR("Adrian Hunter"); 437bf60862aSArtem Bityutskiy MODULE_LICENSE("GPL"); 438